ToyMaker Game Engine 0.0.2
ToyMaker is a game engine developed and maintained by Zoheb Shujauddin.
Loading...
Searching...
No Matches
signals.hpp
Go to the documentation of this file.
1
11
17
18#ifndef TOYMAKERENGINE_SIGNALS_H
19#define TOYMAKERENGINE_SIGNALS_H
20
21#include <memory>
22#include <cassert>
23#include <functional>
24#include <string>
25#include <map>
26#include <set>
27
28namespace ToyMaker {
29 class SignalTracker;
30 class ISignalObserver;
31 class ISignal;
32 template <typename ...TArgs>
33 class SignalObserver_;
34 template <typename ...TArgs>
35 class Signal_;
36 template <typename ...TArgs>
37 class SignalObserver;
38 template <typename ...TArgs>
39 class Signal;
40
42
48 class ISignal {
49 public:
55 virtual void registerObserver(std::weak_ptr<ISignalObserver> observer)=0;
56 };
57
64 template <typename ...TArgs>
65 class Signal_: public ISignal {
66 public:
72 void emit (TArgs... args);
73
79 void registerObserver(std::weak_ptr<ISignalObserver> observer) override;
80
81 private:
88 Signal_() = default;
89
94 std::set<
95 std::weak_ptr<SignalObserver_<TArgs...>>,
96 std::owner_less<std::weak_ptr<SignalObserver_<TArgs...>>>
98
99 friend class SignalTracker;
100 friend class Signal<TArgs...>;
101 };
102
111 template <typename ...TArgs>
113 public:
119 void operator() (TArgs... args);
120 private:
126 SignalObserver_(std::function<void(TArgs...)> callback);
127
132 std::function<void(TArgs...)> mStoredFunction {};
133 friend class SignalTracker;
134 friend class SignalObserver<TArgs...>;
135 };
136
165 public:
171
177 SignalTracker(const SignalTracker& other);
178
186
193
202
210 void connect(const std::string& theirSignal, const std::string& ourObserver, SignalTracker& other);
211
212 private:
213
224 template <typename ...TArgs>
225 std::shared_ptr<Signal_<TArgs...>> declareSignal(
226 const std::string& signalName
227 );
228
237 template <typename ...TArgs>
238 std::shared_ptr<SignalObserver_<TArgs...>> declareSignalObserver(
239 const std::string& observerName,
240 std::function<void(TArgs...)> callbackFunction
241 );
242
247 void garbageCollection();
248
253 std::unordered_map<std::string, std::weak_ptr<ISignalObserver>> mObservers {};
254
259 std::unordered_map<std::string, std::weak_ptr<ISignal>> mSignals {};
260 friend class ISignal;
261 friend class IObserver;
262
263 template <typename ...TArgs>
264 friend class SignalObserver;
265
266 template <typename ...TArgs>
267 friend class Signal;
268 };
269
325 template <typename ...TArgs>
326 class Signal {
327 public:
334 Signal(SignalTracker& owningTracker, const std::string& name);
335
336 Signal(const Signal& other) = delete;
337 Signal(Signal&& other) = delete;
338 Signal& operator=(const Signal& other) = delete;
339 Signal& operator=(Signal&& other) = delete;
340
346 void emit(TArgs...args);
347
359 void resetSignal(SignalTracker& owningTracker, const std::string& name);
360
361 private:
368
373 std::shared_ptr<Signal_<TArgs...>> mSignal_;
374
375 friend class SignalObserver<TArgs...>;
376 };
377
378
414 template <typename ...TArgs>
416 public:
424 SignalObserver(SignalTracker& owningTracker, const std::string& name, std::function<void(TArgs...)> callback);
425
426 SignalObserver(const SignalObserver& other)=delete;
427 SignalObserver(SignalObserver&& other)=delete;
428 SignalObserver& operator=(const SignalObserver& other) = delete;
429 SignalObserver& operator=(SignalObserver&& other) = delete;
430
443 void resetObserver(SignalTracker& owningTracker, const std::string& name, std::function<void(TArgs...)> callback);
444
450 void connectTo(Signal<TArgs...>& signal);
451
452 private:
453
458 std::shared_ptr<SignalObserver_<TArgs...>> mSignalObserver_;
459
460 friend class Signal<TArgs...>;
461 };
462
463 template <typename ...TArgs>
464 inline void Signal_<TArgs...>::registerObserver(std::weak_ptr<ISignalObserver> observer) {
465 assert(!observer.expired() && "Cannot register a null pointer as an observer");
466 mObservers.insert(std::static_pointer_cast<SignalObserver_<TArgs...>>(observer.lock()));
467 }
468
469 template <typename ...TArgs>
470 void Signal_<TArgs...>::emit (TArgs ... args) {
471 //observers that will be removed from the list after this signal has been emitted
472 std::vector<std::weak_ptr<SignalObserver_<TArgs...>>> expiredObservers {};
473
474 for(auto observer: mObservers) {
475 // lock means that this observer is still active
476 if(std::shared_ptr<SignalObserver_<TArgs...>> activeObserver = observer.lock()) {
477 (*activeObserver)(args...);
478
479 // go to the purge list
480 } else {
481 expiredObservers.push_back(observer);
482 }
483 }
484
485 // remove dead observers
486 for(auto expiredObserver: expiredObservers) {
487 mObservers.erase(expiredObserver);
488 }
489 }
490
491 template <typename ...TArgs>
492 inline SignalObserver_<TArgs...>::SignalObserver_(std::function<void(TArgs...)> callback):
493 mStoredFunction{ callback }
494 {}
495 template <typename ...TArgs>
496 inline void SignalObserver_<TArgs...>::operator() (TArgs ... args) {
497 mStoredFunction(args...);
498 }
499
500 template <typename ...TArgs>
501 inline std::shared_ptr<Signal_<TArgs...>> SignalTracker::declareSignal(const std::string& name) {
502 std::shared_ptr<ISignal> newSignal { new Signal_<TArgs...>{} };
503 mSignals.insert({name, newSignal});
505 return std::static_pointer_cast<Signal_<TArgs...>>(newSignal);
506 }
507
508 template <typename ...TArgs>
509 inline std::shared_ptr<SignalObserver_<TArgs...>> SignalTracker::declareSignalObserver(const std::string& name, std::function<void(TArgs...)> callback) {
510 std::shared_ptr<ISignalObserver> newObserver { new SignalObserver_<TArgs...>{callback} };
511 mObservers.insert({name, newObserver});
513 return std::static_pointer_cast<SignalObserver_<TArgs...>>(newObserver);
514 }
515
516 template <typename ...TArgs>
517 Signal<TArgs...>::Signal(SignalTracker& owningTracker, const std::string& name) {
518 resetSignal(owningTracker, name);
519 }
520
521 template <typename ...TArgs>
522 void Signal<TArgs...>::emit(TArgs...args) {
523 mSignal_->emit(args...);
524 }
525
526 template <typename ...TArgs>
527 void Signal<TArgs...>::resetSignal(SignalTracker& owningTracker, const std::string& name) {
528 mSignal_ = owningTracker.declareSignal<TArgs...>(name);
529 }
530
531 template <typename ...TArgs>
533 mSignal_->registerObserver(observer.mSignalObserver_);
534 }
535
536 template <typename ...TArgs>
537 SignalObserver<TArgs...>::SignalObserver(SignalTracker& owningTracker, const std::string& name, std::function<void(TArgs...)> callback) {
538 resetObserver(owningTracker, name, callback);
539 };
540
541 template <typename ...TArgs>
542 void SignalObserver<TArgs...>::resetObserver(SignalTracker& owningTracker, const std::string& name, std::function<void(TArgs...)> callback) {
543 assert(callback && "Empty callback is not allowed");
544 mSignalObserver_ = owningTracker.declareSignalObserver<TArgs...>(name, callback);
545 }
546
547 template <typename ...TArgs>
551}
552
553#endif
Definition signals.hpp:41
The base class for any signal that an object advertises.
Definition signals.hpp:48
virtual void registerObserver(std::weak_ptr< ISignalObserver > observer)=0
A method used by observers to declare their interest in this signal.
A class containing most of the implementation for this engine's SignalObserver concept.
Definition signals.hpp:112
std::function< void(TArgs...)> mStoredFunction
A reference to the function stored by this observer.
Definition signals.hpp:132
SignalObserver_(std::function< void(TArgs...)> callback)
Constructs a new Signal Observer_ object.
Definition signals.hpp:492
void operator()(TArgs... args)
The function called by a Signal this oberver is subscribed to.
Definition signals.hpp:496
A SignalObserver object, which can subscribe to Signals matching its data signature and receive signa...
Definition signals.hpp:415
std::shared_ptr< SignalObserver_< TArgs... > > mSignalObserver_
The underlying implementation of the observer template.
Definition signals.hpp:458
SignalObserver(SignalTracker &owningTracker, const std::string &name, std::function< void(TArgs...)> callback)
Creates a new SignalObserver object.
Definition signals.hpp:537
void resetObserver(SignalTracker &owningTracker, const std::string &name, std::function< void(TArgs...)> callback)
Reinitializes this observer with a new SignalTracker.
Definition signals.hpp:542
void connectTo(Signal< TArgs... > &signal)
Subscribes this SignalObserver to a Signal whose signature matches its own.
Definition signals.hpp:548
A signal tracker, the main interface between an object and the signal system.
Definition signals.hpp:164
void connect(const std::string &theirSignal, const std::string &ourObserver, SignalTracker &other)
Method that connects one of this objects SignalObservers to another tracker's Signal.
Definition signals.cpp:28
std::unordered_map< std::string, std::weak_ptr< ISignalObserver > > mObservers
A list of weak references to this object's SignalObservers, along with their names.
Definition signals.hpp:253
std::shared_ptr< SignalObserver_< TArgs... > > declareSignalObserver(const std::string &observerName, std::function< void(TArgs...)> callbackFunction)
Declares a SignalObserver owned by this tracker, returns a reference to it.
Definition signals.hpp:509
std::unordered_map< std::string, std::weak_ptr< ISignal > > mSignals
A list of weak references to this object's Signals, along with their names.
Definition signals.hpp:259
std::shared_ptr< Signal_< TArgs... > > declareSignal(const std::string &signalName)
Declares a Signal owned by this tracker, and returns a reference to it.
Definition signals.hpp:501
void garbageCollection()
A method which removes any signals and observers sitting on this object which were destroyed at some ...
Definition signals.cpp:44
SignalTracker & operator=(const SignalTracker &other)
Copy assignment operator.
Definition signals.cpp:13
SignalTracker()
Constructs a new SignalTracker object.
A class containing most of the implementation of this engine's Signal concept.
Definition signals.hpp:65
void registerObserver(std::weak_ptr< ISignalObserver > observer) override
Causes an eligible observer to be subscribed to this signal.
Definition signals.hpp:464
void emit(TArgs... args)
Method via which the owner of the signal can send data to the signal's obervers.
Definition signals.hpp:470
Signal_()=default
Constructs a new Signal_ object.
std::set< std::weak_ptr< SignalObserver_< TArgs... > >, std::owner_less< std::weak_ptr< SignalObserver_< TArgs... > > > > mObservers
Weak references to all the observers that have registered themselves with this Signal.
Definition signals.hpp:97
A Signal object, designed to emit signals matching some data signature to be received by all the Sign...
Definition signals.hpp:326
void resetSignal(SignalTracker &owningTracker, const std::string &name)
Reinitializes the tracker with a new owning SignalTracker.
Definition signals.hpp:527
std::shared_ptr< Signal_< TArgs... > > mSignal_
The actual object connected with this Signal's signal tracker, hidden from users of Signal.
Definition signals.hpp:373
void registerObserver(SignalObserver< TArgs... > &observer)
Registers a compatible SignalObserver as a subscriber of this Signal.
Definition signals.hpp:532
void emit(TArgs...args)
A method on the signal which causes the signal to be sent to all of its subscribers (aka SignalObserv...
Definition signals.hpp:522
Signal(SignalTracker &owningTracker, const std::string &name)
Constructs a Signal object and associates it with its SignalTracker.
Definition signals.hpp:517
Namespace containing all class definitions and functions related to the ToyMaker engine.
Definition application.hpp:25