Lely core libraries 2.3.4
fiber_exec.hpp
Go to the documentation of this file.
1
24#ifndef LELY_EV_FIBER_EXEC_HPP_
25#define LELY_EV_FIBER_EXEC_HPP_
26
27#include <lely/ev/exec.hpp>
28#include <lely/ev/fiber_exec.h>
29#include <lely/ev/future.hpp>
30#include <lely/util/fiber.hpp>
31
32#include <mutex>
33#include <utility>
34
35namespace lely {
36namespace ev {
37
38using FiberFlag = util::FiberFlag;
39
45 public:
64 FiberThread(FiberFlag flags = static_cast<FiberFlag>(0),
65 ::std::size_t stack_size = 0, ::std::size_t max_unused = 0) {
66 if (ev_fiber_thrd_init(static_cast<int>(flags), stack_size, max_unused) ==
67 -1)
68 util::throw_errc("FiberThread");
69 }
70
93 FiberThread(FiberFlag flags, ::std::size_t stack_size,
94 ::std::size_t max_unused, bool& already) {
95 int result =
96 ev_fiber_thrd_init(static_cast<int>(flags), stack_size, max_unused);
97 if (result == -1) util::throw_errc("FiberThread");
98 already = result != 0;
99 }
100
101 FiberThread(const FiberThread&) = delete;
102 FiberThread(FiberThread&&) = delete;
103
104 FiberThread& operator=(const FiberThread&) = delete;
105 FiberThread& operator=(FiberThread&&) = delete;
106
112};
113
115class FiberExecutor : public Executor {
116 public:
118 explicit FiberExecutor(Executor inner_exec)
119 : Executor(ev_fiber_exec_create(inner_exec)) {
120 if (!exec_) ::lely::util::throw_errc("FiberExecutor");
121 }
122
123 FiberExecutor(const FiberExecutor&) = delete;
124
125 FiberExecutor(FiberExecutor&& other) noexcept : Executor(other) {
126 other.exec_ = nullptr;
127 }
128
129 FiberExecutor& operator=(const FiberExecutor&) = delete;
130
132 operator=(FiberExecutor&& other) noexcept {
133 using ::std::swap;
134 swap(exec_, other.exec_);
135 return *this;
136 }
137
140
143 get_inner_executor() const noexcept {
145 }
146};
147
149template <class T, class E>
150inline void
153}
154
161inline void
162fiber_yield() noexcept {
163 ev_fiber_await(nullptr);
164}
165
166namespace detail {
167
168inline void
169throw_fiber_error(const char* what_arg, int ev) {
170 switch (ev) {
171 case ev_fiber_success:
172 break;
173 case ev_fiber_error:
174 util::throw_errc(what_arg);
176 throw ::std::system_error(::std::make_error_code(::std::errc::timed_out),
177 what_arg);
178 case ev_fiber_busy:
179 throw ::std::system_error(
180 ::std::make_error_code(::std::errc::resource_unavailable_try_again),
181 what_arg);
182 case ev_fiber_nomem:
183 throw ::std::system_error(
184 ::std::make_error_code(::std::errc::not_enough_memory), what_arg);
185 }
186}
187
190 public:
191 FiberMutexBase() = default;
192
193 FiberMutexBase(const FiberMutexBase&) = delete;
194 FiberMutexBase(FiberMutexBase&& other) = delete;
195
196 FiberMutexBase& operator=(const FiberMutexBase&) = delete;
197 FiberMutexBase& operator=(FiberMutexBase&& other) = delete;
198
200
201 operator ev_fiber_mtx_t*() noexcept { return &mtx_; }
202
204 void
206 int ev = ev_fiber_mtx_lock(*this);
207 if (ev != ev_fiber_success) detail::throw_fiber_error("lock", ev);
208 }
209
211 bool
213 int ev = ev_fiber_mtx_trylock(*this);
214 switch (ev) {
215 case ev_fiber_success:
216 return true;
217 case ev_fiber_busy:
218 return false;
219 default:
220 detail::throw_fiber_error("try_lock", ev);
221 return false;
222 }
223 }
224
226 void
228 int ev = ev_fiber_mtx_unlock(*this);
229 if (ev != ev_fiber_success) detail::throw_fiber_error("unlock", ev);
230 }
231
232 private:
233 ev_fiber_mtx_t mtx_{nullptr};
234};
235
236} // namespace detail
237
240 public:
241 FiberMutex() {
242 int ev = ev_fiber_mtx_init(*this, ev_fiber_mtx_plain);
243 if (ev != ev_fiber_success) detail::throw_fiber_error("FiberMutex", ev);
244 }
245};
246
249 public:
252 if (ev != ev_fiber_success)
253 detail::throw_fiber_error("FiberRecursiveMutex", ev);
254 }
255};
256
259 public:
262 ::lely::util::throw_errc("FiberConditionVariable");
263 }
264
267
268 FiberConditionVariable& operator=(const FiberConditionVariable&) = delete;
269 FiberConditionVariable& operator=(FiberConditionVariable&& other) = delete;
270
272
273 operator ev_fiber_cnd_t*() noexcept { return &cond_; }
274
276 void
277 notify_one() noexcept {
278 ev_fiber_cnd_signal(*this);
279 }
280
282 void
283 notify_all() noexcept {
285 }
286
288 void
289 wait(std::unique_lock<FiberMutex>& lock) {
290 int ev = ev_fiber_cnd_wait(*this, *lock.mutex());
291 if (ev != ev_fiber_success) detail::throw_fiber_error("wait", ev);
292 }
293
295 template <class Predicate>
296 void
297 wait(std::unique_lock<FiberMutex>& lock, Predicate pred) {
298 while (!pred()) wait(lock);
299 }
300
301 private:
302 ev_fiber_cnd_t cond_{nullptr};
303};
304
305} // namespace ev
306} // namespace lely
307
308#endif // !LELY_EV_FIBER_EXEC_HPP_
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition: exec.hpp:38
A condition variable suitable for use in fibers.
Definition: fiber_exec.hpp:258
void wait(std::unique_lock< FiberMutex > &lock, Predicate pred)
Definition: fiber_exec.hpp:297
void wait(std::unique_lock< FiberMutex > &lock)
Definition: fiber_exec.hpp:289
A fiber executor.
Definition: fiber_exec.hpp:115
Executor get_inner_executor() const noexcept
Definition: fiber_exec.hpp:143
FiberExecutor(Executor inner_exec)
Definition: fiber_exec.hpp:118
A plain mutex suitable for use in fibers.
Definition: fiber_exec.hpp:239
A recursive mutex suitable for use in fibers.
Definition: fiber_exec.hpp:248
Convenience class providing a RAII-style mechanism to ensure the calling thread can be used by fiber ...
Definition: fiber_exec.hpp:44
FiberThread(FiberFlag flags, ::std::size_t stack_size, ::std::size_t max_unused, bool &already)
Initializes the calling thread for use by fiber executors, if it was not already initialized.
Definition: fiber_exec.hpp:93
FiberThread(FiberFlag flags=static_cast< FiberFlag >(0), ::std::size_t stack_size=0, ::std::size_t max_unused=0)
Initializes the calling thread for use by fiber executors, if it was not already initialized.
Definition: fiber_exec.hpp:64
~FiberThread()
Finalizes the calling thread and prevents further use by fiber executors, unless another instance of ...
Definition: fiber_exec.hpp:111
A future.
Definition: future.hpp:384
The base class for mutexes suitable for use in fibers.
Definition: fiber_exec.hpp:189
This header file is part of the event library; it contains the C++ interface for the abstract task ex...
This header file is part of the utilities library; it contains the C++ interface for the fiber implem...
FiberFlag
Specifies which properties of the calling environment are saved or restored by a fiber when it is sus...
Definition: fiber.hpp:55
This header file is part of the event library; it contains the fiber executor, mutex and condition va...
int ev_fiber_mtx_lock(ev_fiber_mtx_t *mtx)
Suspends the currently running fiber until it locks the fiber mutex at mtx.
Definition: fiber_exec.c:428
void ev_fiber_thrd_fini(void)
Finalizes the calling thread and prevents further use by fiber executors.
Definition: fiber_exec.c:232
int ev_fiber_mtx_init(ev_fiber_mtx_t *mtx, int type)
Creates a fiber mutex object with properties indicated by type, which must have one of the four value...
Definition: fiber_exec.c:378
int ev_fiber_thrd_init(int flags, size_t stack_size, size_t max_unused)
Initializes the calling thread for use by fiber executors.
Definition: fiber_exec.c:206
int ev_fiber_mtx_unlock(ev_fiber_mtx_t *mtx)
Unlocks the fiber mutex at mtx.
Definition: fiber_exec.c:525
void ev_fiber_cnd_destroy(ev_fiber_cnd_t *cond)
Releases all resources used by the fiber condition variable at cond.
Definition: fiber_exec.c:590
void ev_fiber_mtx_destroy(ev_fiber_mtx_t *mtx)
Releases any resources used by the fiber mutex at mtx.
Definition: fiber_exec.c:411
int ev_fiber_cnd_signal(ev_fiber_cnd_t *cond)
Unblocks one of the fibers that are blocked on the fiber condition variable at cond at the time of th...
Definition: fiber_exec.c:606
int ev_fiber_cnd_broadcast(ev_fiber_cnd_t *cond)
Unblocks all of the fibers that are blocked on the fiber condition variable at cond at the time of th...
Definition: fiber_exec.c:627
int ev_fiber_cnd_init(ev_fiber_cnd_t *cond)
Creates a fiber condition variable.
Definition: fiber_exec.c:566
void ev_fiber_exec_destroy(ev_exec_t *exec)
Destroys a fiber executor.
Definition: fiber_exec.c:352
@ ev_fiber_nomem
Indicates that the requested operation failed because it was unable to allocate memory.
Definition: fiber_exec.h:62
@ ev_fiber_busy
Indicates that the requested operation failed because a resource requested by a test and return funct...
Definition: fiber_exec.h:57
@ ev_fiber_error
Indicates that the requested operation failed.
Definition: fiber_exec.h:47
@ ev_fiber_success
Indicates that the requested operation succeeded.
Definition: fiber_exec.h:45
@ ev_fiber_timedout
Indicates that the time specified in the call was reached without acquiring the requested resource.
Definition: fiber_exec.h:52
void ev_fiber_await(ev_future_t *future)
Suspends a currently running fiber until the specified future becomes ready (or is cancelled).
Definition: fiber_exec.c:369
int ev_fiber_cnd_wait(ev_fiber_cnd_t *cond, ev_fiber_mtx_t *mtx)
Atomically unlocks the fiber mutex at mtx and endeavors to block until the fiber condition variable a...
Definition: fiber_exec.c:652
int ev_fiber_mtx_trylock(ev_fiber_mtx_t *mtx)
Endeavors to lock the fiber mutex at mtx.
Definition: fiber_exec.c:476
@ ev_fiber_mtx_plain
A fiber mutex type that supports neither timeout nor recursive locking.
Definition: fiber_exec.h:70
@ ev_fiber_mtx_recursive
A fiber mutex type that supports recursive locking.
Definition: fiber_exec.h:74
ev_exec_t * ev_fiber_exec_create(ev_exec_t *inner_exec)
Creates a fiber executor.
Definition: fiber_exec.c:325
ev_exec_t * ev_fiber_exec_get_inner_exec(const ev_exec_t *exec)
Returns a pointer to the inner executor of a fiber executor.
Definition: fiber_exec.c:361
void fiber_await(Future< T, E > f) noexcept
Definition: fiber_exec.hpp:151
void fiber_yield() noexcept
Yields a currently running fiber.
Definition: fiber_exec.hpp:162
This header file is part of the event library; it contains the C++ interface for the futures and prom...
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
A synchronization primitive (similar to the standard C11 condition variable) that can be used to bloc...
Definition: fiber_exec.h:92
A synchronization primitive (similar to the standard C11 mutex) that can be used to protect shared da...
Definition: fiber_exec.h:82