xref: /aosp_15_r20/external/skia/src/base/SkSemaphore.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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