10#include <condition_variable>
36 template<
class... Args>
38 std::lock_guard lg {_lock};
43 if constexpr (std::is_same_v<std::optional<T>,
status_t>) {
44 _status = std::make_optional<T>(std::forward<Args>(
args)...);
58 std::lock_guard lg {_lock};
60 return util::false_v<status_t>;
62 auto val = std::move(_status);
63 _status = util::false_v<status_t>;
74 std::unique_lock ul {_lock};
77 return util::false_v<status_t>;
84 return util::false_v<status_t>;
88 auto val = std::move(_status);
89 _status = util::false_v<status_t>;
100 template<
typename Rep,
typename Period>
102 std::unique_lock ul {_lock};
104 if (
bool success = _cv.wait_for(ul, delay, [
this] {
105 return (bool) _status || !_continue;
107 !success || !_continue) {
108 return util::false_v<status_t>;
111 auto val = std::move(_status);
112 _status = util::false_v<status_t>;
123 std::unique_lock ul {_lock};
126 return util::false_v<status_t>;
133 return util::false_v<status_t>;
147 template<
class Rep,
class Period>
149 std::unique_lock ul {_lock};
152 return util::false_v<status_t>;
156 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
157 return util::false_v<status_t>;
170 return _continue && (bool) _status;
177 std::lock_guard lg {_lock};
188 std::lock_guard lg {_lock};
192 _status = util::false_v<status_t>;
205 bool _continue {
true};
206 status_t _status {util::false_v<status_t>};
208 std::condition_variable _cv;
229 std::lock_guard lg(_lock);
242 std::lock_guard lg(_lock);
244 _status = std::move(
status);
255 template<
class Rep,
class Period>
256 auto wait_for(
const std::chrono::duration<Rep, Period> &rel_time) {
257 std::unique_lock ul(_lock);
259 return _cv.wait_for(ul, rel_time, [
this]() {
271 template<
class Rep,
class Period,
class Pred>
272 auto wait_for(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
273 std::unique_lock ul(_lock);
275 return _cv.wait_for(ul, rel_time, [
this, &pred]() {
276 return _rang || pred();
286 template<
class Rep,
class Period>
287 auto wait_until(
const std::chrono::duration<Rep, Period> &rel_time) {
288 std::unique_lock ul(_lock);
290 return _cv.wait_until(ul, rel_time, [
this]() {
302 template<
class Rep,
class Period,
class Pred>
303 auto wait_until(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
304 std::unique_lock ul(_lock);
306 return _cv.wait_until(ul, rel_time, [
this, &pred]() {
307 return _rang || pred();
317 std::unique_lock ul(_lock);
318 _cv.wait(ul, [
this]() {
331 std::unique_lock ul(_lock);
332 _cv.wait(ul, [
this, &pred]() {
333 return _rang || pred();
365 std::condition_variable _cv;
367 status_t _status {util::false_v<status_t>};
375 using alarm_t = std::shared_ptr<alarm_raw_t<T>>;
384 return std::make_shared<alarm_raw_t<T>>();
413 _max_elements {max_elements},
414 _overflow_policy {overflow} {
424 template<
class... Args>
426 std::lock_guard ul {_lock};
432 if (_queue.size() >= _max_elements) {
439 _queue.emplace_back(std::forward<Args>(
args)...);
450 return _continue && !_queue.empty();
459 template<
class Rep,
class Period>
461 std::unique_lock ul {_lock};
464 return util::false_v<status_t>;
467 while (_queue.empty()) {
468 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
469 return util::false_v<status_t>;
473 auto val = std::move(_queue.front());
474 _queue.erase(std::begin(_queue));
485 std::unique_lock ul {_lock};
488 return util::false_v<status_t>;
491 while (_queue.empty()) {
495 return util::false_v<status_t>;
499 auto val = std::move(_queue.front());
500 _queue.erase(std::begin(_queue));
518 std::lock_guard lg {_lock};
535 bool _continue {
true};
536 std::uint32_t _max_elements;
539 std::condition_variable _cv;
541 std::vector<T> _queue;
605 auto tmp = ptr.owner->ref();
622 return *
this = std::move(*ptr.owner->ref());
636 std::swap(
owner, ptr.owner);
650 operator bool()
const {
651 return owner !=
nullptr;
658 std::lock_guard lg {
owner->_lock};
660 if (!--
owner->_count) {
662 (*this)->~element_type();
693 template<
class FC,
class FD>
695 _construct {std::forward<FC>(fc)},
696 _destruct {std::forward<FD>(fd)} {
704 [[nodiscard]] ptr_t
ref() {
705 std::lock_guard lg {_lock};
709 if (_construct(*
reinterpret_cast<element_type *
>(_object_buf.data())) != 0) {
710 return ptr_t {
nullptr};
723 std::array<std::uint8_t,
sizeof(
element_type)> _object_buf;
725 std::uint32_t _count;
736 template<
class T,
class F_Construct,
class F_Destruct>
739 std::forward<F_Construct>(fc),
740 std::forward<F_Destruct>(fd)
753 using mail_t = std::shared_ptr<mail_raw_t>;
774 template<
class... Args>
776 T(std::forward<Args>(
args)...),
794 inline auto lock(
const std::weak_ptr<void> &wp) {
795 return std::reinterpret_pointer_cast<typename T::element_type>(wp.lock());
801 class mail_raw_t:
public std::enable_shared_from_this<mail_raw_t> {
807 using event_t = std::shared_ptr<post_t<event_t<T>>>;
813 using queue_t = std::shared_ptr<post_t<queue_t<T>>>;
823 std::lock_guard lg {
mutex};
830 auto post = std::make_shared<typename event_t<T>::element_type>(shared_from_this());
831 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
844 std::lock_guard lg {
mutex};
851 auto post = std::make_shared<typename queue_t<T>::element_type>(shared_from_this(), 32);
852 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
861 std::lock_guard lg {
mutex};
864 auto &weak = it->second;
866 if (weak.expired()) {
876 std::map<std::string, std::weak_ptr<void>, std::less<>>
id_to_post;
Alarm primitive used to wait for and raise shutdown-style signals.
Definition thread_safe.h:216
void reset()
Reset the object to its initial empty state.
Definition thread_safe.h:358
status_t & status()
Return or update the current status value.
Definition thread_safe.h:351
auto wait_for(const std::chrono::duration< Rep, Period > &rel_time)
Wait for for.
Definition thread_safe.h:256
auto wait()
Block until the event is raised.
Definition thread_safe.h:316
auto wait_until(const std::chrono::duration< Rep, Period > &rel_time, Pred &&pred)
Wait for until.
Definition thread_safe.h:303
auto wait_for(const std::chrono::duration< Rep, Period > &rel_time, Pred &&pred)
Wait for for.
Definition thread_safe.h:272
void ring(const status_t &status)
Mark the alarm as rung and wake waiting threads.
Definition thread_safe.h:228
auto wait(Pred &&pred)
Block until the event is raised and the predicate accepts the state.
Definition thread_safe.h:330
util::optional_t< T > status_t
Status value carried by the alarm.
Definition thread_safe.h:221
const status_t & status() const
Return or update the current status value.
Definition thread_safe.h:342
void ring(status_t &&status)
Mark the alarm as rung and wake waiting threads.
Definition thread_safe.h:241
auto wait_until(const std::chrono::duration< Rep, Period > &rel_time)
Wait for until.
Definition thread_safe.h:287
Thread-safe event value that blocks readers until a value is raised.
Definition thread_safe.h:24
status_t pop()
Remove and return the next queued item, waiting when requested.
Definition thread_safe.h:73
util::optional_t< T > status_t
Status value stored in the event.
Definition thread_safe.h:29
status_t view(std::chrono::duration< Rep, Period > delay)
Read the current value without removing it from the queue.
Definition thread_safe.h:148
bool running() const
Return whether the queue is still running.
Definition thread_safe.h:200
status_t view()
Read the current value without removing it from the queue.
Definition thread_safe.h:122
status_t try_pop()
Try to remove and return the next queued item without any further wait.
Definition thread_safe.h:57
void reset()
Reset the object to its initial empty state.
Definition thread_safe.h:187
bool peek()
Inspect the next queued value without popping it.
Definition thread_safe.h:169
void stop()
Raise the alarm and wake all waiting threads.
Definition thread_safe.h:176
void raise(Args &&...args)
Notify waiters that a new event value is available.
Definition thread_safe.h:37
status_t pop(std::chrono::duration< Rep, Period > delay)
Remove and return the next queued item, waiting when requested.
Definition thread_safe.h:101
Mailbox backing store for events, queues, and posted cleanup objects.
Definition thread_safe.h:801
queue_t< T > queue(const std::string_view &id)
Create a typed queue channel from the raw mailbox.
Definition thread_safe.h:843
std::map< std::string, std::weak_ptr< void >, std::less<> > id_to_post
Posted objects keyed by cleanup identifier.
Definition thread_safe.h:876
void cleanup()
Run cleanup for completed asynchronous work.
Definition thread_safe.h:860
std::mutex mutex
Mutex protecting the map of live posted objects.
Definition thread_safe.h:874
std::shared_ptr< post_t< queue_t< T > > > queue_t
Mailbox-backed queue wrapper for typed messages.
Definition thread_safe.h:813
event_t< T > event(const std::string_view &id)
Create a typed event channel from the raw mailbox.
Definition thread_safe.h:822
std::shared_ptr< post_t< event_t< T > > > event_t
Mailbox-backed event wrapper for a typed value.
Definition thread_safe.h:807
post_t(mail_t mail, Args &&...args)
Construct a message-posting wrapper around an existing type.
Definition thread_safe.h:775
void stop()
Shut down the queue and wake blocked consumers.
Definition thread_safe.h:517
overflow_policy_e
Behavior when raise() is called with the queue already at its bound.
Definition thread_safe.h:401
@ reject
Refuse the new item, leaving existing queued items intact.
Definition thread_safe.h:403
@ drop_oldest
Clear the queue and accept the new item (current default behavior).
Definition thread_safe.h:402
status_t pop(std::chrono::duration< Rep, Period > delay)
Remove and return the next queued item, waiting when requested.
Definition thread_safe.h:460
util::optional_t< T > status_t
Value type stored in the queue.
Definition thread_safe.h:396
bool raise(Args &&...args)
Notify waiters that a new event value may be available.
Definition thread_safe.h:425
bool peek()
Inspect the next queued value without popping it.
Definition thread_safe.h:449
queue_t(std::uint32_t max_elements=32, overflow_policy_e overflow=overflow_policy_e::drop_oldest)
Construct a bounded blocking queue.
Definition thread_safe.h:412
status_t pop()
Remove and return the next queued item, waiting when requested.
Definition thread_safe.h:484
std::vector< T > & unsafe()
Return the wrapped pointer without synchronization checks.
Definition thread_safe.h:510
bool running() const
Return whether the queue is still running.
Definition thread_safe.h:530
Shared object storage with custom construction and destruction hooks.
Definition thread_safe.h:549
std::function< int(element_type &)> construct_f
Definition thread_safe.h:559
std::function< void(element_type &)> destruct_f
Definition thread_safe.h:563
audio_ctx_t element_type
Definition thread_safe.h:554
shared_t(FC &&fc, FD &&fd)
Construct a shared protected object with custom close and destruction hooks.
Definition thread_safe.h:694
ptr_t ref()
Return a shared reference to the protected object.
Definition thread_safe.h:704
Functions for handling command line arguments.
Definition entry_handler.cpp:41
Handles process-wide communication.
Definition globals.h:34
Pointer wrapper state protected by synchronization.
Definition thread_safe.h:568
element_type * operator->()
Access the shared protected object.
Definition thread_safe.h:682
ptr_t(shared_t *owner)
Construct a reference bound to a shared protected object.
Definition thread_safe.h:580
ptr_t(const ptr_t &ptr) noexcept
Copy a shared-object reference without locking the protected object.
Definition thread_safe.h:599
void release()
Release the COM or platform reference owned by the pointer.
Definition thread_safe.h:657
ptr_t(ptr_t &&ptr) noexcept
Move a shared-object reference without locking the protected object.
Definition thread_safe.h:589
element_type * get() const
Return the currently wrapped value or handle.
Definition thread_safe.h:673
shared_t * owner
Shared object that owns the protected value.
Definition thread_safe.h:569
ptr_t & operator=(const ptr_t &ptr) noexcept
Assign state from another instance while preserving ownership semantics.
Definition thread_safe.h:615
ptr_t & operator=(ptr_t &&ptr) noexcept
Assign state from another instance while preserving ownership semantics.
Definition thread_safe.h:631
std::shared_ptr< mail_raw_t > mail_t
Shared mailbox handle used by event and queue wrappers.
Definition thread_safe.h:753
auto make_shared(F_Construct &&fc, F_Destruct &&fd)
Create a shared object or message.
Definition thread_safe.h:737
alarm_t< T > make_alarm()
Create a alarm object or message.
Definition thread_safe.h:383
std::shared_ptr< alarm_raw_t< T > > alarm_t
Shared alarm primitive used for cross-thread shutdown signals.
Definition thread_safe.h:375
event_t< bool > signal_t
Boolean alarm used as a simple signal.
Definition thread_safe.h:747
auto lock(const std::weak_ptr< void > &wp)
Acquire the underlying lock or keyed mutex.
Definition thread_safe.h:794
void cleanup(mail_raw_t *)
Run cleanup for completed asynchronous work.
Definition thread_safe.h:882
Declarations for utility functions.
either_t<(std::is_same_v< T, bool >||is_pointer_v< T >), T, std::optional< T > > optional_t
Optional trait value used by endian serialization helpers.
Definition utility.h:1390