17 #ifndef CPP_MATE_SIGNAL_HPP
18 #define CPP_MATE_SIGNAL_HPP
20 #include <CppMate/Checkers.hpp>
22 #include <unordered_set>
44 using Lambda = std::function<void(
const S& sender)>;
50 Signal(
const S& sender): _sender(sender) {}
59 inline void subscribe(
const T& instance,
void (T::* method)(
const S&))
const {
60 addReceiver(&instance, *
reinterpret_cast<Method*
>(&method));
71 inline void subscribe(std::shared_ptr<T> instance,
void (T::* method)(
const S&))
const {
72 checkArg(instance.get());
73 addReceiver(std::weak_ptr<void>(instance), *
reinterpret_cast<Method*
>(&method));
96 inline bool unsubscribe(
const T& instance,
void (T::* method)(
const S&))
const {
97 return removeReceiver(&instance, *
reinterpret_cast<Method*
>(&method));
108 inline bool unsubscribe(std::shared_ptr<T> instance,
void (T::* method)(
const S&))
const {
109 checkArg(instance.get());
110 return removeReceiver(std::weak_ptr<void>(instance), *
reinterpret_cast<Method*
>(&method));
128 inline bool hasSubscriber(
const T& instance,
void (T::* method)(
const S&))
const {
129 return hasReceiver(&instance, *
reinterpret_cast<Method*
>(&method));
139 inline bool hasSubscriber(std::shared_ptr<T> instance,
void (T::* method)(
const S&))
const {
140 return instance.get() && hasReceiver(std::weak_ptr<void>(instance), *
reinterpret_cast<Method*
>(&method));
149 return subscriber && hasReceiver(subscriber);
156 bool isEmpty()
const {
return _receivers.empty(); }
168 for (
auto it = std::begin(_receivers); it != std::end(_receivers);) {
169 const auto& receiver = *it;
170 receiver(_sender) ? ++it : it = _receivers.erase(it);
182 using Method = void(*)(
const void*,
const S&);
184 struct ReceiverHasher {
185 size_t operator()(
const Receiver& receiver)
const {
return receiver.getHash(); }
188 template<
typename... T>
189 inline bool hasReceiver(T&&... args)
const {
190 return _receivers.find(Receiver(std::forward<T>(args)...)) != _receivers.end();
193 template<
typename... T>
194 inline void addReceiver(T&&... args)
const {
195 _receivers.emplace(std::forward<T>(args)...);
198 template<
typename... T>
199 inline bool removeReceiver(T&&... args)
const {
200 return _receivers.erase(Receiver(std::forward<T>(args)...)) > 0;
204 mutable std::unordered_set<Receiver, ReceiverHasher> _receivers;
214 _method(reinterpret_cast<decltype(_method)>(method)) {}
216 Receiver(
const std::weak_ptr<void>&& instance, Method method):
219 _method(reinterpret_cast<decltype(_method)>(method)),
220 _instancePtr(std::move(instance)) {}
225 _method(reinterpret_cast<decltype(_method)>(receiver))
234 _lambda(std::move(receiver)) {}
237 return _type == other._type
238 && _method == other._method
239 && getInstance() == other.getInstance();
246 case Receiver::Type::Method:
247 return callMethod(sender);
248 case Receiver::Type::Function:
249 return callFunction(sender);
250 case Receiver::Type::Lambda:
251 return callLambda(sender);
257 return std::hash<decltype(_type)>{}(_type) ^ std::hash<decltype(_method)>{}(_method) ^ std::hash<decltype(_instance)>{}(getInstance());
261 enum class Type: uint8_t {
267 const void* getInstance()
const {
268 return _instance ? _instance : _instancePtr.lock().get();
271 bool callMethod(
const S& sender)
const {
272 const auto* instance = getInstance();
276 reinterpret_cast<Method
>(_method)(instance, sender);
280 bool callFunction(
const S& sender)
const {
281 reinterpret_cast<Function>(_method)(sender);
285 bool callLambda(
const S& sender)
const {
291 const void* _instance;
292 std::weak_ptr<void> _instancePtr;
Definition: Signal.hpp:209
bool operator==(const Receiver &other) const
Definition: Signal.hpp:236
Receiver(const void *instance, Method method)
Definition: Signal.hpp:211
size_t getHash() const
Definition: Signal.hpp:256
bool operator()(const S &sender) const
Definition: Signal.hpp:244
Receiver(Function receiver)
Definition: Signal.hpp:222
Receiver(Lambda receiver)
Definition: Signal.hpp:230
bool operator!=(const Receiver &other) const
Definition: Signal.hpp:242
Receiver(const std::weak_ptr< void > &&instance, Method method)
Definition: Signal.hpp:216
Represents signal.
Definition: Signal.hpp:33
Signal(const S &sender)
Constructor.
Definition: Signal.hpp:50
void emit()
Emits signal.
Definition: Signal.hpp:167
void unsubscribeAll()
Clear all subscribers.
Definition: Signal.hpp:177
bool unsubscribe(const T &instance, void(T::*method)(const S &)) const
Unsubscribes from the signal.
Definition: Signal.hpp:96
bool unsubscribe(Function subscriber) const
Unsubscribes function from the signal.
Definition: Signal.hpp:119
bool hasSubscriber(std::shared_ptr< T > instance, void(T::*method)(const S &)) const
Indicates that the receiver is already subscribed to the signal.
Definition: Signal.hpp:139
void subscribe(std::shared_ptr< T > instance, void(T::*method)(const S &)) const
Subscribes method of instance to the signal. The subscription is unique.
Definition: Signal.hpp:71
void subscribe(const T &instance, void(T::*method)(const S &)) const
Subscribes method of instance to the signal. The subscription is unique.
Definition: Signal.hpp:59
size_t getSubscribersCount() const
Returns number of recveivers.
Definition: Signal.hpp:162
std::function< void(const S &sender)> Lambda
Definition: Signal.hpp:44
bool unsubscribe(std::shared_ptr< T > instance, void(T::*method)(const S &)) const
Unsubscribes from the signal.
Definition: Signal.hpp:108
bool isEmpty() const
Indicates that subsciprion is empty.
Definition: Signal.hpp:156
bool hasSubscriber(Function subscriber) const
Indicates that the receiver is already subscribed to the signal.
Definition: Signal.hpp:148
bool hasSubscriber(const T &instance, void(T::*method)(const S &)) const
Indicates that the receiver is already subscribed to the signal.
Definition: Signal.hpp:128
void(*)(const S &) Function
Definition: Signal.hpp:39
void subscribe(Function subscriber) const
Subscribes function to the signal.
Definition: Signal.hpp:81
void subscribe(Lambda subscriber) const
Subscribes lambda expression to the signal.
Definition: Signal.hpp:87
Definition: BinaryData.hpp:28