aGrUM  0.13.2
signaler_with_args.pattern.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
29 #ifndef SIGNALER_PATRON_ACCEPTED
30 # error "This file should not be included directly. Please use signaler{x}.h"
31 #endif // SIGNALER_PATRON_ACCEPTED
32 
33 #include <agrum/core/list.h>
34 
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 
37 namespace gum {
38 
39  namespace __sig__ {
40 
41  template < LIST_DECL_CLASSES >
42  class MAKE_NAME(IConnector) {
43  public:
44  virtual ~MAKE_NAME(IConnector)() {}
45 
46  virtual Listener* target() const = 0;
47  virtual void notify(const void*, LIST_DECL_ARGS) = 0;
48  virtual MAKE_NAME(IConnector)< LIST_CLASSES >* clone() = 0;
49  virtual MAKE_NAME(IConnector)< LIST_CLASSES >* duplicate(
50  Listener* target) = 0;
51  };
52 
53  template < LIST_DECL_CLASSES >
54  class MAKE_NAME(BasicSignaler) : public ISignaler {
55  protected:
56  typedef List< MAKE_NAME(IConnector) < LIST_CLASSES >* > ConnectorList;
57  typedef ListConstIteratorSafe< MAKE_NAME(IConnector)
58  < LIST_CLASSES >* > ConnectorIterator;
59 
60  MAKE_NAME(BasicSignaler)() { GUM_CONSTRUCTOR(MAKE_NAME(BasicSignaler)); }
61 
62  MAKE_NAME(BasicSignaler)
63  (const MAKE_NAME(BasicSignaler) & s) : ISignaler(s) {
64  GUM_CONS_CPY(MAKE_NAME(BasicSignaler));
65 
66  for (const auto& connector : _connectors) {
67  connector->target()->attachSignal__(this);
68  _connectors.pushBack(connector->clone());
69  }
70  }
71 
72  public:
73  virtual ~MAKE_NAME(BasicSignaler)() {
74  GUM_DESTRUCTOR(MAKE_NAME(BasicSignaler));
75 
76  for (const auto& connector : _connectors) {
77  connector->target()->detachSignal__(this);
78  delete connector;
79  }
80 
81  _connectors.clear();
82  }
83 
84  bool hasListener() { return (!(_connectors.empty())); }
85 
86  void detach(Listener* target) {
87  for (ConnectorIterator it =
88  _connectors.reginSafe(); // safe iterator needed here
89  it != _connectors.rendSafe();
90  --it) {
91  if ((*it)->target() == target) {
92  delete *it;
93  _connectors.erase(it);
94  target->detachSignal__(this);
95  return;
96  }
97  }
98  }
99 
100  protected:
101  friend class Listener;
102 
103  void duplicateTarget(const Listener* oldtarget, Listener* newtarget) {
104  for (const auto& connector : _connectors)
105  if (connector->target() == oldtarget) {
106  _connectors.pushBack(connector->duplicate(newtarget));
107  }
108  }
109 
110  void detachFromTarget(Listener* target) {
111  ConnectorIterator itprev;
112 
113  for (ConnectorIterator it =
114  _connectors.rbeginSafe(); // safe iterator needed here
115  it != _connectors.rendSafe();) {
116  itprev = it;
117  --it;
118 
119  if ((*itprev)->target() == target) {
120  delete *itprev;
121  _connectors.erase(itprev);
122  }
123  }
124  }
125 
126  ConnectorList _connectors;
127  };
128 
129  template < class TargetClass, LIST_DECL_CLASSES >
130  class MAKE_NAME(Connector) : public MAKE_NAME(IConnector)< LIST_CLASSES > {
131  public:
132  MAKE_NAME(Connector)() {
133  GUM_CONSTRUCTOR(MAKE_NAME(Connector));
134  __target = NULL;
135  __action = NULL;
136  }
137 
138  MAKE_NAME(Connector)
139  (TargetClass* target,
140  void (TargetClass::*action)(const void*, LIST_CLASSES)) {
141  GUM_CONSTRUCTOR(MAKE_NAME(Connector));
142  __target = target;
143  __action = action;
144  }
145 
146  MAKE_NAME(Connector)
147  (const MAKE_NAME(Connector) < TargetClass, LIST_CLASSES > *src) :
148  MAKE_NAME(IConnector)< LIST_CLASSES >(src) {
149  GUM_CONS_CPY(MAKE_NAME(Connector));
150  }
151 
152  virtual ~MAKE_NAME(Connector)() { GUM_DESTRUCTOR(MAKE_NAME(Connector)); }
153 
154  INLINE virtual MAKE_NAME(IConnector)< LIST_CLASSES >* clone() {
155  return new MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(*this);
156  }
157 
158  INLINE virtual MAKE_NAME(IConnector)< LIST_CLASSES >* duplicate(
159  Listener* target) {
160  return new MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(
161  (TargetClass*)target, __action);
162  }
163 
164  INLINE virtual void notify(const void* src, LIST_DECL_ARGS) {
165  (__target->*__action)(src, LIST_ARGS);
166  }
167 
168  INLINE virtual Listener* target() const { return __target; }
169 
170  private:
171  TargetClass* __target;
172  void (TargetClass::*__action)(const void*, LIST_CLASSES);
173  };
174 
175  } // namespace __sig__
176 
177  template < LIST_DECL_CLASSES >
178  class MAKE_NAME(Signaler) :
179  public __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES > {
180  typedef typename __sig__::MAKE_NAME(
181  BasicSignaler)< LIST_CLASSES >::ConnectorIterator ConnectorIterator;
182 
183  public:
184  using BasicSignaler = __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >;
185 
186  MAKE_NAME(Signaler)() { GUM_CONSTRUCTOR(MAKE_NAME(Signaler)); }
187 
188  MAKE_NAME(Signaler)
189  (const MAKE_NAME(Signaler) & s) :
190  __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >(s) {
191  GUM_CONS_CPY(MAKE_NAME(Signaler));
192  }
193 
194  virtual ~MAKE_NAME(Signaler)() { GUM_DESTRUCTOR(MAKE_NAME(Signaler)); }
195 
196  template < class TargetClass >
197  void attach(TargetClass* target,
198  void (TargetClass::*action)(const void*, LIST_CLASSES)) {
199  __sig__::MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >* conn =
200  new __sig__::MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(target,
201  action);
202  this->_connectors.pushBack(conn);
203  target->attachSignal__(this);
204  }
205 
206  INLINE void operator()(const void* src, LIST_DECL_ARGS) {
207  for (const auto& connector : this->_connectors) {
208  connector->notify(src, LIST_ARGS);
209  }
210  }
211  };
212 
213 } // namespace gum
214 
215 #endif // DOXYGEN_SHOULD_SKIP_THIS
216 
217 #undef MAKE_NAME
218 #undef LIST_DECL_CLASSES
219 #undef LIST_CLASSES
220 #undef LIST_DECL_ARGS
221 #undef LIST_ARGS
222 #undef SIGNALER_PATRON_ACCEPTED
#define MAKE_NAME(nom)
Definition: signaler1.h:34
#define LIST_ARGS
Definition: signaler1.h:38
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
Generic class for manipulating lists.
#define LIST_DECL_ARGS
Definition: signaler1.h:37
#define LIST_CLASSES
Definition: signaler1.h:36