void ThreadPool::run() { for (uint8 x=0; x<m_uiCount; x++) { ThreadPoolThread *thread = new ThreadPoolThread(this, false); thread->onCompleteEvent += delegate(this, &ThreadPool::onThreadComplete); m_vThreadList.push_back( thread ); thread->start(); } while (!isStopped()) { doPause(); removedForced(); uint32 runTaskCount = activeThreads(); if (runTaskCount < m_uiCount) startNewTasks(); runTaskCount = activeThreads(); if ((runTaskCount == m_uiCount || m_vTaskList.empty()) && !isStopped()) m_WaitCondition.wait(); } }
void ThreadPool::purgeTasks() { { m_TaskMutex.lock(); m_ThreadMutex.readLock(); for (size_t x=0; x<m_vThreadList.size(); x++) { m_vThreadList[x]->stopTask(); } m_ThreadMutex.readUnlock(); m_ForcedMutex.writeLock(); for (size_t x=0; x<m_vForcedList.size(); x++) { m_vForcedList[x]->stop(); m_vForcedList[x]->onCompleteEvent -= delegate(this, &ThreadPool::onThreadComplete); } safe_delete(m_vForcedList); m_ForcedMutex.writeUnlock(); safe_delete(m_vTaskList); m_TaskMutex.unlock(); } while (activeThreads() > 0) gcSleep(50); }
void WorkQueue::concurrentApply(size_t iterations, WTF::Function<void (size_t index)>&& function) { if (!iterations) return; if (iterations == 1) { function(0); return; } class ThreadPool { public: ThreadPool() { // We don't need a thread for the current core. unsigned threadCount = numberOfProcessorCores() - 1; m_workers.reserveInitialCapacity(threadCount); for (unsigned i = 0; i < threadCount; ++i) { m_workers.append(Thread::create("ThreadPool Worker", [this] { threadBody(); })); } } size_t workerCount() const { return m_workers.size(); } void dispatch(const WTF::Function<void ()>* function) { LockHolder holder(m_lock); m_queue.append(function); m_condition.notifyOne(); } private: NO_RETURN void threadBody() { while (true) { const WTF::Function<void ()>* function; { LockHolder holder(m_lock); m_condition.wait(m_lock, [this] { return !m_queue.isEmpty(); }); function = m_queue.takeFirst(); } (*function)(); } } Lock m_lock; Condition m_condition; Deque<const WTF::Function<void ()>*> m_queue; Vector<Ref<Thread>> m_workers; }; static LazyNeverDestroyed<ThreadPool> threadPool; static std::once_flag onceFlag; std::call_once(onceFlag, [] { threadPool.construct(); }); // Cap the worker count to the number of iterations (excluding this thread) const size_t workerCount = std::min(iterations - 1, threadPool->workerCount()); std::atomic<size_t> currentIndex(0); std::atomic<size_t> activeThreads(workerCount + 1); Condition condition; Lock lock; WTF::Function<void ()> applier = [&, function = WTFMove(function)] { size_t index; // Call the function for as long as there are iterations left. while ((index = currentIndex++) < iterations) function(index); // If there are no active threads left, signal the caller. if (!--activeThreads) { LockHolder holder(lock); condition.notifyOne(); } }; for (size_t i = 0; i < workerCount; ++i) threadPool->dispatch(&applier); applier(); LockHolder holder(lock); condition.wait(lock, [&] { return !activeThreads; }); }