MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const ModePredicate& predicate) { ASSERT(context); ASSERT(context->thread()); ASSERT(context->thread()->threadID() == currentThread()); double absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<RefPtr<Task> >::infiniteTime(); RefPtr<Task> task; MessageQueueWaitResult result = m_messageQueue.waitForMessageFilteredWithTimeout(task, predicate, absoluteTime); // If the context is closing, don't dispatch any further tasks (per section 4.1.1 of the Web Workers spec). if (context->isClosing()) return result; switch (result) { case MessageQueueTerminated: break; case MessageQueueMessageReceived: task->performTask(context); break; case MessageQueueTimeout: m_sharedTimer->fire(); break; } return result; }
MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, const ModePredicate& predicate, WaitMode waitMode) { ASSERT(context); ASSERT(context->thread().threadID() == currentThread()); double absoluteTime = 0.0; if (waitMode == WaitForMessage) absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime(); MessageQueueWaitResult result; auto task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime); // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec). However, there may be implementation cleanup tasks in the queue, so keep running through it. switch (result) { case MessageQueueTerminated: break; case MessageQueueMessageReceived: task->performTask(*this, context); break; case MessageQueueTimeout: if (!context->isClosing()) m_sharedTimer->fire(); break; } return result; }
MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, const ModePredicate& predicate, WaitMode waitMode) { ASSERT(context); ASSERT(context->thread()); ASSERT(context->thread()->isCurrentThread()); bool nextTimeoutEventIsIdleWatchdog; MessageQueueWaitResult result; OwnPtr<WorkerRunLoop::Task> task; do { double absoluteTime = 0.0; nextTimeoutEventIsIdleWatchdog = false; if (waitMode == WaitForMessage) { absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime(); // Do a script engine idle notification if the next event is distant enough. const double kMinIdleTimespan = 0.3; // seconds if (m_messageQueue.isEmpty() && absoluteTime > currentTime() + kMinIdleTimespan) { bool hasMoreWork = !context->idleNotification(); if (hasMoreWork) { // Schedule a watchdog, so if there are no events within a particular time interval // idle notifications won't stop firing. const double kWatchdogInterval = 3; // seconds double nextWatchdogTime = currentTime() + kWatchdogInterval; if (absoluteTime > nextWatchdogTime) { absoluteTime = nextWatchdogTime; nextTimeoutEventIsIdleWatchdog = true; } } } } task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime); } while (result == MessageQueueTimeout && nextTimeoutEventIsIdleWatchdog); // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec). // However, there may be implementation cleanup tasks in the queue, so keep running through it. switch (result) { case MessageQueueTerminated: break; case MessageQueueMessageReceived: InspectorInstrumentation::willProcessTask(context); task->performTask(*this, context); InspectorInstrumentation::didProcessTask(context); break; case MessageQueueTimeout: if (!context->isClosing()) m_sharedTimer->fire(); break; } return result; }
MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerGlobalScope* context, const ModePredicate& predicate, WaitMode waitMode) { ASSERT(context); ASSERT(context->thread().threadID() == currentThread()); #if PLATFORM(GTK) || PLATFORM(WPE) GMainContext* mainContext = g_main_context_get_thread_default(); if (g_main_context_pending(mainContext)) g_main_context_iteration(mainContext, FALSE); #endif double deadline = MessageQueue<Task>::infiniteTime(); #if USE(CF) CFAbsoluteTime nextCFRunLoopTimerFireDate = CFRunLoopGetNextTimerFireDate(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); double timeUntilNextCFRunLoopTimerInSeconds = nextCFRunLoopTimerFireDate - CFAbsoluteTimeGetCurrent(); deadline = currentTime() + std::max(0.0, timeUntilNextCFRunLoopTimerInSeconds); #endif double absoluteTime = 0.0; if (waitMode == WaitForMessage) { if (predicate.isDefaultMode() && m_sharedTimer->isActive()) absoluteTime = std::min(deadline, m_sharedTimer->fireTime()); else absoluteTime = deadline; } MessageQueueWaitResult result; auto task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime); // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec). However, there may be implementation cleanup tasks in the queue, so keep running through it. switch (result) { case MessageQueueTerminated: break; case MessageQueueMessageReceived: task->performTask(*this, context); break; case MessageQueueTimeout: if (!context->isClosing()) m_sharedTimer->fire(); #if USE(CF) if (nextCFRunLoopTimerFireDate <= CFAbsoluteTimeGetCurrent()) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, /*returnAfterSourceHandled*/ false); #endif break; } return result; }