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>>();
404 _max_elements {max_elements} {
412 template<
class... Args>
414 std::lock_guard ul {_lock};
420 if (_queue.size() == _max_elements) {
424 _queue.emplace_back(std::forward<Args>(
args)...);
435 return _continue && !_queue.empty();
444 template<
class Rep,
class Period>
446 std::unique_lock ul {_lock};
449 return util::false_v<status_t>;
452 while (_queue.empty()) {
453 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
454 return util::false_v<status_t>;
458 auto val = std::move(_queue.front());
459 _queue.erase(std::begin(_queue));
470 std::unique_lock ul {_lock};
473 return util::false_v<status_t>;
476 while (_queue.empty()) {
480 return util::false_v<status_t>;
484 auto val = std::move(_queue.front());
485 _queue.erase(std::begin(_queue));
503 std::lock_guard lg {_lock};
520 bool _continue {
true};
521 std::uint32_t _max_elements;
524 std::condition_variable _cv;
526 std::vector<T> _queue;
589 auto tmp = ptr.owner->ref();
606 return *
this = std::move(*ptr.owner->ref());
620 std::swap(
owner, ptr.owner);
634 operator bool()
const {
635 return owner !=
nullptr;
642 std::lock_guard lg {
owner->_lock};
644 if (!--
owner->_count) {
646 (*this)->~element_type();
677 template<
class FC,
class FD>
679 _construct {std::forward<FC>(fc)},
680 _destruct {std::forward<FD>(fd)} {
689 std::lock_guard lg {_lock};
693 if (_construct(*
reinterpret_cast<element_type *
>(_object_buf.data())) != 0) {
694 return ptr_t {
nullptr};
707 std::array<std::uint8_t,
sizeof(
element_type)> _object_buf;
709 std::uint32_t _count;
720 template<
class T,
class F_Construct,
class F_Destruct>
723 std::forward<F_Construct>(fc),
724 std::forward<F_Destruct>(fd)
737 using mail_t = std::shared_ptr<mail_raw_t>;
758 template<
class... Args>
760 T(std::forward<Args>(
args)...),
778 inline auto lock(
const std::weak_ptr<void> &wp) {
779 return std::reinterpret_pointer_cast<typename T::element_type>(wp.lock());
785 class mail_raw_t:
public std::enable_shared_from_this<mail_raw_t> {
791 using event_t = std::shared_ptr<post_t<event_t<T>>>;
797 using queue_t = std::shared_ptr<post_t<queue_t<T>>>;
807 std::lock_guard lg {
mutex};
811 return lock<event_t<T>>(it->second);
814 auto post = std::make_shared<typename event_t<T>::element_type>(shared_from_this());
815 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
828 std::lock_guard lg {
mutex};
832 return lock<queue_t<T>>(it->second);
835 auto post = std::make_shared<typename queue_t<T>::element_type>(shared_from_this(), 32);
836 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
845 std::lock_guard lg {
mutex};
848 auto &weak = it->second;
850 if (weak.expired()) {
860 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:785
queue_t< T > queue(const std::string_view &id)
Create a typed queue channel from the raw mailbox.
Definition thread_safe.h:827
std::map< std::string, std::weak_ptr< void >, std::less<> > id_to_post
Posted objects keyed by cleanup identifier.
Definition thread_safe.h:860
void cleanup()
Run cleanup for completed asynchronous work.
Definition thread_safe.h:844
std::mutex mutex
Mutex protecting the map of live posted objects.
Definition thread_safe.h:858
std::shared_ptr< post_t< queue_t< T > > > queue_t
Mailbox-backed queue wrapper for typed messages.
Definition thread_safe.h:797
event_t< T > event(const std::string_view &id)
Create a typed event channel from the raw mailbox.
Definition thread_safe.h:806
std::shared_ptr< post_t< event_t< T > > > event_t
Mailbox-backed event wrapper for a typed value.
Definition thread_safe.h:791
Wrapper that posts cleanup work to a mailbox when destroyed.
Definition thread_safe.h:750
mail_t mail
Mailbox kept alive until the posted object is destroyed.
Definition thread_safe.h:764
post_t(mail_t mail, Args &&...args)
Construct a message-posting wrapper around an existing type.
Definition thread_safe.h:759
Thread-safe queue with blocking and shutdown-aware consumers.
Definition thread_safe.h:391
queue_t(std::uint32_t max_elements=32)
Construct a bounded blocking queue.
Definition thread_safe.h:403
void stop()
Shut down the queue and wake blocked consumers.
Definition thread_safe.h:502
status_t pop(std::chrono::duration< Rep, Period > delay)
Remove and return the next queued item, waiting when requested.
Definition thread_safe.h:445
util::optional_t< T > status_t
Value type stored in the queue.
Definition thread_safe.h:396
bool peek()
Inspect the next queued value without popping it.
Definition thread_safe.h:434
status_t pop()
Remove and return the next queued item, waiting when requested.
Definition thread_safe.h:469
std::vector< T > & unsafe()
Return the wrapped pointer without synchronization checks.
Definition thread_safe.h:495
void raise(Args &&...args)
Notify waiters that a new event value is available.
Definition thread_safe.h:413
bool running() const
Return whether the queue is still running.
Definition thread_safe.h:515
Shared object storage with custom construction and destruction hooks.
Definition thread_safe.h:533
std::function< int(element_type &)> construct_f
Callback signature used to construct the protected object.
Definition thread_safe.h:543
std::function< void(element_type &)> destruct_f
Callback signature used to destroy the protected object.
Definition thread_safe.h:547
T element_type
Object type stored in shared protected storage.
Definition thread_safe.h:538
shared_t(FC &&fc, FD &&fd)
Construct a shared protected object with custom close and destruction hooks.
Definition thread_safe.h:678
ptr_t ref()
Return a shared reference to the protected object.
Definition thread_safe.h:688
Functions for handling command line arguments.
Definition entry_handler.cpp:37
Handles process-wide communication.
Definition globals.h:34
Pointer wrapper state protected by synchronization.
Definition thread_safe.h:552
element_type * operator->()
Access the shared protected object.
Definition thread_safe.h:666
ptr_t(shared_t *owner)
Construct a reference bound to a shared protected object.
Definition thread_safe.h:564
ptr_t(const ptr_t &ptr) noexcept
Copy a shared-object reference without locking the protected object.
Definition thread_safe.h:583
void release()
Release the COM or platform reference owned by the pointer.
Definition thread_safe.h:641
ptr_t(ptr_t &&ptr) noexcept
Move a shared-object reference without locking the protected object.
Definition thread_safe.h:573
element_type * get() const
Return the currently wrapped value or handle.
Definition thread_safe.h:657
shared_t * owner
Shared object that owns the protected value.
Definition thread_safe.h:553
ptr_t & operator=(const ptr_t &ptr) noexcept
Assign state from another instance while preserving ownership semantics.
Definition thread_safe.h:599
ptr_t & operator=(ptr_t &&ptr) noexcept
Assign state from another instance while preserving ownership semantics.
Definition thread_safe.h:615
std::shared_ptr< mail_raw_t > mail_t
Shared mailbox handle used by event and queue wrappers.
Definition thread_safe.h:737
auto make_shared(F_Construct &&fc, F_Destruct &&fd)
Create a shared object or message.
Definition thread_safe.h:721
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
auto lock(const std::weak_ptr< void > &wp)
Acquire the underlying lock or keyed mutex.
Definition thread_safe.h:778
void cleanup(mail_raw_t *)
Run cleanup for completed asynchronous work.
Definition thread_safe.h:866
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:1385