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 "../private/SkLeanWindows.h"
9 #include "../private/SkSemaphore.h"
10
11 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
12 #include <mach/mach.h>
13 struct SkBaseSemaphore::OSSemaphore {
14 semaphore_t fSemaphore;
15
OSSemaphoreSkBaseSemaphore::OSSemaphore16 OSSemaphore() {
17 semaphore_create(mach_task_self(), &fSemaphore, SYNC_POLICY_LIFO, 0/*initial count*/);
18 }
~OSSemaphoreSkBaseSemaphore::OSSemaphore19 ~OSSemaphore() { semaphore_destroy(mach_task_self(), fSemaphore); }
20
signalSkBaseSemaphore::OSSemaphore21 void signal(int n) { while (n --> 0) { semaphore_signal(fSemaphore); } }
waitSkBaseSemaphore::OSSemaphore22 void wait() { semaphore_wait(fSemaphore); }
23 };
24 #elif defined(SK_BUILD_FOR_WIN32)
25 struct SkBaseSemaphore::OSSemaphore {
26 HANDLE fSemaphore;
27
OSSemaphoreSkBaseSemaphore::OSSemaphore28 OSSemaphore() {
29 fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/,
30 0 /*initial count*/,
31 MAXLONG /*max count*/,
32 nullptr /*name, optional*/);
33 }
~OSSemaphoreSkBaseSemaphore::OSSemaphore34 ~OSSemaphore() { CloseHandle(fSemaphore); }
35
signalSkBaseSemaphore::OSSemaphore36 void signal(int n) {
37 ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/);
38 }
waitSkBaseSemaphore::OSSemaphore39 void wait() { WaitForSingleObject(fSemaphore, INFINITE/*timeout in ms*/); }
40 };
41 #else
42 // It's important we test for Mach before this. This code will compile but not work there.
43 #include <errno.h>
44 #include <semaphore.h>
45 struct SkBaseSemaphore::OSSemaphore {
46 sem_t fSemaphore;
47
OSSemaphoreSkBaseSemaphore::OSSemaphore48 OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
~OSSemaphoreSkBaseSemaphore::OSSemaphore49 ~OSSemaphore() { sem_destroy(&fSemaphore); }
50
signalSkBaseSemaphore::OSSemaphore51 void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } }
waitSkBaseSemaphore::OSSemaphore52 void wait() {
53 // Try until we're not interrupted.
54 while(sem_wait(&fSemaphore) == -1 && errno == EINTR);
55 }
56 };
57 #endif
58
59 ///////////////////////////////////////////////////////////////////////////////
60
osSignal(int n)61 void SkBaseSemaphore::osSignal(int n) {
62 fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
63 fOSSemaphore->signal(n);
64 }
65
osWait()66 void SkBaseSemaphore::osWait() {
67 fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
68 fOSSemaphore->wait();
69 }
70
cleanup()71 void SkBaseSemaphore::cleanup() {
72 delete fOSSemaphore;
73 }
74
try_wait()75 bool SkBaseSemaphore::try_wait() {
76 int count = fCount.load(std::memory_order_relaxed);
77 if (count > 0) {
78 return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire);
79 }
80 return false;
81 }
82