aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
signaler_with_args.pattern.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2025 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41
49
50#ifndef SIGNALER_PATRON_ACCEPTED
51# error "This file should not be included directly. Please use signaler{x}.h"
52#endif // SIGNALER_PATRON_ACCEPTED
53
55
56#ifndef DOXYGEN_SHOULD_SKIP_THIS
57
58namespace gum {
59
60 namespace __sig__ {
61
62 template < LIST_DECL_CLASSES >
63 class MAKE_NAME(IConnector) {
64 public:
65 virtual ~MAKE_NAME(IConnector)() {}
66
67 virtual Listener* target() const = 0;
68 virtual void notify(const void*, LIST_DECL_ARGS) = 0;
69 virtual MAKE_NAME(IConnector)< LIST_CLASSES >* clone() = 0;
70 virtual MAKE_NAME(IConnector)< LIST_CLASSES >* duplicate(Listener* target) = 0;
71 };
72
73 template < LIST_DECL_CLASSES >
74 class MAKE_NAME(BasicSignaler) : public ISignaler {
75 protected:
76 using ConnectorList = List< MAKE_NAME(IConnector) < LIST_CLASSES >* >;
77 using ConnectorIterator = ListConstIteratorSafe< MAKE_NAME(IConnector) < LIST_CLASSES >* >;
78
79 MAKE_NAME(BasicSignaler)() {
80 GUM_CONSTRUCTOR(MAKE_NAME(BasicSignaler));
81 ;
82 }
83
84 MAKE_NAME(BasicSignaler)
85
86 (const MAKE_NAME(BasicSignaler) & s) : ISignaler(s) {
87 GUM_CONS_CPY(MAKE_NAME(BasicSignaler));
88
89 for (const auto& connector: connectors_) {
90 connector->target()->_attachSignal_(this);
91 connectors_.pushBack(connector->clone());
92 }
93 }
94
95 public:
96 virtual ~MAKE_NAME(BasicSignaler)() {
97 GUM_DESTRUCTOR(MAKE_NAME(BasicSignaler));
98
99 for (const auto& connector: connectors_) {
100 connector->target()->_detachSignal_(this);
101 delete connector;
102 }
103
104 connectors_.clear();
105 }
106
107 bool hasListener() { return (!(connectors_.empty())); }
108
109 void detach(Listener* target) {
110 for (ConnectorIterator it = connectors_.reginSafe(); // safe iterator needed here
111 it != connectors_.rendSafe();
112 --it) {
113 if ((*it)->target() == target) {
114 delete *it;
115 connectors_.erase(it);
116 target->_detachSignal_(this);
117 return;
118 }
119 }
120 }
121
122 protected:
123 friend class Listener;
124
125 void duplicateTarget(const Listener* oldtarget, Listener* newtarget) {
126 for (const auto& connector: connectors_)
127 if (connector->target() == oldtarget) {
128 connectors_.pushBack(connector->duplicate(newtarget));
129 }
130 }
131
132 void detachFromTarget(Listener* target) {
133 ConnectorIterator itprev;
134
135 for (ConnectorIterator it = connectors_.rbeginSafe(); // safe iterator needed here
136 it != connectors_.rendSafe();) {
137 itprev = it;
138 --it;
139
140 if ((*itprev)->target() == target) {
141 delete *itprev;
142 connectors_.erase(itprev);
143 }
144 }
145 }
146
147 ConnectorList connectors_;
148 };
149
150 template < class TargetClass, LIST_DECL_CLASSES >
151 class MAKE_NAME(Connector) : public MAKE_NAME(IConnector)< LIST_CLASSES > {
152 public:
153 MAKE_NAME(Connector)() {
154 GUM_CONSTRUCTOR(MAKE_NAME(Connector));
155 _target_ = NULL;
156 _action_ = NULL;
157 }
158
159 MAKE_NAME(Connector)
160
161 (TargetClass* target, void (TargetClass::*action)(const void*, LIST_CLASSES)) {
162 GUM_CONSTRUCTOR(MAKE_NAME(Connector));
163 _target_ = target;
164 _action_ = action;
165 }
166
167 MAKE_NAME(Connector)
168
169 (const MAKE_NAME(Connector) < TargetClass, LIST_CLASSES > *src) :
170 MAKE_NAME(IConnector)< LIST_CLASSES >(src) {
171 GUM_CONS_CPY(MAKE_NAME(Connector));
172 }
173
174 virtual ~MAKE_NAME(Connector)() {
175 GUM_DESTRUCTOR(MAKE_NAME(Connector));
176 ;
177 }
178
179 INLINE virtual MAKE_NAME(IConnector)< LIST_CLASSES >* clone() {
180 return new MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(*this);
181 }
182
183 INLINE virtual MAKE_NAME(IConnector)< LIST_CLASSES >* duplicate(Listener* target) {
184 return new MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >((TargetClass*)target,
185 _action_);
186 }
187
188 INLINE virtual void notify(const void* src, LIST_DECL_ARGS) {
189 (_target_->*_action_)(src, LIST_ARGS);
190 }
191
192 INLINE virtual Listener* target() const { return _target_; }
193
194 private:
195 TargetClass* _target_;
196 void (TargetClass::*_action_)(const void*, LIST_CLASSES);
197 };
198
199 } // namespace __sig__
200
201 template < LIST_DECL_CLASSES >
202 class MAKE_NAME(Signaler) : public __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES > {
203 using ConnectorIterator
204 = typename __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >::ConnectorIterator;
205
206 public:
207 using BasicSignaler = __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >;
208
209 MAKE_NAME(Signaler)() {
210 GUM_CONSTRUCTOR(MAKE_NAME(Signaler));
211 ;
212 }
213
214 MAKE_NAME(Signaler)
215
216 (const MAKE_NAME(Signaler) & s) : __sig__::MAKE_NAME(BasicSignaler)< LIST_CLASSES >(s) {
217 GUM_CONS_CPY(MAKE_NAME(Signaler));
218 }
219
220 virtual ~MAKE_NAME(Signaler)() {
221 GUM_DESTRUCTOR(MAKE_NAME(Signaler));
222 ;
223 }
224
225 template < class TargetClass >
226 void attach(TargetClass* target, void (TargetClass::*action)(const void*, LIST_CLASSES)) {
227 __sig__::MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >* conn
228 = new __sig__::MAKE_NAME(Connector)< TargetClass, LIST_CLASSES >(target, action);
229 this->connectors_.pushBack(conn);
230 target->_attachSignal_(this);
231 }
232
233 INLINE void operator()(const void* src, LIST_DECL_ARGS) {
234 for (const auto& connector: this->connectors_) {
235 connector->notify(src, LIST_ARGS);
236 }
237 }
238 };
239
240} // namespace gum
241
242#endif // DOXYGEN_SHOULD_SKIP_THIS
243
244#undef MAKE_NAME
245#undef LIST_DECL_CLASSES
246#undef LIST_CLASSES
247#undef LIST_DECL_ARGS
248#undef LIST_ARGS
249#undef SIGNALER_PATRON_ACCEPTED
Generic class for manipulating lists.
Internal namespace for aGrUM signaler/listener components.
Definition agrum.h:49
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
#define MAKE_NAME(nom)
Definition signaler1.h:55
#define LIST_DECL_ARGS
Definition signaler1.h:58
#define LIST_CLASSES
Definition signaler1.h:57
#define LIST_ARGS
Definition signaler1.h:59