Nazara Engine  0.4
A fast, complete, cross-platform API designed for game development
Signal.hpp
1 // Copyright (C) 2017 Jérôme Leclercq
2 // This file is part of the "Nazara Engine - Core module"
3 // For conditions of distribution and use, see copyright notice in Config.hpp
4 
5 #pragma once
6 
7 #ifndef NAZARA_SIGNAL_HPP
8 #define NAZARA_SIGNAL_HPP
9 
10 #include <functional>
11 #include <memory>
12 #include <vector>
13 
14 #define NazaraDetailSignal(Keyword, SignalName, ...) using SignalName ## Type = Nz::Signal<__VA_ARGS__>; \
15  Keyword SignalName ## Type SignalName
16 
17 #define NazaraSignal(SignalName, ...) NazaraDetailSignal(mutable, SignalName, __VA_ARGS__)
18 #define NazaraStaticSignal(SignalName, ...) NazaraDetailSignal(static, SignalName, __VA_ARGS__)
19 #define NazaraStaticSignalImpl(Class, SignalName) Class :: SignalName ## Type Class :: SignalName
20 
21 #define NazaraSlotType(Class, SignalName) Class::SignalName ## Type::ConnectionGuard
22 #define NazaraSlot(Class, SignalName, SlotName) NazaraSlotType(Class, SignalName) SlotName
23 
24 namespace Nz
25 {
26  template<typename... Args>
27  class Signal
28  {
29  public:
30  using Callback = std::function<void(Args...)>;
31  class Connection;
32  class ConnectionGuard;
33 
34  Signal();
35  Signal(const Signal&) = delete;
36  Signal(Signal&& signal) noexcept;
37  ~Signal() = default;
38 
39  void Clear();
40 
41  Connection Connect(const Callback& func);
42  Connection Connect(Callback&& func);
43  template<typename O> Connection Connect(O& object, void (O::*method)(Args...));
44  template<typename O> Connection Connect(O* object, void (O::*method)(Args...));
45  template<typename O> Connection Connect(const O& object, void (O::*method)(Args...) const);
46  template<typename O> Connection Connect(const O* object, void (O::*method)(Args...) const);
47 
48  void operator()(Args... args) const;
49 
50  Signal& operator=(const Signal&) = delete;
51  Signal& operator=(Signal&& signal) noexcept;
52 
53  private:
54  struct Slot;
55 
56  using SlotPtr = std::shared_ptr<Slot>;
57  using SlotList = std::vector<SlotPtr>;
58  using SlotListIndex = typename SlotList::size_type;
59 
60  struct Slot
61  {
62  Slot(Signal* me) :
63  signal(me)
64  {
65  }
66 
67  Callback callback;
68  Signal* signal;
69  SlotListIndex index;
70  };
71 
72  void Disconnect(const SlotPtr& slot) noexcept;
73 
74  SlotList m_slots;
75  mutable SlotListIndex m_slotIterator;
76  };
77 
78  template<typename... Args>
79  class Signal<Args...>::Connection
80  {
81  using BaseClass = Signal<Args...>;
82  friend BaseClass;
83 
84  public:
85  Connection() = default;
86  Connection(const Connection& connection) = default;
87  Connection(Connection&& connection) noexcept;
88  ~Connection() = default;
89 
90  template<typename... ConnectArgs>
91  void Connect(BaseClass& signal, ConnectArgs&&... args);
92  void Disconnect() noexcept;
93 
94  bool IsConnected() const;
95 
96  Connection& operator=(const Connection& connection) = default;
97  Connection& operator=(Connection&& connection) noexcept;
98 
99  private:
100  Connection(const SlotPtr& slot);
101 
102  std::weak_ptr<Slot> m_ptr;
103  };
104 
105  template<typename... Args>
106  class Signal<Args...>::ConnectionGuard
107  {
108  using BaseClass = Signal<Args...>;
109  using Connection = typename BaseClass::Connection;
110 
111  public:
112  ConnectionGuard() = default;
113  ConnectionGuard(const Connection& connection);
114  ConnectionGuard(const ConnectionGuard& connection) = delete;
115  ConnectionGuard(Connection&& connection);
116  ConnectionGuard(ConnectionGuard&& connection) noexcept = default;
117  ~ConnectionGuard();
118 
119  template<typename... ConnectArgs>
120  void Connect(BaseClass& signal, ConnectArgs&&... args);
121  void Disconnect() noexcept;
122 
123  Connection& GetConnection();
124 
125  bool IsConnected() const;
126 
127  ConnectionGuard& operator=(const Connection& connection);
128  ConnectionGuard& operator=(const ConnectionGuard& connection) = delete;
129  ConnectionGuard& operator=(Connection&& connection);
130  ConnectionGuard& operator=(ConnectionGuard&& connection) noexcept;
131 
132  private:
133  Connection m_connection;
134  };
135 }
136 
137 #include <Nazara/Core/Signal.inl>
138 
139 #endif // NAZARA_SIGNAL_HPP
TODO: Inherit SoundEmitter from Node.
Definition: Algorithm.hpp:12
void Clear()
Clears the list of actions attached to the signal.
Definition: Signal.inl:45
Core class that represents a signal, a list of objects waiting for its message.
Definition: Signal.hpp:27
void operator()(Args... args) const
Applies the list of arguments to every callback functions.
Definition: Signal.inl:171
Core class that represents a RAII for a connection attached to a signal.
Definition: Signal.hpp:106
Signal()
Constructs a Signal object by default.
Definition: Signal.inl:23
Connection Connect(const Callback &func)
Connects a function to the signal.
Definition: Signal.inl:59
Core class that represents a connection attached to a signal.
Definition: Signal.hpp:79