73 #ifndef CGU_ASYNC_CHANNEL_H
74 #define CGU_ASYNC_CHANNEL_H
87 #ifdef CGU_USE_SCHED_YIELD
99 --(*
static_cast<std::size_t*
>(arg));
200 enum Status {normal, closed, destructing} status;
249 if (status == normal) {
278 bool push(
const value_type& obj) {
279 bool waiting =
false;
281 if (status != normal)
return false;
292 while (size >= n && status == normal) {
300 pthread_cleanup_pop(
false);
304 Status local_status = status;
305 if (waiting) --waiters;
306 if (local_status != normal)
return false;
308 size_type next = (idx + size) % n;
309 new (
static_cast<void*
>(buf + next)) T{obj};
340 bool waiting =
false;
342 if (status != normal)
return false;
353 while (size >= n && status == normal) {
361 pthread_cleanup_pop(
false);
365 Status local_status = status;
366 if (waiting) --waiters;
367 if (local_status != normal)
return false;
369 size_type next = (idx + size) % n;
370 new (
static_cast<void*
>(buf + next)) T{std::move(obj)};
401 template<
class... Args>
403 bool waiting =
false;
405 if (status != normal)
return false;
416 while (size >= n && status == normal) {
424 pthread_cleanup_pop(
false);
428 Status local_status = status;
429 if (waiting) --waiters;
430 if (local_status != normal)
return false;
432 size_type next = (idx + size) % n;
433 new (
static_cast<void*
>(buf + next)) T{std::forward<Args>(args)...};
464 bool pop(value_type& obj) {
465 bool waiting =
false;
477 while (!size && status == normal) {
485 pthread_cleanup_pop(
false);
487 if (status == destructing) {
490 if (waiting) --waiters;
494 size_type old_idx = idx;
497 if (idx == n) idx = 0;
505 if (waiting) --waiters;
509 if (waiting) --waiters;
514 if (waiting) --waiters;
555 bool waiting =
false;
567 while (!size && status == normal) {
575 pthread_cleanup_pop(
false);
577 if (status == destructing) {
580 if (waiting) --waiters;
584 size_type old_idx = idx;
585 obj = std::move(buf[old_idx]);
587 if (idx == n) idx = 0;
595 if (waiting) --waiters;
599 if (waiting) --waiters;
604 if (waiting) --waiters;
646 buf(static_cast<T*>(malloc(sizeof(T) * n))) {
647 static_assert(n != 0,
"AsyncChannel objects may not be created with size 0");
648 if (!buf)
throw std::bad_alloc();
666 status = destructing;
678 #ifdef CGU_USE_SCHED_YIELD
692 if (idx == n) idx = 0;
703 #ifndef DOXYGEN_PARSING
715 mutable Thread::Mutex mutex;
719 enum Status {normal, closed, destructing} status;
730 void close() noexcept {
731 Thread::Mutex::Lock lock{mutex};
732 if (status == normal) {
738 bool push(
const value_type& obj) {
739 bool waiting =
false;
740 Thread::Mutex::Lock lock{mutex};
741 if (status != normal)
return false;
752 while (full && status == normal) {
759 Thread::CancelBlock b;
760 pthread_cleanup_pop(
false);
764 Status local_status = status;
765 if (waiting) --waiters;
766 if (local_status != normal)
return false;
767 new (
static_cast<void*
>(datum)) T{obj};
773 bool push(value_type&& obj) {
774 bool waiting =
false;
775 Thread::Mutex::Lock lock{mutex};
776 if (status != normal)
return false;
787 while (full && status == normal) {
794 Thread::CancelBlock b;
795 pthread_cleanup_pop(
false);
799 Status local_status = status;
800 if (waiting) --waiters;
801 if (local_status != normal)
return false;
802 new (
static_cast<void*
>(datum)) T{std::move(obj)};
808 template<
class... Args>
810 bool waiting =
false;
811 Thread::Mutex::Lock lock{mutex};
812 if (status != normal)
return false;
823 while (full && status == normal) {
830 Thread::CancelBlock b;
831 pthread_cleanup_pop(
false);
835 Status local_status = status;
836 if (waiting) --waiters;
837 if (local_status != normal)
return false;
838 new (
static_cast<void*
>(datum)) T{std::forward<Args>(args)...};
844 bool pop(value_type& obj) {
845 bool waiting =
false;
846 Thread::Mutex::Lock lock{mutex};
857 while (!full && status == normal) {
864 Thread::CancelBlock b;
865 pthread_cleanup_pop(
false);
867 if (status == destructing) {
870 if (waiting) --waiters;
882 if (waiting) --waiters;
886 if (waiting) --waiters;
891 if (waiting) --waiters;
897 bool waiting =
false;
898 Thread::Mutex::Lock lock{mutex};
909 while (!full && status == normal) {
916 Thread::CancelBlock b;
917 pthread_cleanup_pop(
false);
919 if (status == destructing) {
922 if (waiting) --waiters;
926 obj = std::move(*datum);
934 if (waiting) --waiters;
938 if (waiting) --waiters;
943 if (waiting) --waiters;
948 AsyncChannel(): waiters(0), full(false), status(normal),
958 datum(static_cast<T*>(malloc(sizeof(T)))) {
959 if (!datum)
throw std::bad_alloc();
964 status = destructing;
976 #ifdef CGU_USE_SCHED_YIELD
987 if (full) datum->~T();
994 #endif // DOXYGEN_PARSING
998 #endif // CGU_ASYNC_CHANNEL_H
A thread-safe "channel" class for inter-thread communication.
Definition: async_channel.h:189
int lock() noexcept
Definition: mutex.h:147
int unlock() noexcept
Definition: mutex.h:170
A wrapper class for pthread condition variables.
Definition: mutex.h:449
bool move_pop(value_type &obj)
Definition: async_channel.h:554
bool pop(value_type &obj)
Definition: async_channel.h:464
A class enabling the cancellation state of a thread to be controlled.
Definition: thread.h:723
A scoped locking class for exception safe Mutex locking.
Definition: mutex.h:207
T value_type
Definition: async_channel.h:191
bool push(value_type &&obj)
Definition: async_channel.h:339
bool emplace(Args &&...args)
Definition: async_channel.h:402
A wrapper class for pthread mutexes.
Definition: mutex.h:117
AsyncChannel & operator=(const AsyncChannel &)=delete
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Definition: application.h:44
~AsyncChannel()
Definition: async_channel.h:664
std::size_t size_type
Definition: async_channel.h:192
AsyncChannel()
Definition: async_channel.h:636
void close() noexcept
Definition: async_channel.h:247
int broadcast() noexcept
Definition: mutex.h:483
void cgu_async_channel_waiters_dec(void *arg)
Definition: async_channel.h:98
bool push(const value_type &obj)
Definition: async_channel.h:278
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
int wait(Mutex &mutex)
Definition: mutex.h:513