Cytopia  0.3
A city building simulation game
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Signal.hxx
Go to the documentation of this file.
1 #ifndef SIGNAL_HXX_
2 #define SIGNAL_HXX_
3 
4 #include <memory>
5 #include <functional>
6 #include <list>
7 #include <vector>
8 #include <algorithm>
9 
10 namespace Signal
11 {
12 namespace Lib
13 {
14 
16 template <typename, typename> class ProtoSignal;
17 
19 template <typename, typename> struct CollectorInvocation;
20 
22 template <typename Result> struct CollectorLast
23 {
24  using CollectorResult = Result;
25  explicit CollectorLast() : last_() {}
26  inline bool operator()(Result r)
27  {
28  last_ = r;
29  return true;
30  }
32 
33 private:
34  Result last_;
35 };
36 
38 template <typename Result> struct CollectorDefault : CollectorLast<Result>
39 {
40 };
41 
43 template <> struct CollectorDefault<void>
44 {
45  using CollectorResult = void;
46  void result() {}
47  inline bool operator()(void) { return true; }
48 };
49 
51 template <class Collector, class R, class... Args> struct CollectorInvocation<Collector, R(Args...)>
52 {
53  inline bool invoke(Collector &collector, const std::function<R(Args...)> &cbf, Args... args) const
54  {
55  return collector(cbf(args...));
56  }
57 };
58 
60 template <class Collector, class... Args> struct CollectorInvocation<Collector, void(Args...)>
61 {
62  inline bool invoke(Collector &collector, const std::function<void(Args...)> &cbf, Args... args) const
63  {
64  cbf(args...);
65  return collector();
66  }
67 };
68 
70 template <class Collector, class R, class... Args>
71 class ProtoSignal<R(Args...), Collector> : CollectorInvocation<Collector, R(Args...)>
72 {
73 protected:
74  using CbFunction = std::function<R(Args...)>;
75  using Result = typename CbFunction::result_type;
76  using CollectorResult = typename Collector::CollectorResult;
77 
78 private:
79  /*copy-ctor*/ ProtoSignal(const ProtoSignal &) = delete;
80  ProtoSignal &operator=(const ProtoSignal &) = delete;
81 
82  using CallbackSlot = std::shared_ptr<CbFunction>;
83  using CallbackList = std::list<CallbackSlot>;
85 
86  size_t add_cb(const CbFunction &cb)
87  {
88  callback_list_.emplace_back(std::make_shared<CbFunction>(cb));
89  return size_t(callback_list_.back().get());
90  }
91 
92  bool remove_cb(size_t id)
93  {
94  auto it = std::remove_if(begin(callback_list_), end(callback_list_),
95  [id](const CallbackSlot &slot) { return size_t(slot.get()) == id; });
96  bool const removed = it != end(callback_list_);
97  callback_list_.erase(it, end(callback_list_));
98  return removed;
99  }
100 
101 public:
103  ProtoSignal(const CbFunction &method)
104  {
105  if (method)
106  {
107  add_cb(method);
108  }
109  }
111  ~ProtoSignal() = default;
112 
114  size_t connect(const CbFunction &cb) { return add_cb(cb); }
116  bool disconnect(size_t connection) { return remove_cb(connection); }
117 
119  CollectorResult emit(Args... args) const
120  {
121  Collector collector;
122  for (auto &slot : callback_list_)
123  {
124  if (slot)
125  {
126  const bool continue_emission = this->invoke(collector, *slot, args...);
127  if (!continue_emission)
128  {
129  break;
130  }
131  }
132  }
133  return collector.result();
134  }
136  std::size_t size() { return callback_list_.size(); }
137 };
138 } // namespace Lib
139 
140 // Begin Namespace Signal
141 
156 template <typename SignalSignature, class Collector = Lib::CollectorDefault<typename std::function<SignalSignature>::result_type>>
157 struct Signal : Lib::ProtoSignal<SignalSignature, Collector>
158 {
160  using CbFunction = typename ProtoSignal::CbFunction;
162  Signal(const CbFunction &method = CbFunction()) : ProtoSignal(method) {}
163 };
164 
166 template <class instance, class Class, class R, class... Args>
167 std::function<R(Args...)> slot(instance &object, R (Class::*method)(Args...))
168 {
169  return [&object, method](Args... args) { return (object.*method)(args...); };
170 }
171 
173 template <class Class, class R, class... Args> std::function<R(Args...)> slot(Class *object, R (Class::*method)(Args...))
174 {
175  return [object, method](Args... args) { return (object->*method)(args...); };
176 }
177 
178 } // End Namespace Signal
179 
180 #endif
Signal::Signal< void(bool)>::CbFunction
typename ProtoSignal::CbFunction CbFunction
Definition: Signal.hxx:160
Signal::Lib::CollectorLast::result
CollectorResult result()
Definition: Signal.hxx:31
Signal::Lib::ProtoSignal< R(Args...), Collector >::CallbackSlot
std::shared_ptr< CbFunction > CallbackSlot
Definition: Signal.hxx:82
Signal::Lib::ProtoSignal< R(Args...), Collector >::CbFunction
std::function< R(Args...)> CbFunction
Definition: Signal.hxx:74
Signal::Lib::CollectorDefault
CollectorDefault implements the default signal handler collection behaviour.
Definition: Signal.hxx:38
Signal::Lib::ProtoSignal< R(Args...), Collector >::callback_list_
CallbackList callback_list_
Definition: Signal.hxx:84
Signal::Lib::ProtoSignal< R(Args...), Collector >::CallbackList
std::list< CallbackSlot > CallbackList
Definition: Signal.hxx:83
Signal
Definition: Signal.hxx:10
Signal::Lib::CollectorDefault< void >::result
void result()
Definition: Signal.hxx:46
Signal::Lib::ProtoSignal< R(Args...), Collector >::size
std::size_t size()
Number of connected slots.
Definition: Signal.hxx:136
Signal::Lib::ProtoSignal< R(Args...), Collector >::CollectorResult
typename Collector::CollectorResult CollectorResult
Definition: Signal.hxx:76
Signal::Lib::ProtoSignal< R(Args...), Collector >::emit
CollectorResult emit(Args... args) const
Emit a signal, i.e. invoke all its callbacks and collect return types with the Collector.
Definition: Signal.hxx:119
Signal::Lib::CollectorInvocation< Collector, void(Args...)>::invoke
bool invoke(Collector &collector, const std::function< void(Args...)> &cbf, Args... args) const
Definition: Signal.hxx:62
Signal::Lib::ProtoSignal< R(Args...), Collector >::connect
size_t connect(const CbFunction &cb)
Operator to add a new function or lambda as signal handler, returns a handler connection ID.
Definition: Signal.hxx:114
Signal::Lib::CollectorLast::operator()
bool operator()(Result r)
Definition: Signal.hxx:26
Signal::Lib::CollectorLast::CollectorLast
CollectorLast()
Definition: Signal.hxx:25
Signal::Lib::ProtoSignal< R(Args...), Collector >::add_cb
size_t add_cb(const CbFunction &cb)
Definition: Signal.hxx:86
Signal::Lib::ProtoSignal< R(Args...), Collector >::Result
typename CbFunction::result_type Result
Definition: Signal.hxx:75
Signal::Signal::Signal
Signal(const CbFunction &method=CbFunction())
Signal constructor, supports a default callback as argument.
Definition: Signal.hxx:162
Signal::Lib::ProtoSignal
ProtoSignal is the template implementation for callback list.
Definition: Signal.hxx:16
Signal::Lib::CollectorDefault< void >::operator()
bool operator()(void)
Definition: Signal.hxx:47
Signal::Lib::CollectorInvocation< Collector, R(Args...)>::invoke
bool invoke(Collector &collector, const std::function< R(Args...)> &cbf, Args... args) const
Definition: Signal.hxx:53
Signal::Lib::CollectorDefault< void >::CollectorResult
void CollectorResult
Definition: Signal.hxx:45
Signal::slot
std::function< R(Args...)> slot(instance &object, R(Class::*method)(Args...))
This function creates a std::function by binding object to the member function pointer method.
Definition: Signal.hxx:167
Signal::Lib::CollectorLast::last_
Result last_
Definition: Signal.hxx:34
Signal::Lib::CollectorLast
CollectorLast returns the result of the last signal handler from a signal emission.
Definition: Signal.hxx:22
Signal::Lib::ProtoSignal< R(Args...), Collector >::ProtoSignal
ProtoSignal(const CbFunction &method)
ProtoSignal constructor, connects default callback if non-nullptr.
Definition: Signal.hxx:103
Signal::Lib::ProtoSignal< R(Args...), Collector >::remove_cb
bool remove_cb(size_t id)
Definition: Signal.hxx:92
Signal::Lib::CollectorInvocation
CollectorInvocation invokes signal handlers differently depending on return type.
Definition: Signal.hxx:19
Signal::Lib::ProtoSignal< R(Args...), Collector >::disconnect
bool disconnect(size_t connection)
Operator to remove a signal handler through it connection ID, returns if a handler was removed.
Definition: Signal.hxx:116
Signal::Lib::CollectorLast::CollectorResult
Result CollectorResult
Definition: Signal.hxx:24