Home | History | Annotate | Download | only in core
      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         OSSemaphore()  { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
     49         ~OSSemaphore() { sem_destroy(&fSemaphore); }
     50 
     51         void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } }
     52         void wait() {
     53             // Try until we're not interrupted.
     54             while(sem_wait(&fSemaphore) == -1 && errno == EINTR);
     55         }
     56     };
     57 #endif
     58 
     59 ///////////////////////////////////////////////////////////////////////////////
     60 
     61 void SkBaseSemaphore::osSignal(int n) {
     62     fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
     63     fOSSemaphore->signal(n);
     64 }
     65 
     66 void SkBaseSemaphore::osWait() {
     67     fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
     68     fOSSemaphore->wait();
     69 }
     70 
     71 void SkBaseSemaphore::cleanup() {
     72     delete fOSSemaphore;
     73 }
     74 
     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