• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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