| Index: include/private/SkSemaphore.h
|
| diff --git a/src/core/SkSemaphore.h b/include/private/SkSemaphore.h
|
| similarity index 62%
|
| rename from src/core/SkSemaphore.h
|
| rename to include/private/SkSemaphore.h
|
| index 5f4c2968a77aed4a061c2b8e4347bc7567d20813..b5b5ea5957bbc14ad070a1735e5f412aec6b66db 100644
|
| --- a/src/core/SkSemaphore.h
|
| +++ b/include/private/SkSemaphore.h
|
| @@ -10,6 +10,53 @@
|
|
|
| #include "SkTypes.h"
|
| #include "SkAtomics.h"
|
| +#include "../private/SkOncePtr.h"
|
| +
|
| +struct SkBaseSemaphore {
|
| +
|
| + // Increment the counter by 1.
|
| + // This is a specialization for supporting SkMutex.
|
| + void signal() {
|
| + // Since this fetches the value before the add, 0 indicates that this thread is running and
|
| + // no threads are waiting, -1 and below means that threads are waiting, but only signal 1
|
| + // thread to run.
|
| + if (sk_atomic_fetch_add(&fCount, 1, sk_memory_order_release) < 0) {
|
| + this->osSignal(1);
|
| + }
|
| + }
|
| +
|
| + // Increment the counter N times.
|
| + // Generally it's better to call signal(N) instead of signal() N times.
|
| + void signal(int N);
|
| +
|
| + // Decrement the counter by 1,
|
| + // then if the counter is <= 0, sleep this thread until the counter is > 0.
|
| + void wait() {
|
| + // Since this fetches the value before the subtract, zero and below means that there are no
|
| + // resources left, so the thread needs to wait.
|
| + if (sk_atomic_fetch_sub(&fCount, 1, sk_memory_order_acquire) <= 0) {
|
| + this->osWait();
|
| + }
|
| + }
|
| +
|
| + struct OSSemaphore;
|
| +
|
| + void osSignal(int n);
|
| + void osWait();
|
| + void deleteSemaphore();
|
| +
|
| + // This implementation follows the general strategy of
|
| + // 'A Lightweight Semaphore with Partial Spinning'
|
| + // found here
|
| + // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/
|
| + // That article (and entire blog) are very much worth reading.
|
| + //
|
| + // We wrap an OS-provided semaphore with a user-space atomic counter that
|
| + // lets us avoid interacting with the OS semaphore unless strictly required:
|
| + // moving the count from >0 to <=0 or vice-versa, i.e. sleeping or waking threads.
|
| + int fCount;
|
| + SkBaseOncePtr<OSSemaphore> fOSSemaphore;
|
| +};
|
|
|
| /**
|
| * SkSemaphore is a fast mostly-user-space semaphore.
|
| @@ -28,28 +75,12 @@ public:
|
| SkSemaphore();
|
| ~SkSemaphore();
|
|
|
| - // Increment the counter N times.
|
| - // Generally it's better to call signal(N) instead of signal() N times.
|
| - void signal(int N = 1);
|
| -
|
| - // Decrement the counter by 1,
|
| - // then if the counter is <= 0, sleep this thread until the counter is > 0.
|
| void wait();
|
|
|
| -private:
|
| - // This implementation follows the general strategy of
|
| - // 'A Lightweight Semaphore with Partial Spinning'
|
| - // found here
|
| - // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/
|
| - // That article (and entire blog) are very much worth reading.
|
| - //
|
| - // We wrap an OS-provided semaphore with a user-space atomic counter that
|
| - // lets us avoid interacting with the OS semaphore unless strictly required:
|
| - // moving the count from >0 to <=0 or vice-versa, i.e. sleeping or waking threads.
|
| - struct OSSemaphore;
|
| + void signal(int n = 1);
|
|
|
| - SkAtomic<int> fCount;
|
| - OSSemaphore* fOSSemaphore;
|
| +private:
|
| + SkBaseSemaphore fBaseSemaphore;
|
| };
|
|
|
| #endif//SkSemaphore_DEFINED
|
|
|