• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/fml/synchronization/semaphore.h"
6 
7 #include "flutter/fml/build_config.h"
8 #include "flutter/fml/logging.h"
9 
10 #if OS_MACOSX
11 #include <dispatch/dispatch.h>
12 
13 namespace fml {
14 
15 class PlatformSemaphore {
16  public:
PlatformSemaphore(uint32_t count)17   explicit PlatformSemaphore(uint32_t count)
18       : _sem(dispatch_semaphore_create(count)), _initial(count) {}
19 
~PlatformSemaphore()20   ~PlatformSemaphore() {
21     for (uint32_t i = 0; i < _initial; ++i) {
22       Signal();
23     }
24     if (_sem != nullptr) {
25       dispatch_release(reinterpret_cast<dispatch_object_t>(_sem));
26       _sem = nullptr;
27     }
28   }
29 
IsValid() const30   bool IsValid() const { return _sem != nullptr; }
31 
TryWait()32   bool TryWait() {
33     if (_sem == nullptr) {
34       return false;
35     }
36 
37     return dispatch_semaphore_wait(_sem, DISPATCH_TIME_NOW) == 0;
38   }
39 
Signal()40   void Signal() {
41     if (_sem != nullptr) {
42       dispatch_semaphore_signal(_sem);
43     }
44   }
45 
46  private:
47   dispatch_semaphore_t _sem;
48   const uint32_t _initial;
49 
50   FML_DISALLOW_COPY_AND_ASSIGN(PlatformSemaphore);
51 };
52 
53 }  // namespace fml
54 
55 #elif OS_WIN
56 #include <windows.h>
57 
58 namespace fml {
59 
60 class PlatformSemaphore {
61  public:
PlatformSemaphore(uint32_t count)62   explicit PlatformSemaphore(uint32_t count)
63       : _sem(CreateSemaphore(NULL, count, LONG_MAX, NULL)) {}
64 
~PlatformSemaphore()65   ~PlatformSemaphore() {
66     if (_sem != nullptr) {
67       CloseHandle(_sem);
68       _sem = nullptr;
69     }
70   }
71 
IsValid() const72   bool IsValid() const { return _sem != nullptr; }
73 
TryWait()74   bool TryWait() {
75     if (_sem == nullptr) {
76       return false;
77     }
78 
79     return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
80   }
81 
Signal()82   void Signal() {
83     if (_sem != nullptr) {
84       ReleaseSemaphore(_sem, 1, NULL);
85     }
86   }
87 
88  private:
89   HANDLE _sem;
90 
91   FML_DISALLOW_COPY_AND_ASSIGN(PlatformSemaphore);
92 };
93 
94 }  // namespace fml
95 
96 #else
97 #include <semaphore.h>
98 #include "flutter/fml/eintr_wrapper.h"
99 
100 namespace fml {
101 
102 class PlatformSemaphore {
103  public:
PlatformSemaphore(uint32_t count)104   explicit PlatformSemaphore(uint32_t count)
105       : valid_(::sem_init(&sem_, 0 /* not shared */, count) == 0) {}
106 
~PlatformSemaphore()107   ~PlatformSemaphore() {
108     if (valid_) {
109       int result = ::sem_destroy(&sem_);
110       // Can only be EINVAL which should not be possible since we checked for
111       // validity.
112       FML_DCHECK(result == 0);
113     }
114   }
115 
IsValid() const116   bool IsValid() const { return valid_; }
117 
TryWait()118   bool TryWait() {
119     if (!valid_) {
120       return false;
121     }
122 
123     return FML_HANDLE_EINTR(::sem_trywait(&sem_)) == 0;
124   }
125 
Signal()126   void Signal() {
127     if (!valid_) {
128       return;
129     }
130 
131     ::sem_post(&sem_);
132 
133     return;
134   }
135 
136  private:
137   bool valid_;
138   sem_t sem_;
139 
140   FML_DISALLOW_COPY_AND_ASSIGN(PlatformSemaphore);
141 };
142 
143 }  // namespace fml
144 
145 #endif
146 
147 namespace fml {
148 
Semaphore(uint32_t count)149 Semaphore::Semaphore(uint32_t count) : _impl(new PlatformSemaphore(count)) {}
150 
151 Semaphore::~Semaphore() = default;
152 
IsValid() const153 bool Semaphore::IsValid() const {
154   return _impl->IsValid();
155 }
156 
TryWait()157 bool Semaphore::TryWait() {
158   return _impl->TryWait();
159 }
160 
Signal()161 void Semaphore::Signal() {
162   return _impl->Signal();
163 }
164 
165 }  // namespace fml
166