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_
ev_fiber_exec_destroy
void ev_fiber_exec_destroy(ev_exec_t *exec)
Destroys a fiber executor.
Definition: fiber_exec.c:352
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:232
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:277
ev_fiber_exec_create
ev_exec_t * ev_fiber_exec_create(ev_exec_t *inner_exec)
Creates a fiber executor.
Definition: fiber_exec.c:325
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:248
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:55
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:652
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:590
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:411
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:476
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:206
lely::ev::FiberConditionVariable
A condition variable suitable for use in fibers.
Definition: fiber_exec.hpp:258
lely::ev::detail::FiberMutexBase::unlock
void unlock()
Definition: fiber_exec.hpp:227
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:606
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:289
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:369
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:239
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:297
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:378
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:283
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:361
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:566
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:627
ev_fiber_mtx_unlock
int ev_fiber_mtx_unlock(ev_fiber_mtx_t *mtx)
Unlocks the fiber mutex at mtx.
Definition: fiber_exec.c:525
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:428
lely::ev::detail::FiberMutexBase::lock
void lock()
Definition: fiber_exec.hpp:205