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