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) {
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;
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;
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;
433 new (
static_cast<void*
>(buf + next)) T{std::forward<Args>(args)...};
465 bool waiting =
false;
477 while (!size && status == normal) {
485 pthread_cleanup_pop(
false);
487 if (status == destructing) {
490 if (waiting) --waiters;
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;
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*>(std::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
710 class AsyncChannel<T, 1> {
715 mutable Thread::Mutex mutex;
719 enum Status {normal, closed, destructing} status;
731 Thread::Mutex::Lock lock{mutex};
732 if (status == normal) {
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};
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)...};
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*>(std::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