Lely core libraries  2.2.5
fiber_exec.hpp
Go to the documentation of this file.
1 
24 #ifndef LELY_EV_CO_FIBER_HPP_
25 #define LELY_EV_CO_FIBER_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 
35 namespace lely {
36 namespace ev {
37 
38 using FiberFlag = util::FiberFlag;
39 
44 class FiberThread {
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 
115 class 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 
142  Executor
143  get_inner_executor() const noexcept {
144  return Executor(ev_fiber_exec_get_inner_exec(*this));
145  }
146 };
147 
149 template <class T, class E>
150 inline void
152  ev_fiber_await(f);
153 }
154 
161 inline void
162 fiber_yield() noexcept {
163  ev_fiber_await(nullptr);
164 }
165 
166 namespace detail {
167 
168 inline void
169 throw_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);
175  case ev_fiber_timedout:
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 
199  ~FiberMutexBase() { ev_fiber_mtx_destroy(*this); }
200 
201  operator ev_fiber_mtx_t*() noexcept { return &mtx_; }
202 
204  void
205  lock() {
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  }
222  }
223 
225  void
226  unlock() {
227  int ev = ev_fiber_mtx_unlock(*this);
228  if (ev != ev_fiber_success) detail::throw_fiber_error("unlock", ev);
229  }
230 
231  private:
232  ev_fiber_mtx_t mtx_{nullptr};
233 };
234 
235 } // namespace detail
236 
239  public:
240  FiberMutex() {
241  int ev = ev_fiber_mtx_init(*this, ev_fiber_mtx_plain);
242  if (ev != ev_fiber_success) detail::throw_fiber_error("FiberMutex", ev);
243  }
244 };
245 
248  public:
250  int ev = ev_fiber_mtx_init(*this, ev_fiber_mtx_recursive);
251  if (ev != ev_fiber_success)
252  detail::throw_fiber_error("FiberRecursiveMutex", ev);
253  }
254 };
255 
258  public:
260  if (ev_fiber_cnd_init(*this) != ev_fiber_success)
261  ::lely::util::throw_errc("FiberConditionVariable");
262  }
263 
266 
267  FiberConditionVariable& operator=(const FiberConditionVariable&) = delete;
268  FiberConditionVariable& operator=(FiberConditionVariable&& other) = delete;
269 
271 
272  operator ev_fiber_cnd_t*() noexcept { return &cond_; }
273 
275  void
276  notify_one() noexcept {
277  ev_fiber_cnd_signal(*this);
278  }
279 
281  void
282  notify_all() noexcept {
283  ev_fiber_cnd_broadcast(*this);
284  }
285 
287  void
288  wait(std::unique_lock<FiberMutex>& lock) {
289  int ev = ev_fiber_cnd_wait(*this, *lock.mutex());
290  if (ev != ev_fiber_success) detail::throw_fiber_error("wait", ev);
291  }
292 
294  template <class Predicate>
295  void
296  wait(std::unique_lock<FiberMutex>& lock, Predicate pred) {
297  while (!pred()) wait(lock);
298  }
299 
300  private:
301  ev_fiber_cnd_t cond_{nullptr};
302 };
303 
304 } // namespace ev
305 } // namespace lely
306 
307 #endif // !LELY_EV_CO_FIBER_HPP_
void wait(std::unique_lock< FiberMutex > &lock)
Definition: fiber_exec.hpp:288
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:581
Indicates that the requested operation succeeded.
Definition: fiber_exec.h:45
FiberFlag
Specifies which properties of the calling environment are saved or restored by a fiber when it is sus...
Definition: fiber.hpp:56
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:597
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:203
Indicates that the requested operation failed because a resource requested by a test and return funct...
Definition: fiber_exec.h:57
int ev_fiber_mtx_trylock(ev_fiber_mtx_t *mtx)
Endeavors to lock the fiber mutex at mtx.
Definition: fiber_exec.c:467
Convenience class providing a RAII-style mechanism to ensure the calling thread can be used by fiber ...
Definition: fiber_exec.hpp:44
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
A fiber executor.
Definition: fiber_exec.hpp:115
int ev_fiber_cnd_init(ev_fiber_cnd_t *cond)
Creates a fiber condition variable.
Definition: fiber_exec.c:557
A fiber mutex type that supports neither timeout nor recursive locking.
Definition: fiber_exec.h:70
~FiberThread()
Finalizes the calling thread and prevents further use by fiber executors, unless another instance of ...
Definition: fiber_exec.hpp:111
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:618
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:643
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
Indicates that the requested operation failed.
Definition: fiber_exec.h:47
Executor get_inner_executor() const noexcept
Definition: fiber_exec.hpp:143
The base class for mutexes suitable for use in fibers.
Definition: fiber_exec.hpp:189
void ev_fiber_thrd_fini(void)
Finalizes the calling thread and prevents further use by fiber executors.
Definition: fiber_exec.c:229
int ev_fiber_mtx_unlock(ev_fiber_mtx_t *mtx)
Unlocks the fiber mutex at mtx.
Definition: fiber_exec.c:516
ev_exec_t * ev_fiber_exec_create(ev_exec_t *inner_exec)
Creates a fiber executor.
Definition: fiber_exec.c:316
void wait(std::unique_lock< FiberMutex > &lock, Predicate pred)
Definition: fiber_exec.hpp:296
void fiber_await(Future< T, E > f) noexcept
Definition: fiber_exec.hpp:151
Indicates that the requested operation failed because it was unable to allocate memory.
Definition: fiber_exec.h:62
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...
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
A plain mutex suitable for use in fibers.
Definition: fiber_exec.hpp:238
This header file is part of the event library; it contains the C++ interface for the abstract task ex...
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:257
void ev_fiber_exec_destroy(ev_exec_t *exec)
Destroys a fiber executor.
Definition: fiber_exec.c:343
FiberExecutor(Executor inner_exec)
Definition: fiber_exec.hpp:118
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
Indicates that the time specified in the call was reached without acquiring the requested resource...
Definition: fiber_exec.h:52
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:352
This header file is part of the event library; it contains the fiber executor, mutex and condition va...
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:369
Definition: buf.hpp:32
A fiber mutex type that supports recursive locking.
Definition: fiber_exec.h:74
A recursive mutex suitable for use in fibers.
Definition: fiber_exec.hpp:247
void ev_fiber_mtx_destroy(ev_fiber_mtx_t *mtx)
Releases any resources used by the fiber mutex at mtx.
Definition: fiber_exec.c:402
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:360
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:419
This header file is part of the utilities library; it contains the C++ interface for the fiber implem...
A future.
Definition: future.hpp:50