diff options
author | 2014-08-06 06:55:12 -0700 | |
---|---|---|
committer | 2014-08-06 06:55:12 -0700 | |
commit | 847092c88be671c06bdf24aa02b5a66e7a593a15 (patch) | |
tree | 60909e9c901e0310d1e1379d8c8193fefd38cad3 /include/utils | |
parent | 70f25c1a3f5677ff582399e138a82653a5bfe7c8 (diff) |
SkThreadPool and co. are not public.
BUG=skia:
R=reed@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/444583006
Diffstat (limited to 'include/utils')
-rw-r--r-- | include/utils/SkCondVar.h | 78 | ||||
-rw-r--r-- | include/utils/SkRunnable.h | 25 | ||||
-rw-r--r-- | include/utils/SkThreadPool.h | 221 |
3 files changed, 0 insertions, 324 deletions
diff --git a/include/utils/SkCondVar.h b/include/utils/SkCondVar.h deleted file mode 100644 index 6f18e1a651..0000000000 --- a/include/utils/SkCondVar.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkCondVar_DEFINED -#define SkCondVar_DEFINED - -/** - * Import any thread model setting from configuration files. - */ -#include "SkTypes.h" - -#ifdef SK_USE_POSIX_THREADS -#include <pthread.h> -#elif defined(SK_BUILD_FOR_WIN32) -#include <windows.h> -#else -/** - * Warn if the implementation of this class is empty, i.e. thread safety is not working. - */ -#warning "Thread safety class SkCondVar has no implementation!" -#endif - -/** - * Condition variable for blocking access to shared data from other threads and - * controlling which threads are awake. - * - * Currently only supported on platforms with posix threads and Windows Vista and - * above. - */ -class SkCondVar { -public: - SkCondVar(); - ~SkCondVar(); - - /** - * Lock a mutex. Must be done before calling the other functions on this object. - */ - void lock(); - - /** - * Unlock the mutex. - */ - void unlock(); - - /** - * Pause the calling thread. Will be awoken when signal() or broadcast() is called. - * Must be called while lock() is held (but gives it up while waiting). Once awoken, - * the calling thread will hold the lock once again. - */ - void wait(); - - /** - * Wake one thread waiting on this condition. Must be called while lock() - * is held. - */ - void signal(); - - /** - * Wake all threads waiting on this condition. Must be called while lock() - * is held. - */ - void broadcast(); - -private: -#ifdef SK_USE_POSIX_THREADS - pthread_mutex_t fMutex; - pthread_cond_t fCond; -#elif defined(SK_BUILD_FOR_WIN32) - CRITICAL_SECTION fCriticalSection; - CONDITION_VARIABLE fCondition; -#endif -}; - -#endif diff --git a/include/utils/SkRunnable.h b/include/utils/SkRunnable.h deleted file mode 100644 index 5acf4dbc61..0000000000 --- a/include/utils/SkRunnable.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkRunnable_DEFINED -#define SkRunnable_DEFINED - -template <typename T> -struct SkTRunnable { - virtual ~SkTRunnable() {}; - virtual void run(T&) = 0; -}; - -template <> -struct SkTRunnable<void> { - virtual ~SkTRunnable() {}; - virtual void run() = 0; -}; - -typedef SkTRunnable<void> SkRunnable; - -#endif diff --git a/include/utils/SkThreadPool.h b/include/utils/SkThreadPool.h deleted file mode 100644 index c99c5c4188..0000000000 --- a/include/utils/SkThreadPool.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkThreadPool_DEFINED -#define SkThreadPool_DEFINED - -#include "SkCondVar.h" -#include "SkRunnable.h" -#include "SkTDArray.h" -#include "SkTInternalLList.h" -#include "SkThreadUtils.h" -#include "SkTypes.h" - -#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_ANDROID) -# include <unistd.h> -#endif - -// Returns the number of cores on this machine. -static inline int num_cores() { -#if defined(SK_BUILD_FOR_WIN32) - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; -#elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_ANDROID) - return (int) sysconf(_SC_NPROCESSORS_ONLN); -#else - return 1; -#endif -} - -template <typename T> -class SkTThreadPool { -public: - /** - * Create a threadpool with count threads, or one thread per core if kThreadPerCore. - */ - static const int kThreadPerCore = -1; - explicit SkTThreadPool(int count); - ~SkTThreadPool(); - - /** - * Queues up an SkRunnable to run when a thread is available, or synchronously if count is 0. - * Does not take ownership. NULL is a safe no-op. If T is not void, the runnable will be passed - * a reference to a T on the thread's local stack. - */ - void add(SkTRunnable<T>*); - - /** - * Same as add, but adds the runnable as the very next to run rather than enqueueing it. - */ - void addNext(SkTRunnable<T>*); - - /** - * Block until all added SkRunnables have completed. Once called, calling add() is undefined. - */ - void wait(); - - private: - struct LinkedRunnable { - SkTRunnable<T>* fRunnable; // Unowned. - SK_DECLARE_INTERNAL_LLIST_INTERFACE(LinkedRunnable); - }; - - enum State { - kRunning_State, // Normal case. We've been constructed and no one has called wait(). - kWaiting_State, // wait has been called, but there still might be work to do or being done. - kHalting_State, // There's no work to do and no thread is busy. All threads can shut down. - }; - - void addSomewhere(SkTRunnable<T>* r, - void (SkTInternalLList<LinkedRunnable>::*)(LinkedRunnable*)); - - SkTInternalLList<LinkedRunnable> fQueue; - SkCondVar fReady; - SkTDArray<SkThread*> fThreads; - State fState; - int fBusyThreads; - - static void Loop(void*); // Static because we pass in this. -}; - -template <typename T> -SkTThreadPool<T>::SkTThreadPool(int count) : fState(kRunning_State), fBusyThreads(0) { - if (count < 0) { - count = num_cores(); - } - // Create count threads, all running SkTThreadPool::Loop. - for (int i = 0; i < count; i++) { - SkThread* thread = SkNEW_ARGS(SkThread, (&SkTThreadPool::Loop, this)); - *fThreads.append() = thread; - thread->start(); - } -} - -template <typename T> -SkTThreadPool<T>::~SkTThreadPool() { - if (kRunning_State == fState) { - this->wait(); - } -} - -namespace SkThreadPoolPrivate { - -template <typename T> -struct ThreadLocal { - void run(SkTRunnable<T>* r) { r->run(data); } - T data; -}; - -template <> -struct ThreadLocal<void> { - void run(SkTRunnable<void>* r) { r->run(); } -}; - -} // namespace SkThreadPoolPrivate - -template <typename T> -void SkTThreadPool<T>::addSomewhere(SkTRunnable<T>* r, - void (SkTInternalLList<LinkedRunnable>::* f)(LinkedRunnable*)) { - if (r == NULL) { - return; - } - - if (fThreads.isEmpty()) { - SkThreadPoolPrivate::ThreadLocal<T> threadLocal; - threadLocal.run(r); - return; - } - - LinkedRunnable* linkedRunnable = SkNEW(LinkedRunnable); - linkedRunnable->fRunnable = r; - fReady.lock(); - SkASSERT(fState != kHalting_State); // Shouldn't be able to add work when we're halting. - (fQueue.*f)(linkedRunnable); - fReady.signal(); - fReady.unlock(); -} - -template <typename T> -void SkTThreadPool<T>::add(SkTRunnable<T>* r) { - this->addSomewhere(r, &SkTInternalLList<LinkedRunnable>::addToTail); -} - -template <typename T> -void SkTThreadPool<T>::addNext(SkTRunnable<T>* r) { - this->addSomewhere(r, &SkTInternalLList<LinkedRunnable>::addToHead); -} - - -template <typename T> -void SkTThreadPool<T>::wait() { - fReady.lock(); - fState = kWaiting_State; - fReady.broadcast(); - fReady.unlock(); - - // Wait for all threads to stop. - for (int i = 0; i < fThreads.count(); i++) { - fThreads[i]->join(); - SkDELETE(fThreads[i]); - } - SkASSERT(fQueue.isEmpty()); -} - -template <typename T> -/*static*/ void SkTThreadPool<T>::Loop(void* arg) { - // The SkTThreadPool passes itself as arg to each thread as they're created. - SkTThreadPool<T>* pool = static_cast<SkTThreadPool<T>*>(arg); - SkThreadPoolPrivate::ThreadLocal<T> threadLocal; - - while (true) { - // We have to be holding the lock to read the queue and to call wait. - pool->fReady.lock(); - while(pool->fQueue.isEmpty()) { - // Does the client want to stop and are all the threads ready to stop? - // If so, we move into the halting state, and whack all the threads so they notice. - if (kWaiting_State == pool->fState && pool->fBusyThreads == 0) { - pool->fState = kHalting_State; - pool->fReady.broadcast(); - } - // Any time we find ourselves in the halting state, it's quitting time. - if (kHalting_State == pool->fState) { - pool->fReady.unlock(); - return; - } - // wait yields the lock while waiting, but will have it again when awoken. - pool->fReady.wait(); - } - // We've got the lock back here, no matter if we ran wait or not. - - // The queue is not empty, so we have something to run. Claim it. - LinkedRunnable* r = pool->fQueue.head(); - - pool->fQueue.remove(r); - - // Having claimed our SkRunnable, we now give up the lock while we run it. - // Otherwise, we'd only ever do work on one thread at a time, which rather - // defeats the point of this code. - pool->fBusyThreads++; - pool->fReady.unlock(); - - // OK, now really do the work. - threadLocal.run(r->fRunnable); - SkDELETE(r); - - // Let everyone know we're not busy. - pool->fReady.lock(); - pool->fBusyThreads--; - pool->fReady.unlock(); - } - - SkASSERT(false); // Unreachable. The only exit happens when pool->fState is kHalting_State. -} - -typedef SkTThreadPool<void> SkThreadPool; - -#endif |