71 #ifndef CGU_ASYNC_QUEUE_H
72 #define CGU_ASYNC_QUEUE_H
87 #ifdef CGU_USE_SCHED_YIELD
103 virtual const char*
what()
const throw() {
return "AsyncQueuePopError: popping from empty AsyncQueue object\n";}
147 template <
class T,
class Container = std::list<T> >
class AsyncQueue {
155 std::queue<T, Container> q;
169 #ifdef CGU_USE_SCHED_YIELD
219 q.push(std::move(obj));
245 template<
class... Args>
248 q.emplace(std::forward<Args>(args)...);
316 obj = std::move(q.front());
441 if (
this != &other) {
442 lock2(mutex, other.mutex);
473 lock2(mutex, rhs.mutex);
476 std::queue<T, Container> temp{rhs.q};
507 q = std::move(rhs.q);
649 std::queue<T, Container> q;
664 #ifdef CGU_USE_SCHED_YIELD
715 q.push(std::move(obj));
742 template<
class... Args>
745 q.emplace(std::forward<Args>(args)...);
814 obj = std::move(q.front());
900 while (q.empty()) cond.
wait(mutex);
945 while (q.empty()) cond.
wait(mutex);
947 obj = std::move(q.front());
1103 obj = std::move(q.front());
1243 if (
this != &other) {
1244 lock2(mutex, other.mutex);
1249 if (!other.q.empty()) other.cond.
broadcast();
1288 lock2(mutex, rhs.mutex);
1291 std::queue<T, Container> temp{rhs.q};
1330 q = std::move(rhs.q);
1427 q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1466 template <
class T,
class Container>
1495 template <
class T,
class Container>
1501 #if defined(CGU_USE_INHERITABLE_QUEUE) && !defined(DOXYGEN_PARSING)
1510 template <
class T,
class Allocator>
1511 class AsyncQueue<T, std::list<T, Allocator> > {
1513 typedef std::list<T, Allocator> Container;
1514 typedef typename Container::value_type
value_type;
1515 typedef typename Container::size_type
size_type;
1523 class Q:
public std::queue<T, Container> {
1525 void splice_end(Container&& lst) {
1526 this->c.splice(this->c.end(), std::move(lst));
1528 void unsplice_beginning(Container& lst) {
1529 lst.splice(lst.begin(), this->c, this->c.begin());
1532 mutable Thread::Mutex mutex;
1535 void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
1538 if (!m2.trylock()) {
1543 #ifdef CGU_USE_SCHED_YIELD
1553 Container temp{obj};
1554 Thread::Mutex::Lock lock{mutex};
1556 q.splice_end(std::move(temp));
1566 temp.push_back(std::move(obj));
1567 Thread::Mutex::Lock lock{mutex};
1569 q.splice_end(std::move(temp));
1572 template<
class... Args>
1573 void emplace(Args&&... args) {
1575 temp.emplace_back(std::forward<Args>(args)...);
1576 Thread::Mutex::Lock lock{mutex};
1578 q.splice_end(std::move(temp));
1582 Thread::Mutex::Lock lock{mutex};
1583 if (q.empty())
throw AsyncQueuePopError();
1589 Thread::Mutex::Lock lock{mutex};
1590 if (q.empty())
throw AsyncQueuePopError();
1591 obj = std::move(q.front());
1601 Thread::Mutex::Lock lock{mutex};
1602 if (q.empty())
throw AsyncQueuePopError();
1604 q.unsplice_beginning(temp);
1606 obj = std::move(temp.front());
1610 Thread::Mutex::Lock lock{mutex};
1611 if (q.empty())
throw AsyncQueuePopError();
1615 bool empty()
const {
1616 Thread::Mutex::Lock lock{mutex};
1621 Thread::Mutex::Lock lock{mutex};
1626 if (
this != &other) {
1627 lock2(mutex, other.mutex);
1636 lock2(mutex, rhs.mutex);
1646 Thread::Mutex::Lock lock{mutex};
1647 q = std::move(rhs.q);
1658 Thread::Mutex::Lock lock{mutex};
1671 template <
class T,
class Allocator>
1672 class AsyncQueueDispatch<T, std::list<T, Allocator> > {
1674 typedef std::list<T, Allocator> Container;
1675 typedef typename Container::value_type
value_type;
1676 typedef typename Container::size_type
size_type;
1684 class Q:
public std::queue<T, Container> {
1686 void splice_end(Container&& lst) {
1687 this->c.splice(this->c.end(), std::move(lst));
1689 void unsplice_beginning(Container& lst) {
1690 lst.splice(lst.begin(), this->c, this->c.begin());
1693 mutable Thread::Mutex mutex;
1697 void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
1700 if (!m2.trylock()) {
1705 #ifdef CGU_USE_SCHED_YIELD
1715 Container temp{obj};
1716 Thread::Mutex::Lock lock{mutex};
1718 q.splice_end(std::move(temp));
1729 temp.push_back(std::move(obj));
1730 Thread::Mutex::Lock lock{mutex};
1732 q.splice_end(std::move(temp));
1736 template<
class... Args>
1737 void emplace(Args&&... args) {
1739 temp.emplace_back(std::forward<Args>(args)...);
1740 Thread::Mutex::Lock lock{mutex};
1742 q.splice_end(std::move(temp));
1747 Thread::Mutex::Lock lock{mutex};
1748 if (q.empty())
throw AsyncQueuePopError();
1754 Thread::Mutex::Lock lock{mutex};
1755 if (q.empty())
throw AsyncQueuePopError();
1756 obj = std::move(q.front());
1766 Thread::Mutex::Lock lock{mutex};
1767 if (q.empty())
throw AsyncQueuePopError();
1769 q.unsplice_beginning(temp);
1771 obj = std::move(temp.front());
1775 Thread::Mutex::Lock lock{mutex};
1776 while (q.empty()) cond.
wait(mutex);
1777 Thread::CancelBlock b;
1783 Thread::Mutex::Lock lock{mutex};
1784 while (q.empty()) cond.
wait(mutex);
1785 Thread::CancelBlock b;
1786 obj = std::move(q.front());
1793 bool cancelstate_restored =
false;
1795 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
1800 pthread_setcancelstate(old_state, &ignore);
1801 cancelstate_restored =
true;
1802 Thread::Mutex::TrackLock lock{mutex};
1803 while (q.empty()) cond.
wait(mutex);
1804 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ignore);
1805 cancelstate_restored =
false;
1807 q.unsplice_beginning(temp);
1809 obj = std::move(temp.front());
1810 pthread_setcancelstate(old_state, &ignore);
1820 if (!cancelstate_restored) {
1821 pthread_setcancelstate(old_state, &ignore);
1830 Thread::Mutex::Lock lock{mutex};
1834 Thread::CancelBlock b;
1843 Thread::Mutex::Lock lock{mutex};
1847 Thread::CancelBlock b;
1848 obj = std::move(q.front());
1858 bool cancelstate_restored =
false;
1860 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
1865 pthread_setcancelstate(old_state, &ignore);
1866 cancelstate_restored =
true;
1867 Thread::Mutex::TrackLock lock{mutex};
1871 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ignore);
1872 cancelstate_restored =
false;
1874 q.unsplice_beginning(temp);
1876 obj = std::move(temp.front());
1877 pthread_setcancelstate(old_state, &ignore);
1888 if (!cancelstate_restored) {
1889 pthread_setcancelstate(old_state, &ignore);
1896 Thread::Mutex::Lock lock{mutex};
1897 if (q.empty())
throw AsyncQueuePopError();
1901 bool empty()
const {
1902 Thread::Mutex::Lock lock{mutex};
1907 Thread::Mutex::Lock lock{mutex};
1912 if (
this != &other) {
1913 lock2(mutex, other.mutex);
1918 if (!other.q.empty()) other.cond.broadcast();
1924 lock2(mutex, rhs.mutex);
1935 Thread::Mutex::Lock lock{mutex};
1936 q = std::move(rhs.q);
1946 q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1949 Thread::Mutex::Lock lock{mutex};
1955 #endif // CGU_USE_INHERITABLE_QUEUE