inline MachineThreads& wasmThreads() { static LazyNeverDestroyed<MachineThreads> threads; static std::once_flag once; std::call_once(once, [] { threads.construct(); }); return threads; }
FunctionOverrides& FunctionOverrides::overrides() { static LazyNeverDestroyed<FunctionOverrides> overrides; static std::once_flag initializeListFlag; std::call_once(initializeListFlag, [] { const char* overridesFileName = Options::functionOverrides(); overrides.construct(overridesFileName); }); return overrides; }
const Extensions3DCache& Extensions3DCache::singleton() { static std::once_flag onceFlag; static LazyNeverDestroyed<Extensions3DCache> extensions3DCache; std::call_once(onceFlag, []{ extensions3DCache.construct(); }); return extensions3DCache; }
FunctionWhitelist& FunctionWhitelist::ensureGlobalWhitelist() { static LazyNeverDestroyed<FunctionWhitelist> functionWhitelist; static std::once_flag initializeWhitelistFlag; std::call_once(initializeWhitelistFlag, [] { const char* functionWhitelistFile = Options::dfgWhitelist(); functionWhitelist.construct(functionWhitelistFile); }); return functionWhitelist; }
DefaultSharedWorkerRepository& DefaultSharedWorkerRepository::instance() { static std::once_flag onceFlag; static LazyNeverDestroyed<DefaultSharedWorkerRepository> instance; std::call_once(onceFlag, []{ instance.construct(); }); return instance; }
NetworkStateNotifier& networkStateNotifier() { static std::once_flag onceFlag; static LazyNeverDestroyed<NetworkStateNotifier> networkStateNotifier; std::call_once(onceFlag, []{ networkStateNotifier.construct(); }); return networkStateNotifier; }
// FIXME: move all guid-related functions to a DatabaseVersionTracker class. static std::mutex& guidMutex() { static std::once_flag onceFlag; static LazyNeverDestroyed<std::mutex> mutex; std::call_once(onceFlag, []{ mutex.construct(); }); return mutex; }
// Because of driver bugs, exiting the program when there are active pbuffers // can crash the X server (this has been observed with the official Nvidia drivers). // We need to ensure that we clean everything up on exit. There are several reasons // that GraphicsContext3Ds will still be alive at exit, including user error (memory // leaks) and the page cache. In any case, we don't want the X server to crash. static HashSet<GLContextGLX*>& activeContexts() { static std::once_flag onceFlag; static LazyNeverDestroyed<HashSet<GLContextGLX*>> contexts; std::call_once(onceFlag, [] { contexts.construct(); std::atexit([] { for (auto* context : activeContexts()) context->clear(); }); }); return contexts; }
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; }); }