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<
class Rep,
class Period>
64 status_t pop(std::chrono::duration<Rep, Period> delay) {
65 std::unique_lock ul {_lock};
68 return util::false_v<status_t>;
72 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
73 return util::false_v<status_t>;
77 auto val = std::move(_status);
78 _status = util::false_v<status_t>;
84 std::unique_lock ul {_lock};
87 return util::false_v<status_t>;
94 return util::false_v<status_t>;
102 template<
class Rep,
class Period>
103 status_t view(std::chrono::duration<Rep, Period> delay) {
104 std::unique_lock ul {_lock};
107 return util::false_v<status_t>;
111 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
112 return util::false_v<status_t>;
120 return _continue && (bool) _status;
124 std::lock_guard lg {_lock};
132 std::lock_guard lg {_lock};
136 _status = util::false_v<status_t>;
139 [[nodiscard]]
bool running()
const {
144 bool _continue {
true};
145 status_t _status {util::false_v<status_t>};
147 std::condition_variable _cv;
154 using status_t = util::optional_t<T>;
156 void ring(
const status_t &status) {
157 std::lock_guard lg(_lock);
164 void ring(status_t &&status) {
165 std::lock_guard lg(_lock);
167 _status = std::move(status);
172 template<
class Rep,
class Period>
173 auto wait_for(
const std::chrono::duration<Rep, Period> &rel_time) {
174 std::unique_lock ul(_lock);
176 return _cv.wait_for(ul, rel_time, [
this]() {
181 template<
class Rep,
class Period,
class Pred>
182 auto wait_for(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
183 std::unique_lock ul(_lock);
185 return _cv.wait_for(ul, rel_time, [
this, &pred]() {
186 return _rang || pred();
190 template<
class Rep,
class Period>
191 auto wait_until(
const std::chrono::duration<Rep, Period> &rel_time) {
192 std::unique_lock ul(_lock);
194 return _cv.wait_until(ul, rel_time, [
this]() {
199 template<
class Rep,
class Period,
class Pred>
200 auto wait_until(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
201 std::unique_lock ul(_lock);
203 return _cv.wait_until(ul, rel_time, [
this, &pred]() {
204 return _rang || pred();
209 std::unique_lock ul(_lock);
210 _cv.wait(ul, [
this]() {
216 auto wait(Pred &&pred) {
217 std::unique_lock ul(_lock);
218 _cv.wait(ul, [
this, &pred]() {
219 return _rang || pred();
223 const status_t &status()
const {
232 _status = status_t {};
238 std::condition_variable _cv;
240 status_t _status {util::false_v<status_t>};
255 using status_t = util::optional_t<T>;
257 queue_t(std::uint32_t max_elements = 32):
258 _max_elements {max_elements} {
261 template<
class... Args>
262 void raise(Args &&...
args) {
263 std::lock_guard ul {_lock};
269 if (_queue.size() == _max_elements) {
273 _queue.emplace_back(std::forward<Args>(
args)...);
279 return _continue && !_queue.empty();
282 template<
class Rep,
class Period>
283 status_t pop(std::chrono::duration<Rep, Period> delay) {
284 std::unique_lock ul {_lock};
287 return util::false_v<status_t>;
290 while (_queue.empty()) {
291 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
292 return util::false_v<status_t>;
296 auto val = std::move(_queue.front());
297 _queue.erase(std::begin(_queue));
303 std::unique_lock ul {_lock};
306 return util::false_v<status_t>;
309 while (_queue.empty()) {
313 return util::false_v<status_t>;
317 auto val = std::move(_queue.front());
318 _queue.erase(std::begin(_queue));
323 std::vector<T> &unsafe() {
328 std::lock_guard lg {_lock};
335 [[nodiscard]]
bool running()
const {
340 bool _continue {
true};
341 std::uint32_t _max_elements;
344 std::condition_variable _cv;
346 std::vector<T> _queue;
352 using element_type = T;
354 using construct_f = std::function<int(element_type &)>;
355 using destruct_f = std::function<void(element_type &)>;
379 auto tmp = ptr.owner->ref();
390 return *
this = std::move(*ptr.owner->ref());
398 std::swap(owner, ptr.owner);
409 operator bool()
const {
410 return owner !=
nullptr;
414 std::lock_guard lg {owner->_lock};
416 if (!--owner->_count) {
417 owner->_destruct(*get());
418 (*this)->~element_type();
424 element_type *get()
const {
425 return reinterpret_cast<element_type *
>(owner->_object_buf.data());
428 element_type *operator->() {
429 return reinterpret_cast<element_type *
>(owner->_object_buf.data());
433 template<
class FC,
class FD>
435 _construct {std::forward<FC>(fc)},
436 _destruct {std::forward<FD>(fd)} {
439 [[nodiscard]] ptr_t ref() {
440 std::lock_guard lg {_lock};
443 new (_object_buf.data()) element_type;
444 if (_construct(*
reinterpret_cast<element_type *
>(_object_buf.data()))) {
445 return ptr_t {
nullptr};
455 construct_f _construct;
456 destruct_f _destruct;
458 std::array<std::uint8_t,
sizeof(element_type)> _object_buf;
460 std::uint32_t _count;
500 class mail_raw_t:
public std::enable_shared_from_this<mail_raw_t> {
503 using event_t = std::shared_ptr<post_t<event_t<T>>>;
506 using queue_t = std::shared_ptr<post_t<queue_t<T>>>;
509 event_t<T> event(
const std::string_view &
id) {
510 std::lock_guard lg {mutex};
512 auto it = id_to_post.find(
id);
513 if (it != std::end(id_to_post)) {
514 return lock<event_t<T>>(it->second);
517 auto post = std::make_shared<typename event_t<T>::element_type>(shared_from_this());
518 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
524 queue_t<T> queue(
const std::string_view &
id) {
525 std::lock_guard lg {mutex};
527 auto it = id_to_post.find(
id);
528 if (it != std::end(id_to_post)) {
529 return lock<queue_t<T>>(it->second);
532 auto post = std::make_shared<typename queue_t<T>::element_type>(shared_from_this(), 32);
533 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> {std::string {
id}, post});
539 std::lock_guard lg {mutex};
541 for (
auto it = std::begin(id_to_post); it != std::end(id_to_post); ++it) {
542 auto &weak = it->second;
544 if (weak.expired()) {
545 id_to_post.erase(it);
554 std::map<std::string, std::weak_ptr<void>, std::less<>> id_to_post;
Definition thread_safe.h:480