diff --git a/ostd/channel.hh b/ostd/channel.hh index 7c851e0..1e1108b 100644 --- a/ostd/channel.hh +++ b/ostd/channel.hh @@ -14,6 +14,8 @@ #include #include +#include "ostd/generic_condvar.hh" + namespace ostd { struct channel_error: std::logic_error { @@ -66,62 +68,6 @@ struct channel { } private: - struct cond_iface { - cond_iface() {} - virtual ~cond_iface() {} - virtual void notify_one() = 0; - virtual void notify_all() = 0; - virtual void wait(std::unique_lock &) = 0; - }; - - template - struct cond_impl: cond_iface { - cond_impl(): p_cond() {} - template - cond_impl(F &func): p_cond(func()) {} - void notify_one() { - p_cond.notify_one(); - } - void notify_all() { - p_cond.notify_all(); - } - void wait(std::unique_lock &l) { - p_cond.wait(l); - } - private: - C p_cond; - }; - - struct cond { - cond() { - new (reinterpret_cast(&p_condbuf)) - cond_impl(); - } - template - cond(F &func) { - new (reinterpret_cast(&p_condbuf)) - cond_impl>(func); - } - ~cond() { - reinterpret_cast(&p_condbuf)->~cond_iface(); - } - - void notify_one() { - reinterpret_cast(&p_condbuf)->notify_one(); - } - void notify_all() { - reinterpret_cast(&p_condbuf)->notify_all(); - } - void wait(std::unique_lock &l) { - reinterpret_cast(&p_condbuf)->wait(l); - } - - private: - std::aligned_storage_t) - ), alignof(std::condition_variable)> p_condbuf; - }; - struct impl { impl() { } @@ -174,7 +120,7 @@ private: std::list p_messages; mutable std::mutex p_lock; - cond p_cond; + generic_condvar p_cond; bool p_closed = false; }; diff --git a/ostd/generic_condvar.hh b/ostd/generic_condvar.hh new file mode 100644 index 0000000..bdb5b18 --- /dev/null +++ b/ostd/generic_condvar.hh @@ -0,0 +1,81 @@ +/* A generic condvar that can store any other condvar as a single type. + * + * This file is part of OctaSTD. See COPYING.md for futher information. + */ + +#ifndef OSTD_GENERIC_CONDVAR_HH +#define OSTD_GENERIC_CONDVAR_HH + +#include +#include +#include + +namespace ostd { + +namespace detail { + struct cond_iface { + cond_iface() {} + virtual ~cond_iface() {} + virtual void notify_one() = 0; + virtual void notify_all() = 0; + virtual void wait(std::unique_lock &) = 0; + }; + + template + struct cond_impl: cond_iface { + cond_impl(): p_cond() {} + template + cond_impl(F &func): p_cond(func()) {} + void notify_one() { + p_cond.notify_one(); + } + void notify_all() { + p_cond.notify_all(); + } + void wait(std::unique_lock &l) { + p_cond.wait(l); + } + private: + C p_cond; + }; +} /* namespace detail */ + +struct generic_condvar { + generic_condvar() { + new (reinterpret_cast(&p_condbuf)) + detail::cond_impl(); + } + template + generic_condvar(F &&func) { + new (reinterpret_cast(&p_condbuf)) + detail::cond_impl>(func); + } + + generic_condvar(generic_condvar const &) = delete; + generic_condvar(generic_condvar &&) = delete; + generic_condvar &operator=(generic_condvar const &) = delete; + generic_condvar &operator=(generic_condvar &&) = delete; + + ~generic_condvar() { + reinterpret_cast(&p_condbuf)->~cond_iface(); + } + + void notify_one() { + reinterpret_cast(&p_condbuf)->notify_one(); + } + void notify_all() { + reinterpret_cast(&p_condbuf)->notify_all(); + } + void wait(std::unique_lock &l) { + reinterpret_cast(&p_condbuf)->wait(l); + } + +private: + std::aligned_storage_t) + )> p_condbuf; +}; + +} /* namespace ostd */ + +#endif