int DeviceManagerThread::Run() { ThreadCommand::PopBuffer command; SetThreadName("OVR::DeviceManagerThread"); LogText("OVR::DeviceManagerThread - running (ThreadId=%p).\n", GetThreadId()); while(!IsExiting()) { // PopCommand will reset event on empty queue. if (PopCommand(&command)) { command.Execute(); } else { bool commands = 0; do { int n = poll(&PollFds[0], PollFds.GetSize(), -1); for (int i = 0; i < PollFds.GetSize(); i++) { if (PollFds[i].revents & POLLERR) { OVR_DEBUG_LOG(("poll: error on [%d]: %d", i, PollFds[i].fd)); } else if (PollFds[i].revents & POLLIN) { if (FdNotifiers[i]) FdNotifiers[i]->OnEvent(i, PollFds[i].fd); else if (i == 0) // command { char dummy[128]; read(PollFds[i].fd, dummy, 128); commands = 1; } } if (PollFds[i].revents & POLLHUP) PollFds[i].events = 0; if (PollFds[i].revents != 0) { n--; if (n == 0) break; } } } while (PollFds.GetSize() > 0 && !commands); } } LogText("OVR::DeviceManagerThread - exiting (ThreadId=%p).\n", GetThreadId()); return 0; }
int DeviceManagerThread::Run() { ThreadCommand::PopBuffer command; SetThreadName("OVR::DeviceManagerThread"); LogText("OVR::DeviceManagerThread - running (ThreadId=%p).\n", GetThreadId()); // Signal to the parent thread that initialization has finished. StartupEvent.SetEvent(); while(!IsExiting()) { // PopCommand will reset event on empty queue. if (PopCommand(&command)) { command.Execute(); } else { bool commands = 0; do { int waitMs = -1; // If devices have time-dependent logic registered, get the longest wait // allowed based on current ticks. if (!TicksNotifiers.IsEmpty()) { UInt64 ticksMks = Timer::GetTicks(); int waitAllowed; for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++) { waitAllowed = (int)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs); if (waitAllowed < waitMs) waitMs = waitAllowed; } } // wait until there is data available on one of the devices or the timeout expires int n = poll(&PollFds[0], PollFds.GetSize(), waitMs); if (n > 0) { // Iterate backwards through the list so the ordering will not be // affected if the called object gets removed during the callback // Also, the HID data streams are located toward the back of the list // and servicing them first will allow a disconnect to be handled // and cleaned directly at the device first instead of the general HID monitor for (int i=PollFds.GetSize()-1; i>=0; i--) { if (PollFds[i].revents & POLLERR) { OVR_DEBUG_LOG(("poll: error on [%d]: %d", i, PollFds[i].fd)); } else if (PollFds[i].revents & POLLIN) { if (FdNotifiers[i]) FdNotifiers[i]->OnEvent(i, PollFds[i].fd); else if (i == 0) // command { char dummy[128]; read(PollFds[i].fd, dummy, 128); commands = 1; } } if (PollFds[i].revents & POLLHUP) PollFds[i].events = 0; if (PollFds[i].revents != 0) { n--; if (n == 0) break; } } } } while (PollFds.GetSize() > 0 && !commands); } } LogText("OVR::DeviceManagerThread - exiting (ThreadId=%p).\n", GetThreadId()); return 0; }
int DeviceManagerThread::Run() { SetThreadName("OVR::DeviceManagerThread"); LogText("OVR::DeviceManagerThread - running (ThreadId=0x%p).\n", GetThreadId()); // Store out the run loop ref. RunLoop = CFRunLoopGetCurrent(); // Create a 'source' to enable us to signal the run loop to process the command queue. CFRunLoopSourceContext sourceContext; memset(&sourceContext, 0, sizeof(sourceContext)); sourceContext.version = 0; sourceContext.info = this; sourceContext.perform = &staticCommandQueueSourceCallback; CommandQueueSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 , &sourceContext); CFRunLoopAddSource(RunLoop, CommandQueueSource, kCFRunLoopDefaultMode); // Signal to the parent thread that initialization has finished. StartupEvent.SetEvent(); ThreadCommand::PopBuffer command; while(!IsExiting()) { // PopCommand will reset event on empty queue. if (PopCommand(&command)) { command.Execute(); } else { SInt32 exitReason = 0; do { UInt32 waitMs = INT_MAX; // If devices have time-dependent logic registered, get the longest wait // allowed based on current ticks. if (!TicksNotifiers.IsEmpty()) { UInt64 ticksMks = Timer::GetTicks(); UInt32 waitAllowed; for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++) { waitAllowed = (UInt32)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs); if (waitAllowed < waitMs) waitMs = waitAllowed; } } // Enter blocking run loop. We may continue until we timeout in which // case it's time to service the ticks. Or if commands arrive in the command // queue then the source callback will call 'CFRunLoopStop' causing this // to return. CFTimeInterval blockInterval = 0.001 * (double) waitMs; exitReason = CFRunLoopRunInMode(kCFRunLoopDefaultMode, blockInterval, false); if (exitReason == kCFRunLoopRunFinished) { // Maybe this will occur during shutdown? break; } else if (exitReason == kCFRunLoopRunStopped ) { // Commands need processing or we're being shutdown. break; } else if (exitReason == kCFRunLoopRunTimedOut) { // Timed out so that we can service our ticks callbacks. continue; } else if (exitReason == kCFRunLoopRunHandledSource) { // Should never occur since the last param when we call // 'CFRunLoopRunInMode' is false. OVR_ASSERT(false); break; } else { OVR_ASSERT_LOG(false, ("CFRunLoopRunInMode returned unexpected code")); break; } } while(true); } } CFRunLoopRemoveSource(RunLoop, CommandQueueSource, kCFRunLoopDefaultMode); CFRelease(CommandQueueSource); LogText("OVR::DeviceManagerThread - exiting (ThreadId=0x%p).\n", GetThreadId()); return 0; }