| Taskflow: A General-purpose Task-parallel Programming System

Loading...
Searching...
No Matches
semaphore.hpp
1#pragma once
2
3#include <mutex>
4
5#include "declarations.hpp"
6#include "../utility/small_vector.hpp"
7
13 namespace tf {
14
15// ----------------------------------------------------------------------------
16// Semaphore
17// ----------------------------------------------------------------------------
18
68 class Semaphore {
69
70 friend class Node;
71 friend class Executor;
72
73 public:
74
81 Semaphore() = default;
82
93 explicit Semaphore(size_t max_value);
94
98 size_t value() const;
99
103 size_t max_value() const;
104
108 void reset();
109
113 void reset(size_t new_max_value);
114
115 private:
116
117 mutable std::mutex _mtx;
118
119 size_t _max_value{0};
120 size_t _cur_value{0};
121
122 SmallVector<Node*> _waiters;
123
124 bool _try_acquire_or_wait(Node*);
125
126 void _release(SmallVector<Node*>&);
127};
128
129 inline Semaphore::Semaphore(size_t max_value) :
130 _max_value(max_value),
131 _cur_value(max_value) {
132}
133
134 inline bool Semaphore::_try_acquire_or_wait(Node* me) {
135 std::lock_guard<std::mutex> lock(_mtx);
136 if(_cur_value > 0) {
137 --_cur_value;
138 return true;
139 }
140 else {
141 _waiters.push_back(me);
142 return false;
143 }
144}
145
146 inline void Semaphore::_release(SmallVector<Node*>& dst) {
147
148 std::lock_guard<std::mutex> lock(_mtx);
149
150 if(_cur_value >= _max_value) {
151 TF_THROW("can't release the semaphore more than its maximum value: ", _max_value);
152 }
153
154 ++_cur_value;
155
156 if(dst.empty()) {
157 dst.swap(_waiters);
158 }
159 else {
160 dst.reserve(dst.size() + _waiters.size());
161 dst.insert(dst.end(), _waiters.begin(), _waiters.end());
162 _waiters.clear();
163 }
164}
165
166 inline size_t Semaphore::max_value() const {
167 return _max_value;
168}
169
170 inline size_t Semaphore::value() const {
171 std::lock_guard<std::mutex> lock(_mtx);
172 return _cur_value;
173}
174
175 inline void Semaphore::reset() {
176 std::lock_guard<std::mutex> lock(_mtx);
177 _cur_value = _max_value;
178 _waiters.clear();
179}
180
181 inline void Semaphore::reset(size_t new_max_value) {
182 std::lock_guard<std::mutex> lock(_mtx);
183 _cur_value = (_max_value = new_max_value);
184 _waiters.clear();
185}
186
187} // end of namespace tf. ---------------------------------------------------
188
tf::Executor
class to create an executor
Definition executor.hpp:62
tf::Semaphore
class to create a semophore object for building a concurrency constraint
Definition semaphore.hpp:68
tf::Semaphore::max_value
size_t max_value() const
queries the maximum allowable value of this semaphore
Definition semaphore.hpp:166
tf::Semaphore::Semaphore
Semaphore()=default
constructs a default semaphore
tf::Semaphore::value
size_t value() const
queries the current counter value
Definition semaphore.hpp:170
tf::Semaphore::reset
void reset()
resets the semaphores to a clean state
Definition semaphore.hpp:175
tf
taskflow namespace
Definition small_vector.hpp:20