diff --git a/configure.ac b/configure.ac index 25703b313..3935dc342 100644 --- a/configure.ac +++ b/configure.ac @@ -328,6 +328,7 @@ RB_CHK_SYSHEADER([map], [MAP]) RB_CHK_SYSHEADER([set], [SET]) RB_CHK_SYSHEADER([list], [LIST]) RB_CHK_SYSHEADER([stack], [STACK]) +RB_CHK_SYSHEADER([queue], [QUEUE]) RB_CHK_SYSHEADER([deque], [DEQUE]) RB_CHK_SYSHEADER([array], [ARRAY]) RB_CHK_SYSHEADER([vector], [VECTOR]) diff --git a/include/ircd/ctx.h b/include/ircd/ctx.h index 46470972e..c840ea9c6 100644 --- a/include/ircd/ctx.h +++ b/include/ircd/ctx.h @@ -105,6 +105,7 @@ using ctx::timeout; #include "ctx/context.h" #include "ctx/prof.h" #include "ctx/dock.h" +#include "ctx/queue.h" #include "ctx/mutex.h" #include "ctx/shared_state.h" #include "ctx/promise.h" diff --git a/include/ircd/ctx/queue.h b/include/ircd/ctx/queue.h new file mode 100644 index 000000000..e4285bc31 --- /dev/null +++ b/include/ircd/ctx/queue.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#define HAVE_IRCD_CTX_QUEUE_H + +namespace ircd { +namespace ctx { + +template +class queue +{ + struct dock dock; + std::queue q; + + public: + auto empty() const { return q.empty(); } + auto size() const { return q.size(); } + + // Consumer interface; waits for item and std::move() it off the queue + template T pop_until(time_point&&); + template T pop_for(const duration &); + T pop(); + + // Producer interface; emplace item on the queue and notify consumer + template void emplace(args&&...); + void push(const T &); + void push(T &&) noexcept; + + queue() = default; + ~queue() noexcept; +}; + +template +queue::~queue() +noexcept +{ + assert(q.empty()); +} + +template +void +queue::push(T &&t) +noexcept +{ + q.push(std::move(t)); + dock.notify(); +} + +template +void +queue::push(const T &t) +{ + q.push(t); + dock.notify(); +} + +template +template +void +queue::emplace(args&&... a) +{ + q.emplace(std::forward(a)...); + dock.notify(); +} + +template +T +queue::pop() +{ + dock.wait([this] + { + return !q.empty(); + }); + + const scope pop([this] + { + q.pop(); + }); + + auto &ret(q.front()); + return std::move(ret); +} + +template +template +T +queue::pop_for(const duration &dur) +{ + const auto status(dock.wait_for(dur, [this] + { + return !q.empty(); + })); + + if(status == cv_status::timeout) + throw timeout(); + + const scope pop([this] + { + q.pop(); + }); + + auto &ret(q.front()); + return std::move(ret); +} + +template +template +T +queue::pop_until(time_point&& tp) +{ + const auto status(dock.wait_until(tp, [this] + { + return !q.empty(); + })); + + if(status == cv_status::timeout) + throw timeout(); + + const scope pop([this] + { + q.pop(); + }); + + auto &ret(q.front()); + return std::move(ret); +} + +} // namespace ctx +} // namespace ircd diff --git a/include/rb/requires.h b/include/rb/requires.h index bb1db2a01..b9758bac5 100644 --- a/include/rb/requires.h +++ b/include/rb/requires.h @@ -79,6 +79,7 @@ extern "C" { #include