| 140 | } |
| 141 | |
| 142 | void ThreadedDispatchQueue::handler(ThreadedDispatchQueue* dispatchQueue, const Ref<TaskQueue>& taskQueue) { |
| 143 | current = dispatchQueue; |
| 144 | |
| 145 | while (!taskQueue->isDisposed()) { |
| 146 | #if TARGET_OS_IPHONE |
| 147 | auto pool = objc_autoreleasePoolPush(); |
| 148 | |
| 149 | // On Apple systems, every thread (even C++ threads) come with a CFRunLoop attached. |
| 150 | // Some system libraries, like JavaScriptCore pushes timers onto the CFRunLoop. |
| 151 | // We therefore need to flush manually our CFRunLoop as well as our TaskQueue. |
| 152 | |
| 153 | auto nextFireDate = CFRunLoopGetNextTimerFireDate(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); |
| 154 | if (nextFireDate == 0.0) { |
| 155 | // Nothing in the run loop, we can loop semi-indefinitely. |
| 156 | taskQueue->runNextTask(std::chrono::steady_clock::now() + std::chrono::seconds(10000000)); |
| 157 | } else { |
| 158 | auto timeToWaitSeconds = std::max(nextFireDate - CFAbsoluteTimeGetCurrent(), 0.0); |
| 159 | // We have something in the runloop, we need to cap our wait to the next task in the CFRunLoop. |
| 160 | taskQueue->runNextTask(std::chrono::steady_clock::now() + |
| 161 | std::chrono::nanoseconds(static_cast<long long>(timeToWaitSeconds * 1000000000))); |
| 162 | } |
| 163 | |
| 164 | // Flush the CFRunLoop |
| 165 | while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) { |
| 166 | } |
| 167 | |
| 168 | objc_autoreleasePoolPop(pool); |
| 169 | #else |
| 170 | taskQueue->runNextTask(std::chrono::steady_clock::now() + std::chrono::seconds(100000)); |
| 171 | #endif |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | bool ThreadedDispatchQueue::isCurrent() const { |
| 176 | return this == getCurrent(); |
nothing calls this directly
no test coverage detected