Line data Source code
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 :
16 : OSSemaphore() {
17 : semaphore_create(mach_task_self(), &fSemaphore, SYNC_POLICY_LIFO, 0/*initial count*/);
18 : }
19 : ~OSSemaphore() { semaphore_destroy(mach_task_self(), fSemaphore); }
20 :
21 : void signal(int n) { while (n --> 0) { semaphore_signal(fSemaphore); } }
22 : void wait() { semaphore_wait(fSemaphore); }
23 : };
24 : #elif defined(SK_BUILD_FOR_WIN32)
25 : struct SkBaseSemaphore::OSSemaphore {
26 : HANDLE fSemaphore;
27 :
28 : OSSemaphore() {
29 : fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/,
30 : 0 /*initial count*/,
31 : MAXLONG /*max count*/,
32 : nullptr /*name, optional*/);
33 : }
34 : ~OSSemaphore() { CloseHandle(fSemaphore); }
35 :
36 : void signal(int n) {
37 : ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/);
38 : }
39 : 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 :
48 0 : OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
49 0 : ~OSSemaphore() { sem_destroy(&fSemaphore); }
50 :
51 0 : void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } }
52 0 : void wait() {
53 : // Try until we're not interrupted.
54 0 : while(sem_wait(&fSemaphore) == -1 && errno == EINTR);
55 0 : }
56 : };
57 : #endif
58 :
59 : ///////////////////////////////////////////////////////////////////////////////
60 :
61 0 : void SkBaseSemaphore::osSignal(int n) {
62 0 : fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
63 0 : fOSSemaphore->signal(n);
64 0 : }
65 :
66 0 : void SkBaseSemaphore::osWait() {
67 0 : fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
68 0 : fOSSemaphore->wait();
69 0 : }
70 :
71 250 : void SkBaseSemaphore::cleanup() {
72 250 : delete fOSSemaphore;
73 250 : }
74 :
75 0 : bool SkBaseSemaphore::try_wait() {
76 0 : int count = fCount.load(std::memory_order_relaxed);
77 0 : if (count > 0) {
78 0 : return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire);
79 : }
80 0 : return false;
81 : }
|