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
126 other.exec_ = nullptr;
127 }
128
129 FiberExecutor& operator=(const FiberExecutor&) = delete;
130
131 FiberExecutor&
132 operator=(FiberExecutor&& other) noexcept {
133 using ::std::swap;
134 swap(exec_, other.exec_);
135 return *this;
136 }
137
140
146};
147
149template <class T, class E>
150inline void
153}
154
161inline void
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;
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;
270
272
273 operator ev_fiber_cnd_t*() noexcept { return &cond_; }
274
276 void
280
282 void
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_
A CANopen value.
Definition val.hpp:42
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.
void wait(std::unique_lock< FiberMutex > &lock, Predicate pred)
void wait(std::unique_lock< FiberMutex > &lock)
A fiber executor.
Executor get_inner_executor() const noexcept
FiberExecutor(Executor inner_exec)
A plain mutex suitable for use in fibers.
A recursive mutex suitable for use in fibers.
Convenience class providing a RAII-style mechanism to ensure the calling thread can be used by fiber ...
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.
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.
~FiberThread()
Finalizes the calling thread and prevents further use by fiber executors, unless another instance of ...
The base class for mutexes suitable for use in fibers.
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_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
void fiber_yield() noexcept
Yields a currently running fiber.
This header file is part of the event library; it contains the C++ interface for the futures and prom...
A synchronization primitive (similar to the standard C11 condition variable) that can be used to bloc...
Definition fiber_exec.h:92
The context of a wait operation on a fiber condition variable.
Definition fiber_exec.c:177
A synchronization primitive (similar to the standard C11 mutex) that can be used to protect shared da...
Definition fiber_exec.h:82