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_
ev_fiber_exec_destroy
void ev_fiber_exec_destroy(ev_exec_t *exec)
Destroys a fiber executor.
Definition: fiber_exec.c:343
ev_fiber_thrd_fini
void ev_fiber_thrd_fini(void)
Finalizes the calling thread and prevents further use by fiber executors.
Definition: fiber_exec.c:229
lely::ev::FiberThread::FiberThread
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
lely::ev::FiberThread
Convenience class providing a RAII-style mechanism to ensure the calling thread can be used by fiber ...
Definition: fiber_exec.hpp:44
ev_fiber_mtx_plain
@ ev_fiber_mtx_plain
A fiber mutex type that supports neither timeout nor recursive locking.
Definition: fiber_exec.h:70
lely::ev::FiberConditionVariable::notify_one
void notify_one() noexcept
Definition: fiber_exec.hpp:276
ev_fiber_exec_create
ev_exec_t * ev_fiber_exec_create(ev_exec_t *inner_exec)
Creates a fiber executor.
Definition: fiber_exec.c:316
ev_fiber_mtx_recursive
@ ev_fiber_mtx_recursive
A fiber mutex type that supports recursive locking.
Definition: fiber_exec.h:74
lely::ev::FiberRecursiveMutex
A recursive mutex suitable for use in fibers.
Definition: fiber_exec.hpp:247
lely::ev::detail::FiberMutexBase::try_lock
bool try_lock()
Definition: fiber_exec.hpp:212
lely::util::FiberFlag
FiberFlag
Specifies which properties of the calling environment are saved or restored by a fiber when it is sus...
Definition: fiber.hpp:56
fiber.hpp
ev_fiber_cnd_wait
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
ev_fiber_cnd_destroy
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
ev_fiber_mtx_destroy
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
lely::ev::FiberThread::FiberThread
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
ev_fiber_mtx_trylock
int ev_fiber_mtx_trylock(ev_fiber_mtx_t *mtx)
Endeavors to lock the fiber mutex at mtx.
Definition: fiber_exec.c:467
lely::ev::FiberExecutor::~FiberExecutor
~FiberExecutor()
Definition: fiber_exec.hpp:139
ev_fiber_thrd_init
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
lely::ev::FiberConditionVariable
A condition variable suitable for use in fibers.
Definition: fiber_exec.hpp:257
lely::ev::detail::FiberMutexBase::unlock
void unlock()
Definition: fiber_exec.hpp:226
lely::ev::Executor
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition: exec.hpp:38
ev_fiber_cnd_signal
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
ev_fiber_error
@ ev_fiber_error
Indicates that the requested operation failed.
Definition: fiber_exec.h:47
lely::ev::Future
A future.
Definition: future.hpp:50
lely::ev::FiberConditionVariable::wait
void wait(std::unique_lock< FiberMutex > &lock)
Definition: fiber_exec.hpp:288
ev_fiber_await
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
fiber_exec.h
lely::ev::FiberThread::~FiberThread
~FiberThread()
Finalizes the calling thread and prevents further use by fiber executors, unless another instance of ...
Definition: fiber_exec.hpp:111
lely::ev::FiberMutex
A plain mutex suitable for use in fibers.
Definition: fiber_exec.hpp:238
ev_fiber_mtx_t
A synchronization primitive (similar to the standard C11 mutex) that can be used to protect shared da...
Definition: fiber_exec.h:82
ev_fiber_success
@ ev_fiber_success
Indicates that the requested operation succeeded.
Definition: fiber_exec.h:45
future.hpp
lely::ev::detail::FiberMutexBase
The base class for mutexes suitable for use in fibers.
Definition: fiber_exec.hpp:189
lely::ev::fiber_await
void fiber_await(Future< T, E > f) noexcept
Definition: fiber_exec.hpp:151
ev_fiber_nomem
@ ev_fiber_nomem
Indicates that the requested operation failed because it was unable to allocate memory.
Definition: fiber_exec.h:62
lely::ev::FiberConditionVariable::wait
void wait(std::unique_lock< FiberMutex > &lock, Predicate pred)
Definition: fiber_exec.hpp:296
ev_fiber_mtx_init
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
ev_fiber_cnd_t
A synchronization primitive (similar to the standard C11 condition variable) that can be used to bloc...
Definition: fiber_exec.h:92
ev_fiber_timedout
@ ev_fiber_timedout
Indicates that the time specified in the call was reached without acquiring the requested resource.
Definition: fiber_exec.h:52
lely::ev::FiberExecutor
A fiber executor.
Definition: fiber_exec.hpp:115
lely::ev::FiberConditionVariable::notify_all
void notify_all() noexcept
Definition: fiber_exec.hpp:282
ev_fiber_exec_get_inner_exec
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
lely::canopen::make_error_code
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
exec.hpp
lely::ev::fiber_yield
void fiber_yield() noexcept
Yields a currently running fiber.
Definition: fiber_exec.hpp:162
lely::ev::FiberExecutor::FiberExecutor
FiberExecutor(Executor inner_exec)
Definition: fiber_exec.hpp:118
lely::ev::FiberExecutor::get_inner_executor
Executor get_inner_executor() const noexcept
Definition: fiber_exec.hpp:143
ev_fiber_cnd_init
int ev_fiber_cnd_init(ev_fiber_cnd_t *cond)
Creates a fiber condition variable.
Definition: fiber_exec.c:557
ev_fiber_busy
@ 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_cnd_broadcast
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
ev_fiber_mtx_unlock
int ev_fiber_mtx_unlock(ev_fiber_mtx_t *mtx)
Unlocks the fiber mutex at mtx.
Definition: fiber_exec.c:516
ev_fiber_mtx_lock
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
lely::ev::detail::FiberMutexBase::lock
void lock()
Definition: fiber_exec.hpp:205