Flutter Engine
semaphore.cc
Go to the documentation of this file.
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:
17  explicit PlatformSemaphore(uint32_t count)
18  : _sem(dispatch_semaphore_create(count)), _initial(count) {}
19 
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 
30  bool IsValid() const { return _sem != nullptr; }
31 
32  bool TryWait() {
33  if (_sem == nullptr) {
34  return false;
35  }
36 
37  return dispatch_semaphore_wait(_sem, DISPATCH_TIME_NOW) == 0;
38  }
39 
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:
62  explicit PlatformSemaphore(uint32_t count)
63  : _sem(CreateSemaphore(NULL, count, LONG_MAX, NULL)) {}
64 
66  if (_sem != nullptr) {
67  CloseHandle(_sem);
68  _sem = nullptr;
69  }
70  }
71 
72  bool IsValid() const { return _sem != nullptr; }
73 
74  bool TryWait() {
75  if (_sem == nullptr) {
76  return false;
77  }
78 
79  return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
80  }
81 
82  void Signal() {
83  if (_sem != nullptr) {
84  ReleaseSemaphore(_sem, 1, NULL);
85  }
86  }
87 
88  private:
89  HANDLE _sem;
90 
92 };
93 
94 } // namespace fml
95 
96 #else
97 #include <semaphore.h>
98 #include "flutter/fml/eintr_wrapper.h"
99 
100 namespace fml {
101 
103  public:
104  explicit PlatformSemaphore(uint32_t count)
105  : valid_(::sem_init(&sem_, 0 /* not shared */, count) == 0) {}
106 
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 
116  bool IsValid() const { return valid_; }
117 
118  bool TryWait() {
119  if (!valid_) {
120  return false;
121  }
122 
123  return FML_HANDLE_EINTR(::sem_trywait(&sem_)) == 0;
124  }
125 
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 
141 };
142 
143 } // namespace fml
144 
145 #endif
146 
147 namespace fml {
148 
149 Semaphore::Semaphore(uint32_t count) : _impl(new PlatformSemaphore(count)) {}
150 
151 Semaphore::~Semaphore() = default;
152 
153 bool Semaphore::IsValid() const {
154  return _impl->IsValid();
155 }
156 
158  return _impl->TryWait();
159 }
160 
162  return _impl->Signal();
163 }
164 
165 } // namespace fml
#define FML_DCHECK(condition)
Definition: logging.h:86
PlatformSemaphore(uint32_t count)
Definition: semaphore.cc:104
bool IsValid() const
Definition: semaphore.cc:116
Definition: ascii_trie.cc:9
Semaphore(uint32_t count)
Definition: semaphore.cc:149
#define FML_HANDLE_EINTR(x)
Definition: eintr_wrapper.h:33
bool IsValid() const
Definition: semaphore.cc:153
bool TryWait()
Definition: semaphore.cc:157
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27