aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
signaler_with_args.pattern.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/**
23
* @file
24
* @brief Meta classes for signalers.
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27
*
28
*/
29
30
#
ifndef
SIGNALER_PATRON_ACCEPTED
31
#
error
"This file should not be included directly. Please use signaler{x}.h"
32
#
endif
// SIGNALER_PATRON_ACCEPTED
33
34
#
include
<
agrum
/
tools
/
core
/
list
.
h
>
35
36
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
37
38
namespace
gum
{
39
40
namespace
__sig__
{
41
42
template
<
LIST_DECL_CLASSES
>
43
class
MAKE_NAME(IConnector) {
44
public
:
45
virtual
~
MAKE_NAME
(
IConnector
)() {}
46
47
virtual
Listener
*
target
()
const
= 0;
48
virtual
void
notify
(
const
void
*,
LIST_DECL_ARGS
) = 0;
49
virtual
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
>*
clone
() = 0;
50
virtual
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
>*
duplicate
(
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
) <
LIST_CLASSES
>* >
ConnectorIterator
;
58
59
MAKE_NAME
(
BasicSignaler
)() {
60
GUM_CONSTRUCTOR
(
MAKE_NAME
(
BasicSignaler
));
61
;
62
}
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
=
connectors_
.
reginSafe
();
// safe iterator needed here
90
it
!=
connectors_
.
rendSafe
();
91
--
it
) {
92
if
((*
it
)->
target
() ==
target
) {
93
delete
*
it
;
94
connectors_
.
erase
(
it
);
95
target
->
_detachSignal_
(
this
);
96
return
;
97
}
98
}
99
}
100
101
protected
:
102
friend
class
Listener
;
103
104
void
duplicateTarget
(
const
Listener
*
oldtarget
,
Listener
*
newtarget
) {
105
for
(
const
auto
&
connector
:
connectors_
)
106
if
(
connector
->
target
() ==
oldtarget
) {
107
connectors_
.
pushBack
(
connector
->
duplicate
(
newtarget
));
108
}
109
}
110
111
void
detachFromTarget
(
Listener
*
target
) {
112
ConnectorIterator
itprev
;
113
114
for
(
ConnectorIterator
it
=
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
,
void
(
TargetClass
::*
action
)(
const
void
*,
LIST_CLASSES
)) {
140
GUM_CONSTRUCTOR
(
MAKE_NAME
(
Connector
));
141
_target_
=
target
;
142
_action_
=
action
;
143
}
144
145
MAKE_NAME
(
Connector
)
146
(
const
MAKE_NAME
(
Connector
) <
TargetClass
,
LIST_CLASSES
> *
src
) :
147
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
>(
src
) {
148
GUM_CONS_CPY
(
MAKE_NAME
(
Connector
));
149
}
150
151
virtual
~
MAKE_NAME
(
Connector
)() {
152
GUM_DESTRUCTOR
(
MAKE_NAME
(
Connector
));
153
;
154
}
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
(
Listener
*
target
) {
161
return
new
MAKE_NAME
(
Connector
)<
TargetClass
,
LIST_CLASSES
>((
TargetClass
*)
target
,
162
_action_
);
163
}
164
165
INLINE
virtual
void
notify
(
const
void
*
src
,
LIST_DECL_ARGS
) {
166
(
_target_
->*
_action_
)(
src
,
LIST_ARGS
);
167
}
168
169
INLINE
virtual
Listener
*
target
()
const
{
return
_target_
; }
170
171
private
:
172
TargetClass
*
_target_
;
173
void
(
TargetClass
::*
_action_
)(
const
void
*,
LIST_CLASSES
);
174
};
175
176
}
// namespace __sig__
177
178
template
<
LIST_DECL_CLASSES
>
179
class
MAKE_NAME(Signaler) :
public
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
> {
180
typedef
typename
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
>::
ConnectorIterator
181
ConnectorIterator
;
182
183
public
:
184
using
BasicSignaler
=
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
>;
185
186
MAKE_NAME
(
Signaler
)() {
187
GUM_CONSTRUCTOR
(
MAKE_NAME
(
Signaler
));
188
;
189
}
190
191
MAKE_NAME
(
Signaler
)
192
(
const
MAKE_NAME
(
Signaler
) &
s
) :
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
>(
s
) {
193
GUM_CONS_CPY
(
MAKE_NAME
(
Signaler
));
194
}
195
196
virtual
~
MAKE_NAME
(
Signaler
)() {
197
GUM_DESTRUCTOR
(
MAKE_NAME
(
Signaler
));
198
;
199
}
200
201
template
<
class
TargetClass
>
202
void
attach
(
TargetClass
*
target
,
void
(
TargetClass
::*
action
)(
const
void
*,
LIST_CLASSES
)) {
203
__sig__
::
MAKE_NAME
(
Connector
)<
TargetClass
,
LIST_CLASSES
>*
conn
204
=
new
__sig__
::
MAKE_NAME
(
Connector
)<
TargetClass
,
LIST_CLASSES
>(
target
,
action
);
205
this
->
connectors_
.
pushBack
(
conn
);
206
target
->
_attachSignal_
(
this
);
207
}
208
209
INLINE
void
operator
()(
const
void
*
src
,
LIST_DECL_ARGS
) {
210
for
(
const
auto
&
connector
:
this
->
connectors_
) {
211
connector
->
notify
(
src
,
LIST_ARGS
);
212
}
213
}
214
};
215
216
}
// namespace gum
217
218
#
endif
// DOXYGEN_SHOULD_SKIP_THIS
219
220
#
undef
MAKE_NAME
221
#
undef
LIST_DECL_CLASSES
222
#
undef
LIST_CLASSES
223
#
undef
LIST_DECL_ARGS
224
#
undef
LIST_ARGS
225
#
undef
SIGNALER_PATRON_ACCEPTED
gum::__sig__
Internal namespace for aGrUM signaler/listener components.
Definition:
agrum.h:28
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643