23 using status_t = util::optional_t<T>;
25 template<
class... Args>
26 void raise(Args &&...
args) {
27 std::lock_guard lg {_lock};
32 if constexpr (std::is_same_v<std::optional<T>, status_t>) {
33 _status = std::make_optional<T>(std::forward<Args>(
args)...);
35 _status = status_t {std::forward<Args>(
args)...};
43 std::unique_lock ul {_lock};
46 return util::false_v<status_t>;
53 return util::false_v<status_t>;
57 auto val = std::move(_status);
58 _status = util::false_v<status_t>;
63 template<
typename Rep,
typename Period>
64 status_t pop(std::chrono::duration<Rep, Period> delay) {
65 std::unique_lock ul {_lock};
67 if (
bool success = _cv.wait_for(ul, delay, [
this] {
68 return (bool) _status || !_continue;
70 !success || !_continue) {
71 return util::false_v<status_t>;
74 auto val = std::move(_status);
81 std::unique_lock ul {_lock};
84 return util::false_v<status_t>;
91 return util::false_v<status_t>;
99 template<
class Rep,
class Period>
100 status_t view(std::chrono::duration<Rep, Period> delay) {
101 std::unique_lock ul {_lock};
104 return util::false_v<status_t>;
108 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
109 return util::false_v<status_t>;
117 return _continue && (bool) _status;
121 std::lock_guard lg {_lock};
129 std::lock_guard lg {_lock};
133 _status = util::false_v<status_t>;
136 [[nodiscard]]
bool running()
const {
141 bool _continue {
true};
142 status_t _status {util::false_v<status_t>};
144 std::condition_variable _cv;
151 using status_t = util::optional_t<T>;
153 void ring(
const status_t &status) {
154 std::lock_guard lg(_lock);
161 void ring(status_t &&status) {
162 std::lock_guard lg(_lock);
164 _status = std::move(status);
169 template<
class Rep,
class Period>
170 auto wait_for(
const std::chrono::duration<Rep, Period> &rel_time) {
171 std::unique_lock ul(_lock);
173 return _cv.wait_for(ul, rel_time, [
this]() {
178 template<
class Rep,
class Period,
class Pred>
179 auto wait_for(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
180 std::unique_lock ul(_lock);
182 return _cv.wait_for(ul, rel_time, [
this, &pred]() {
183 return _rang || pred();
187 template<
class Rep,
class Period>
188 auto wait_until(
const std::chrono::duration<Rep, Period> &rel_time) {
189 std::unique_lock ul(_lock);
191 return _cv.wait_until(ul, rel_time, [
this]() {
196 template<
class Rep,
class Period,
class Pred>
197 auto wait_until(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
198 std::unique_lock ul(_lock);
200 return _cv.wait_until(ul, rel_time, [
this, &pred]() {
201 return _rang || pred();
206 std::unique_lock ul(_lock);
207 _cv.wait(ul, [
this]() {
213 auto wait(Pred &&pred) {
214 std::unique_lock ul(_lock);
215 _cv.wait(ul, [
this, &pred]() {
216 return _rang || pred();
220 const status_t &status()
const {
229 _status = status_t {};
235 std::condition_variable _cv;
237 status_t _status {util::false_v<status_t>};
252 using status_t = util::optional_t<T>;
254 queue_t(std::uint32_t max_elements = 32):
255 _max_elements {max_elements} {
258 template<
class... Args>
259 void raise(Args &&...
args) {
260 std::lock_guard ul {_lock};
266 if (_queue.size() == _max_elements) {
270 _queue.emplace_back(std::forward<Args>(
args)...);
276 return _continue && !_queue.empty();
279 template<
class Rep,
class Period>
280 status_t pop(std::chrono::duration<Rep, Period> delay) {
281 std::unique_lock ul {_lock};
284 return util::false_v<status_t>;
287 while (_queue.empty()) {
288 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
289 return util::false_v<status_t>;
293 auto val = std::move(_queue.front());
294 _queue.erase(std::begin(_queue));
300 std::unique_lock ul {_lock};
303 return util::false_v<status_t>;
306 while (_queue.empty()) {
310 return util::false_v<status_t>;
314 auto val = std::move(_queue.front());
315 _queue.erase(std::begin(_queue));
320 std::vector<T> &unsafe() {
325 std::lock_guard lg {_lock};
332 [[nodiscard]]
bool running()
const {
337 bool _continue {
true};
338 std::uint32_t _max_elements;
341 std::condition_variable _cv;
343 std::vector<T> _queue;
349 using element_type = T;
351 using construct_f = std::function<int(element_type &)>;
352 using destruct_f = std::function<void(element_type &)>;
376 auto tmp = ptr.owner->ref();
387 return *
this = std::move(*ptr.owner->ref());
395 std::swap(owner, ptr.owner);
406 operator bool()
const {
407 return owner !=
nullptr;
411 std::lock_guard lg {owner->_lock};
413 if (!--owner->_count) {
414 owner->_destruct(*get());
415 (*this)->~element_type();
421 element_type *get()
const {
422 return reinterpret_cast<element_type *
>(owner->_object_buf.data());
425 element_type *operator->() {
426 return reinterpret_cast<element_type *
>(owner->_object_buf.data());
430 template<
class FC,
class FD>
432 _construct {std::forward<FC>(fc)},
433 _destruct {std::forward<FD>(fd)} {
436 [[nodiscard]] ptr_t ref() {
437 std::lock_guard lg {_lock};
440 new (_object_buf.data()) element_type;
441 if (_construct(*
reinterpret_cast<element_type *
>(_object_buf.data())) != 0) {
442 return ptr_t {
nullptr};
452 construct_f _construct;
453 destruct_f _destruct;
455 std::array<std::uint8_t,
sizeof(element_type)> _object_buf;
457 std::uint32_t _count;
497 class mail_raw_t:
public std::enable_shared_from_this<mail_raw_t> {
500 using event_t = std::shared_ptr<post_t<event_t<T>>>;
503 using queue_t = std::shared_ptr<post_t<queue_t<T>>>;
506 event_t<T> event(
const std::string_view &
id) {
507 std::lock_guard lg {mutex};
509 auto it = id_to_post.find(
id);
510 if (it != std::end(id_to_post)) {
511 return lock<event_t<T>>(it->second);
514 auto post = std::make_shared<typename event_t<T>::element_type>(shared_from_this());
515 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
521 queue_t<T> queue(
const std::string_view &
id) {
522 std::lock_guard lg {mutex};
524 auto it = id_to_post.find(
id);
525 if (it != std::end(id_to_post)) {
526 return lock<queue_t<T>>(it->second);
529 auto post = std::make_shared<typename queue_t<T>::element_type>(shared_from_this(), 32);
530 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
536 std::lock_guard lg {mutex};
538 for (
auto it = std::begin(id_to_post); it != std::end(id_to_post); ++it) {
539 auto &weak = it->second;
541 if (weak.expired()) {
542 id_to_post.erase(it);
551 std::map<std::string, std::weak_ptr<void>, std::less<>> id_to_post;
Definition thread_safe.h:477