1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/private/base/SkSemaphore.h"
9
10 #include "include/private/base/SkFeatures.h" // IWYU pragma: keep
11
12 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
13 #include <dispatch/dispatch.h>
14
15 struct SkSemaphore::OSSemaphore {
16 dispatch_semaphore_t fSemaphore;
17
OSSemaphoreSkSemaphore::OSSemaphore18 OSSemaphore() { fSemaphore = dispatch_semaphore_create(0/*initial count*/); }
~OSSemaphoreSkSemaphore::OSSemaphore19 ~OSSemaphore() { dispatch_release(fSemaphore); }
20
signalSkSemaphore::OSSemaphore21 void signal(int n) { while (n --> 0) { dispatch_semaphore_signal(fSemaphore); } }
waitSkSemaphore::OSSemaphore22 void wait() { dispatch_semaphore_wait(fSemaphore, DISPATCH_TIME_FOREVER); }
23 };
24 #elif defined(SK_BUILD_FOR_WIN)
25 #include "src/base/SkLeanWindows.h"
26
27 struct SkSemaphore::OSSemaphore {
28 HANDLE fSemaphore;
29
OSSemaphoreSkSemaphore::OSSemaphore30 OSSemaphore() {
31 fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/,
32 0 /*initial count*/,
33 MAXLONG /*max count*/,
34 nullptr /*name, optional*/);
35 }
~OSSemaphoreSkSemaphore::OSSemaphore36 ~OSSemaphore() { CloseHandle(fSemaphore); }
37
signalSkSemaphore::OSSemaphore38 void signal(int n) {
39 ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/);
40 }
waitSkSemaphore::OSSemaphore41 void wait() { WaitForSingleObject(fSemaphore, INFINITE/*timeout in ms*/); }
42 };
43 #else
44 // It's important we test for Mach before this. This code will compile but not work there.
45 #include <errno.h>
46 #include <semaphore.h>
47 struct SkSemaphore::OSSemaphore {
48 sem_t fSemaphore;
49
OSSemaphoreSkSemaphore::OSSemaphore50 OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
~OSSemaphoreSkSemaphore::OSSemaphore51 ~OSSemaphore() { sem_destroy(&fSemaphore); }
52
signalSkSemaphore::OSSemaphore53 void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } }
waitSkSemaphore::OSSemaphore54 void wait() {
55 // Try until we're not interrupted.
56 while(sem_wait(&fSemaphore) == -1 && errno == EINTR);
57 }
58 };
59 #endif
60
61 ///////////////////////////////////////////////////////////////////////////////
62
~SkSemaphore()63 SkSemaphore::~SkSemaphore() {
64 delete fOSSemaphore;
65 }
66
osSignal(int n)67 void SkSemaphore::osSignal(int n) {
68 fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
69 fOSSemaphore->signal(n);
70 }
71
osWait()72 void SkSemaphore::osWait() {
73 fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
74 fOSSemaphore->wait();
75 }
76
try_wait()77 bool SkSemaphore::try_wait() {
78 int count = fCount.load(std::memory_order_relaxed);
79 if (count > 0) {
80 return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire);
81 }
82 return false;
83 }
84