21 using status_t = util::optional_t<T>;
23 template <
class... Args>
25 raise(Args &&...
args) {
26 std::lock_guard lg { _lock };
31 if constexpr (std::is_same_v<std::optional<T>, status_t>) {
32 _status = std::make_optional<T>(std::forward<Args>(
args)...);
35 _status = status_t { std::forward<Args>(
args)... };
44 std::unique_lock ul { _lock };
47 return util::false_v<status_t>;
54 return util::false_v<status_t>;
58 auto val = std::move(_status);
59 _status = util::false_v<status_t>;
64 template <
class Rep,
class Period>
66 pop(std::chrono::duration<Rep, Period> delay) {
67 std::unique_lock ul { _lock };
70 return util::false_v<status_t>;
74 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
75 return util::false_v<status_t>;
79 auto val = std::move(_status);
80 _status = util::false_v<status_t>;
87 std::unique_lock ul { _lock };
90 return util::false_v<status_t>;
97 return util::false_v<status_t>;
105 template <
class Rep,
class Period>
107 view(std::chrono::duration<Rep, Period> delay) {
108 std::unique_lock ul { _lock };
111 return util::false_v<status_t>;
115 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
116 return util::false_v<status_t>;
125 return _continue && (bool) _status;
130 std::lock_guard lg { _lock };
139 std::lock_guard lg { _lock };
143 _status = util::false_v<status_t>;
152 bool _continue {
true };
153 status_t _status { util::false_v<status_t> };
155 std::condition_variable _cv;
162 using status_t = util::optional_t<T>;
165 ring(
const status_t &status) {
166 std::lock_guard lg(_lock);
174 ring(status_t &&status) {
175 std::lock_guard lg(_lock);
177 _status = std::move(status);
182 template <
class Rep,
class Period>
184 wait_for(
const std::chrono::duration<Rep, Period> &rel_time) {
185 std::unique_lock ul(_lock);
187 return _cv.wait_for(ul, rel_time, [
this]() {
return _rang; });
190 template <
class Rep,
class Period,
class Pred>
192 wait_for(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
193 std::unique_lock ul(_lock);
195 return _cv.wait_for(ul, rel_time, [
this, &pred]() {
return _rang || pred(); });
198 template <
class Rep,
class Period>
200 wait_until(
const std::chrono::duration<Rep, Period> &rel_time) {
201 std::unique_lock ul(_lock);
203 return _cv.wait_until(ul, rel_time, [
this]() {
return _rang; });
206 template <
class Rep,
class Period,
class Pred>
208 wait_until(
const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
209 std::unique_lock ul(_lock);
211 return _cv.wait_until(ul, rel_time, [
this, &pred]() {
return _rang || pred(); });
216 std::unique_lock ul(_lock);
217 _cv.wait(ul, [
this]() {
return _rang; });
220 template <
class Pred>
223 std::unique_lock ul(_lock);
224 _cv.wait(ul, [
this, &pred]() {
return _rang || pred(); });
239 _status = status_t {};
245 std::condition_variable _cv;
247 status_t _status { util::false_v<status_t> };
248 bool _rang {
false };
263 using status_t = util::optional_t<T>;
265 queue_t(std::uint32_t max_elements = 32):
266 _max_elements { max_elements } {}
268 template <
class... Args>
270 raise(Args &&...
args) {
271 std::lock_guard ul { _lock };
277 if (_queue.size() == _max_elements) {
281 _queue.emplace_back(std::forward<Args>(
args)...);
288 return _continue && !_queue.empty();
291 template <
class Rep,
class Period>
293 pop(std::chrono::duration<Rep, Period> delay) {
294 std::unique_lock ul { _lock };
297 return util::false_v<status_t>;
300 while (_queue.empty()) {
301 if (!_continue || _cv.wait_for(ul, delay) == std::cv_status::timeout) {
302 return util::false_v<status_t>;
306 auto val = std::move(_queue.front());
307 _queue.erase(std::begin(_queue));
314 std::unique_lock ul { _lock };
317 return util::false_v<status_t>;
320 while (_queue.empty()) {
324 return util::false_v<status_t>;
328 auto val = std::move(_queue.front());
329 _queue.erase(std::begin(_queue));
341 std::lock_guard lg { _lock };
354 bool _continue {
true };
355 std::uint32_t _max_elements;
358 std::condition_variable _cv;
360 std::vector<T> _queue;
366 using element_type = T;
368 using construct_f = std::function<int(element_type &)>;
369 using destruct_f = std::function<void(element_type &)>;
380 owner { ptr.owner } {
385 owner { ptr.owner } {
390 auto tmp = ptr.owner->ref();
395 operator=(
const ptr_t &ptr)
noexcept {
402 return *
this = std::move(*ptr.owner->ref());
406 operator=(
ptr_t &&ptr)
noexcept {
411 std::swap(owner, ptr.owner);
422 operator bool()
const {
423 return owner !=
nullptr;
428 std::lock_guard lg { owner->_lock };
430 if (!--owner->_count) {
431 owner->_destruct(*get());
432 (*this)->~element_type();
440 return reinterpret_cast<element_type *
>(owner->_object_buf.data());
445 return reinterpret_cast<element_type *
>(owner->_object_buf.data());
449 template <
class FC,
class FD>
451 _construct { std::forward<FC>(fc) }, _destruct { std::forward<FD>(fd) } {}
454 std::lock_guard lg { _lock };
457 new (_object_buf.data()) element_type;
458 if (_construct(*
reinterpret_cast<element_type *
>(_object_buf.data()))) {
459 return ptr_t {
nullptr };
465 return ptr_t {
this };
469 construct_f _construct;
470 destruct_f _destruct;
472 std::array<std::uint8_t,
sizeof(element_type)> _object_buf;
474 std::uint32_t _count;
513 class mail_raw_t:
public std::enable_shared_from_this<mail_raw_t> {
516 using event_t = std::shared_ptr<post_t<event_t<T>>>;
519 using queue_t = std::shared_ptr<post_t<queue_t<T>>>;
523 event(
const std::string_view &
id) {
524 std::lock_guard lg { mutex };
526 auto it = id_to_post.find(
id);
527 if (it != std::end(id_to_post)) {
528 return lock<event_t<T>>(it->second);
531 auto post = std::make_shared<typename event_t<T>::element_type>(shared_from_this());
532 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> { std::string {
id }, post });
539 queue(
const std::string_view &
id) {
540 std::lock_guard lg { mutex };
542 auto it = id_to_post.find(
id);
543 if (it != std::end(id_to_post)) {
544 return lock<queue_t<T>>(it->second);
547 auto post = std::make_shared<typename queue_t<T>::element_type>(shared_from_this(), 32);
548 id_to_post.emplace(std::pair<std::string, std::weak_ptr<void>> { std::string {
id }, post });
555 std::lock_guard lg { mutex };
557 for (
auto it = std::begin(id_to_post); it != std::end(id_to_post); ++it) {
558 auto &weak = it->second;
560 if (weak.expired()) {
561 id_to_post.erase(it);
570 std::map<std::string, std::weak_ptr<void>, std::less<>> id_to_post;
Definition thread_safe.h:494