aGrUM  0.16.0
signaler_with_args.pattern.h
Go to the documentation of this file.
1 
31 #ifndef SIGNALER_PATRON_ACCEPTED
32 # error "This file should not be included directly. Please use signaler{x}.h"
33 #endif // SIGNALER_PATRON_ACCEPTED
34 
35 #include <agrum/core/list.h>
36 
37 #ifndef DOXYGEN_SHOULD_SKIP_THIS
38 
39 namespace gum {
40 
41  namespace __sig__ {
42 
43  template < LIST_DECL_CLASSES >
44  class MAKE_NAME(IConnector) {
45  public:
46  virtual ~MAKE_NAME(IConnector)() {}
47 
48  virtual Listener* target() const = 0;
49  virtual void notify(const void*, LIST_DECL_ARGS) = 0;
50  virtual MAKE_NAME(IConnector)< LIST_CLASSES >* clone() = 0;
51  virtual MAKE_NAME(IConnector)< LIST_CLASSES >* duplicate(
52  Listener* target) = 0;
53  };
54 
55  template < LIST_DECL_CLASSES >
56  class MAKE_NAME(BasicSignaler) : public ISignaler {
57  protected:
58  typedef List< MAKE_NAME(IConnector) < LIST_CLASSES >* > ConnectorList;
59  typedef ListConstIteratorSafe< MAKE_NAME(IConnector)
60  < LIST_CLASSES >* > ConnectorIterator;
61 
62  MAKE_NAME(BasicSignaler)() { GUM_CONSTRUCTOR(MAKE_NAME(BasicSignaler)); }
63 
64  MAKE_NAME(BasicSignaler)
65  (const MAKE_NAME(BasicSignaler) & s) : ISignaler(s) {
66  GUM_CONS_CPY(MAKE_NAME(BasicSignaler));
67 
68  for (const auto& connector : _connectors) {
69  connector->target()->attachSignal__(this);
70  _connectors.pushBack(connector->clone());
71  }
72  }
73 
74  public:
75  virtual ~MAKE_NAME(BasicSignaler)() {
76  GUM_DESTRUCTOR(MAKE_NAME(BasicSignaler));
77 
78  for (const auto& connector : _connectors) {
79  connector->target()->detachSignal__(this);
80  delete connector;
81  }
82 
83  _connectors.clear();
84  }
85 
86  bool hasListener() { return (!(_connectors.empty())); }
87 
88  void detach(Listener* target) {
89  for (ConnectorIterator it =
90  _connectors.reginSafe(); // safe iterator needed here
91  it != _connectors.rendSafe();
92  --it) {
93  if ((*it)->target() == target) {
94  delete *it;
95  _connectors.erase(it);
96  target->detachSignal__(this);
97  return;
98  }
99  }
100  }
101 
102  protected:
103  friend class Listener;
104 
105  void duplicateTarget(const Listener* oldtarget, Listener* newtarget) {
106  for (const auto& connector : _connectors)
107  if (connector->target() == oldtarget) {
108  _connectors.pushBack(connector->duplicate(newtarget));
109  }
110  }
111 
112  void detachFromTarget(Listener* target) {
113  ConnectorIterator itprev;
114 
115  for (ConnectorIterator it =
116  _connectors.rbeginSafe(); // safe iterator needed here
117  it != _connectors.rendSafe();) {
118  itprev = it;
119  --it;
120 
121  if ((*itprev)->target() == target) {
122  delete *itprev;
123  _connectors.erase(itprev);
124  }
125  }
126  }
127 
128  ConnectorList _connectors;
129  };
130 
131  template < class TargetClass, LIST_DECL_CLASSES >
132  class MAKE_NAME(Connector) : public MAKE_NAME(IConnector)< LIST_CLASSES > {
133  public:
134  MAKE_NAME(Connector)() {
135  GUM_CONSTRUCTOR(MAKE_NAME(Connector));
136  __target = NULL;
137  __action = NULL;
138  }
139 
140  MAKE_NAME(Connector)
141  (TargetClass* target,
142  void (TargetClass::*action)(const void*, LIST_CLASSES)) {
143  GUM_CONSTRUCTOR(MAKE_NAME(Connector));
144  __target = target;
145  __action = action;
146  }
147 
148  MAKE_NAME(Connector)
149  (const MAKE_NAME(Connector) < TargetClass, LIST_CLASSES > *src) :
150  MAKE_NAME(IConnector)< LIST_CLASSES >(src) {
151  GUM_CONS_CPY(MAKE_NAME(Connector));
152  }
153 
154  virtual ~MAKE_NAME(Connector)() { GUM_DESTRUCTOR(MAKE_NAME(Connector)); }
155 
156  INLINE virtual MAKE_NAME(IConnector)< LIST_CLASSES >* clone() {
157  return new MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(*this);
158  }
159 
160  INLINE virtual MAKE_NAME(IConnector)< LIST_CLASSES >* duplicate(
161  Listener* target) {
162  return new MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(
163  (TargetClass*)target, __action);
164  }
165 
166  INLINE virtual void notify(const void* src, LIST_DECL_ARGS) {
167  (__target->*__action)(src, LIST_ARGS);
168  }
169 
170  INLINE virtual Listener* target() const { return __target; }
171 
172  private:
173  TargetClass* __target;
174  void (TargetClass::*__action)(const void*, LIST_CLASSES);
175  };
176 
177  } // namespace __sig__
178 
179  template < LIST_DECL_CLASSES >
180  class MAKE_NAME(Signaler) :
181  public __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES > {
182  typedef typename __sig__::MAKE_NAME(
183  BasicSignaler)< LIST_CLASSES >::ConnectorIterator ConnectorIterator;
184 
185  public:
186  using BasicSignaler = __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >;
187 
188  MAKE_NAME(Signaler)() { GUM_CONSTRUCTOR(MAKE_NAME(Signaler)); }
189 
190  MAKE_NAME(Signaler)
191  (const MAKE_NAME(Signaler) & s) :
192  __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >(s) {
193  GUM_CONS_CPY(MAKE_NAME(Signaler));
194  }
195 
196  virtual ~MAKE_NAME(Signaler)() { GUM_DESTRUCTOR(MAKE_NAME(Signaler)); }
197 
198  template < class TargetClass >
199  void attach(TargetClass* target,
200  void (TargetClass::*action)(const void*, LIST_CLASSES)) {
201  __sig__::MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >* conn =
202  new __sig__::MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(target,
203  action);
204  this->_connectors.pushBack(conn);
205  target->attachSignal__(this);
206  }
207 
208  INLINE void operator()(const void* src, LIST_DECL_ARGS) {
209  for (const auto& connector : this->_connectors) {
210  connector->notify(src, LIST_ARGS);
211  }
212  }
213  };
214 
215 } // namespace gum
216 
217 #endif // DOXYGEN_SHOULD_SKIP_THIS
218 
219 #undef MAKE_NAME
220 #undef LIST_DECL_CLASSES
221 #undef LIST_CLASSES
222 #undef LIST_DECL_ARGS
223 #undef LIST_ARGS
224 #undef SIGNALER_PATRON_ACCEPTED
#define MAKE_NAME(nom)
Definition: signaler1.h:36
#define LIST_ARGS
Definition: signaler1.h:40
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
#define LIST_DECL_ARGS
Definition: signaler1.h:39
#define LIST_CLASSES
Definition: signaler1.h:38