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 
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  return false;
222  }
223  }
224 
226  void
227  unlock() {
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:
251  int ev = ev_fiber_mtx_init(*this, ev_fiber_mtx_recursive);
252  if (ev != ev_fiber_success)
253  detail::throw_fiber_error("FiberRecursiveMutex", ev);
254  }
255 };
256 
259  public:
261  if (ev_fiber_cnd_init(*this) != ev_fiber_success)
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 {
284  ev_fiber_cnd_broadcast(*this);
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
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
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_exec_t * ev_fiber_exec_create(ev_exec_t *inner_exec)
Creates a fiber executor.
Definition: fiber_exec.c:325
@ 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
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