OSSIA
Open Scenario System for Interactive Application
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
callback_container.hpp
Go to the documentation of this file.
1#pragma once
2#include <ossia/detail/config.hpp>
3
4#include <ossia/detail/mutex.hpp>
5
6#if defined(__cpp_exceptions)
7#include <exception>
8#endif
9#include <list>
10#include <mutex>
11
16namespace ossia
17{
18
19#if defined(__cpp_exceptions)
25struct OSSIA_EXPORT invalid_callback_error final : public std::exception
26{
27 ~invalid_callback_error() override;
28 invalid_callback_error();
29 const char* what() const noexcept override;
30};
31#endif
32
33template <typename T>
46{
47 using mutex = OSSIA_CALLBACK_CONTAINER_MUTEX;
48 using lock_guard = std::lock_guard<mutex>;
49
50public:
51 callback_container() = default;
53 {
54 lock_guard lck{other.m_mutx};
55 m_callbacks = other.m_callbacks;
56 }
58 {
59 lock_guard lck{other.m_mutx};
60 m_callbacks = std::move(other.m_callbacks);
61 }
62 callback_container& operator=(const callback_container& other)
63 {
64 lock_guard lck{other.m_mutx};
65 m_callbacks = other.m_callbacks;
66 return *this;
67 }
68 callback_container& operator=(callback_container&& other) noexcept
69 {
70 lock_guard lck{other.m_mutx};
71 m_callbacks = std::move(other.m_callbacks);
72 return *this;
73 }
74
75 virtual ~callback_container() = default;
76
82 using impl = std::list<T>;
83 using iterator = typename impl::iterator;
84
90 iterator add_callback(T&& callback)
91 {
92 if(callback)
93 {
94 lock_guard lck{m_mutx};
95 auto it = m_callbacks.insert(m_callbacks.begin(), std::move(callback));
96 if(m_callbacks.size() == 1)
97 on_first_callback_added();
98 return it;
99 }
100 else
101 {
102#if defined(__cpp_exceptions)
103 throw invalid_callback_error{};
104#else
105 return {};
106#endif
107 }
108 }
109
114 void remove_callback(iterator it)
115 {
116 lock_guard lck{m_mutx};
117 if(m_callbacks.size() == 1)
118 on_removing_last_callback();
119
120 m_callbacks.erase(it);
121 }
122
126 void replace_callback(iterator it, T&& cb)
127 {
128 lock_guard lck{m_mutx};
129 *m_callbacks.erase(it, it) = std::move(cb);
130 }
131
132 void replace_callbacks(impl&& cbs)
133 {
134 lock_guard lck{m_mutx};
135 m_callbacks = std::move(cbs);
136 }
137
138 class disabled_callback
139 {
140 public:
141 explicit disabled_callback(callback_container& self)
142 : self{self}
143 , old_callbacks{self.m_callbacks}
144 {
145 }
146
147 ~disabled_callback() { self.replace_callbacks(std::move(old_callbacks)); }
148
149 private:
150 callback_container& self;
151 callback_container::impl old_callbacks;
152 };
153
154 disabled_callback disable_callback(iterator it)
155 {
156 lock_guard lck{m_mutx};
157 disabled_callback dis{*this};
158
159 // TODO should we also call on_removing_last_blah ?
160 // I don't think so : it's supposed to be a short operation
161 m_callbacks.erase(it);
162 return dis;
163 }
164
169 std::size_t callback_count() const
170 {
171 lock_guard lck{m_mutx};
172 return m_callbacks.size();
173 }
174
179 bool callbacks_empty() const
180 {
181 lock_guard lck{m_mutx};
182 return m_callbacks.empty();
183 }
184
189 template <typename... Args>
190 void send(Args&&... args)
191 {
192 lock_guard lck{m_mutx};
193 for(auto& callback : m_callbacks)
194 {
195 if(callback)
196 callback(std::forward<Args>(args)...);
197 }
198 }
199
204 {
205 lock_guard lck{m_mutx};
206 if(!m_callbacks.empty())
207 on_removing_last_callback();
208 m_callbacks.clear();
209 }
210
211protected:
222 virtual void on_first_callback_added() { }
223
229 virtual void on_removing_last_callback() { }
230
231 //private:
232public:
233 impl m_callbacks TS_GUARDED_BY(m_mutx);
234 mutable mutex m_mutx;
235};
236
237}
The callback_container class.
Definition callback_container.hpp:46
void callbacks_clear()
clear Clears callbacks.
Definition callback_container.hpp:203
virtual void on_removing_last_callback()
on_removing_last_callback
Definition callback_container.hpp:229
bool callbacks_empty() const
callbacks_empty
Definition callback_container.hpp:179
void replace_callback(iterator it, T &&cb)
Replaces an existing callback with another function.
Definition callback_container.hpp:126
std::list< T > impl
impl How the callbackas are stored. A list is used since iterators to other callbacks must not be inv...
Definition callback_container.hpp:82
virtual void on_first_callback_added()
on_first_callback_added
Definition callback_container.hpp:222
std::size_t callback_count() const
callback_count
Definition callback_container.hpp:169
void remove_callback(iterator it)
remove_callback Removes a callback identified by an iterator.
Definition callback_container.hpp:114
iterator add_callback(T &&callback)
add_callback Add a new callback.
Definition callback_container.hpp:90
void send(Args &&... args)
send Trigger all callbacks
Definition callback_container.hpp:190
Definition git_info.h:7