]> git.stg.codes - stg.git/blob - include/stg/subscriptions.h
1486e62d9003d1086edee1a0c25e3963513eb186
[stg.git] / include / stg / subscriptions.h
1 #pragma once
2
3 #include <list>
4 #include <functional>
5 #include <mutex>
6
7 namespace STG
8 {
9
10 template <typename... Ts>
11 class Subscriptions
12 {
13     public:
14         using Callback = std::function<void (Ts...)>;
15         using Callbacks = std::list<Callback>;
16
17         class Connection
18         {
19             public:
20                 Connection(Subscriptions& s, typename Callbacks::iterator i) noexcept
21                     : m_subscriptions(s), m_iterator(i), m_connected(true)
22                 {}
23                 ~Connection()
24                 {
25                     disconnect();
26                 }
27
28                 void disconnect() noexcept
29                 {
30                     if (!m_connected)
31                         return;
32                     m_subscriptions.remove(m_iterator);
33                     m_connected = false;
34                 }
35             private:
36                 Subscriptions& m_subscriptions;
37                 typename Callbacks::iterator m_iterator;
38                 bool m_connected;
39         };
40
41         template <typename F>
42         Connection add(F&& f)
43         {
44             std::lock_guard lock(m_mutex);
45             return Connection(*this, m_callbacks.insert(m_callbacks.end(), Callback(std::forward<F>(f))));
46         }
47
48         template <typename C, typename... T2s>
49         Connection add(C& c, void (C::*m)(T2s...))
50         {
51             return add([&c, m](Ts&&... values){ (c.*m)(std::forward<Ts>(values)...); });
52         }
53
54         void remove(typename Callbacks::iterator i)
55         {
56             std::lock_guard lock(m_mutex);
57             m_callbacks.erase(i);
58         }
59
60         void notify(Ts&&... values)
61         {
62             std::lock_guard lock(m_mutex);
63             for (auto& cb : m_callbacks)
64                 cb(values...);
65         }
66
67         bool empty() const noexcept
68         {
69             std::lock_guard lock(m_mutex);
70             return m_callbacks.empty();
71         }
72
73         size_t size() const noexcept
74         {
75             std::lock_guard lock(m_mutex);
76             return m_callbacks.size();
77         }
78
79     private:
80         mutable std::mutex m_mutex;
81         Callbacks m_callbacks;
82 };
83
84 }