bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag) { bool result = false; ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue(); if (GetManagerImpl()->GetThreadId() != OVR::GetCurrentThreadId()) { if (!waitFlag) { return queue->PushCall(this, &LatencyTestDeviceImpl::setConfiguration, configuration); } if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setConfiguration, &result, configuration)) { return false; } } else return setConfiguration(configuration); return result; }
void DeviceCommon::DeviceRelease() { while(1) { UInt32 refCount = RefCount; OVR_ASSERT(refCount > 0); if (refCount == 1) { DeviceManagerImpl* manager = pCreateDesc->GetManagerImpl(); ThreadCommandQueue* queue = manager->GetThreadQueue(); // Enqueue ReleaseDevice for {1 -> 0} transition with no wait. // We pass our reference ownership into the queue to destroy. // It's in theory possible for another thread to re-steal our device reference, // but that is checked for atomically in DeviceManagerImpl::ReleaseDevice. if (!queue->PushCall(manager, &DeviceManagerImpl::ReleaseDevice_MgrThread, pCreateDesc->pDevice)) { // PushCall shouldn't fail because background thread runs while manager is // alive and we are holding Manager alive through pParent chain. OVR_ASSERT(false); } // Warning! At his point everything, including manager, may be dead. break; } else if (RefCount.CompareAndSet_NoSync(refCount, refCount-1)) { break; } } }
bool LatencyTestDeviceImpl::GetConfiguration(OVR::LatencyTestConfiguration* configuration) { bool result = false; ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue(); if (!pQueue->PushCallAndWaitResult(this, &LatencyTestDeviceImpl::getConfiguration, &result, configuration)) return false; return result; }
bool LatencyTestDeviceImpl::SetDisplay(const OVR::LatencyTestDisplay& display, bool waitFlag) { bool result = false; ThreadCommandQueue * queue = GetManagerImpl()->GetThreadQueue(); if (!waitFlag) { return queue->PushCall(this, &LatencyTestDeviceImpl::setDisplay, display); } if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setDisplay, &result, display)) { return false; } return result; }
bool LatencyTestDeviceImpl::SetStartTest(const Color& targetColor, bool waitFlag) { bool result = false; ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue(); if (!waitFlag) { return queue->PushCall(this, &LatencyTestDeviceImpl::setStartTest, targetColor); } if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setStartTest, &result, targetColor)) { return false; } return result; }
bool ThreadCommandQueueImpl::PushCommand(const ThreadCommand& command) { ThreadCommand::NotifyEvent* completeEvent = 0; ThreadCommand::NotifyEvent* queueAvailableEvent = 0; // Repeat writing command into buffer until it is available. do { { // Lock Scope Lock::Locker lock(&QueueLock); if (queueAvailableEvent) { FreeNotifyEvent_NTS(queueAvailableEvent); queueAvailableEvent = 0; } // Don't allow any commands after PushExitCommand() is called. if (ExitEnqueued && !command.ExitFlag) return false; bool bufferWasEmpty = CommandBuffer.IsEmpty(); UByte* buffer = CommandBuffer.Write(command.GetSize()); if (buffer) { ThreadCommand* c = command.CopyConstruct(buffer); if (c->NeedsWait()) completeEvent = c->pEvent = AllocNotifyEvent_NTS(); // Signal-waker consumer when we add data to buffer. if (bufferWasEmpty) pQueue->OnPushNonEmpty_Locked(); break; } queueAvailableEvent = AllocNotifyEvent_NTS(); BlockedProducers.PushBack(queueAvailableEvent); } // Lock Scope queueAvailableEvent->Wait(); } while(1); // Command was enqueued, wait if necessary. if (completeEvent) { completeEvent->Wait(); Lock::Locker lock(&QueueLock); FreeNotifyEvent_NTS(completeEvent); } return true; }
// Pops the next command from the thread queue, if any is available. bool ThreadCommandQueueImpl::PopCommand(ThreadCommand::PopBuffer* popBuffer) { Lock::Locker lock(&QueueLock); UByte* buffer = CommandBuffer.ReadBegin(); if (!buffer) { // Notify thread while in lock scope, enabling initialization of wait. pQueue->OnPopEmpty_Locked(); return false; } popBuffer->InitFromBuffer(buffer); CommandBuffer.ReadEnd(popBuffer->GetSize()); if (!BlockedProducers.IsEmpty()) { ThreadCommand::NotifyEvent* queueAvailableEvent = BlockedProducers.GetFirst(); queueAvailableEvent->RemoveNode(); queueAvailableEvent->PulseEvent(); // Event is freed later by waiter. } return true; }