HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
notifier.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "required.hpp"
8#include "unfair_recursive_mutex.hpp"
9#include <mutex>
10#include <vector>
11#include <tuple>
12#include <functional>
13
14namespace tt {
15
16template<typename T>
17class notifier {
18};
19
27template<typename Result, typename... Args>
28class notifier<Result(Args...)> {
29public:
30 static_assert(std::is_same_v<Result,void>, "Result of a notifier must be void.");
31
32 using callback_type = std::function<Result(Args const &...)>;
34
42 void subscribe_ptr(callback_ptr_type const &callback_ptr) noexcept
43 {
44 auto lock = std::scoped_lock(_mutex);
45
46 ttlet i = std::find_if(_callbacks.cbegin(), _callbacks.cend(), [&callback_ptr](ttlet &item) {
47 return item.lock() == callback_ptr;
48 });
49
50 if (i == _callbacks.cend()) {
51 _callbacks.emplace_back(callback_ptr);
52 }
53 }
54
63 template<typename Callback>
64 [[nodiscard]] callback_ptr_type subscribe(Callback &&callback) noexcept
65 {
66 auto callback_ptr = std::make_shared<callback_type>(std::forward<decltype(callback)>(callback));
67
68 auto lock = std::scoped_lock(_mutex);
69 _callbacks.emplace_back(callback_ptr);
70 return callback_ptr;
71 }
72
76 void unsubscribe(callback_ptr_type const &callback_ptr) noexcept
77 {
78 auto lock = std::scoped_lock(_mutex);
79
80 ttlet new_end = std::remove_if(_callbacks.begin(), _callbacks.end(), [&callback_ptr](ttlet &item) {
81 return item.expired() || item.lock() == callback_ptr;
82 });
83 _callbacks.erase(new_end, _callbacks.cend());
84 }
85
89 void operator()(Args const &...args) const noexcept
90 {
91 auto lock = std::scoped_lock(_mutex);
92 tt_assert(!_executing_callbacks);
93 _executing_callbacks = true;
94
95 auto i = _callbacks.begin();
96 while (i != _callbacks.end()) {
97 if (auto callback = i->lock()) {
98 (*callback)(args...);
99 ++i;
100
101 } else {
102 i = _callbacks.erase(i);
103 }
104 };
105 _executing_callbacks = false;
106 }
107
108private:
109 mutable unfair_recursive_mutex _mutex;
110 mutable bool _executing_callbacks = false;
112};
113
114} // namespace tt
Definition notifier.hpp:17
void unsubscribe(callback_ptr_type const &callback_ptr) noexcept
Remove a callback from the notifier.
Definition notifier.hpp:76
void operator()(Args const &...args) const noexcept
Call the subscribed callbacks with the given arguments.
Definition notifier.hpp:89
void subscribe_ptr(callback_ptr_type const &callback_ptr) noexcept
Add a callback to the notifier.
Definition notifier.hpp:42
callback_ptr_type subscribe(Callback &&callback) noexcept
Add a callback to the notifier.
Definition notifier.hpp:64
An unfair recursive-mutex This is a fast implementation of a recursive-mutex which does not fairly ar...
Definition unfair_recursive_mutex.hpp:32
T find_if(T... args)
T forward(T... args)
T remove_if(T... args)