1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/private/SkSemaphore.h" 9cb93a386Sopenharmony_ci#include "src/core/SkLeanWindows.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 12cb93a386Sopenharmony_ci #include <dispatch/dispatch.h> 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci struct SkSemaphore::OSSemaphore { 15cb93a386Sopenharmony_ci dispatch_semaphore_t fSemaphore; 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci OSSemaphore() { fSemaphore = dispatch_semaphore_create(0/*initial count*/); } 18cb93a386Sopenharmony_ci ~OSSemaphore() { dispatch_release(fSemaphore); } 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci void signal(int n) { while (n --> 0) { dispatch_semaphore_signal(fSemaphore); } } 21cb93a386Sopenharmony_ci void wait() { dispatch_semaphore_wait(fSemaphore, DISPATCH_TIME_FOREVER); } 22cb93a386Sopenharmony_ci }; 23cb93a386Sopenharmony_ci#elif defined(SK_BUILD_FOR_WIN) 24cb93a386Sopenharmony_ci struct SkSemaphore::OSSemaphore { 25cb93a386Sopenharmony_ci HANDLE fSemaphore; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci OSSemaphore() { 28cb93a386Sopenharmony_ci fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/, 29cb93a386Sopenharmony_ci 0 /*initial count*/, 30cb93a386Sopenharmony_ci MAXLONG /*max count*/, 31cb93a386Sopenharmony_ci nullptr /*name, optional*/); 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci ~OSSemaphore() { CloseHandle(fSemaphore); } 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci void signal(int n) { 36cb93a386Sopenharmony_ci ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci void wait() { WaitForSingleObject(fSemaphore, INFINITE/*timeout in ms*/); } 39cb93a386Sopenharmony_ci }; 40cb93a386Sopenharmony_ci#else 41cb93a386Sopenharmony_ci // It's important we test for Mach before this. This code will compile but not work there. 42cb93a386Sopenharmony_ci #include <errno.h> 43cb93a386Sopenharmony_ci #include <semaphore.h> 44cb93a386Sopenharmony_ci struct SkSemaphore::OSSemaphore { 45cb93a386Sopenharmony_ci sem_t fSemaphore; 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); } 48cb93a386Sopenharmony_ci ~OSSemaphore() { sem_destroy(&fSemaphore); } 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } } 51cb93a386Sopenharmony_ci void wait() { 52cb93a386Sopenharmony_ci // Try until we're not interrupted. 53cb93a386Sopenharmony_ci while(sem_wait(&fSemaphore) == -1 && errno == EINTR); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci }; 56cb93a386Sopenharmony_ci#endif 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ciSkSemaphore::~SkSemaphore() { 61cb93a386Sopenharmony_ci delete fOSSemaphore; 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_civoid SkSemaphore::osSignal(int n) { 65cb93a386Sopenharmony_ci fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; }); 66cb93a386Sopenharmony_ci fOSSemaphore->signal(n); 67cb93a386Sopenharmony_ci} 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_civoid SkSemaphore::osWait() { 70cb93a386Sopenharmony_ci fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; }); 71cb93a386Sopenharmony_ci fOSSemaphore->wait(); 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_cibool SkSemaphore::try_wait() { 75cb93a386Sopenharmony_ci int count = fCount.load(std::memory_order_relaxed); 76cb93a386Sopenharmony_ci if (count > 0) { 77cb93a386Sopenharmony_ci return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire); 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci return false; 80cb93a386Sopenharmony_ci} 81