aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
signaler_with_args.pattern.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2020 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
)
51
= 0;
52
};
53
54
template
< LIST_DECL_CLASSES >
55
class
MAKE_NAME(BasicSignaler) :
public
ISignaler
{
56
protected
:
57
typedef
List
<
MAKE_NAME
(
IConnector
) <
LIST_CLASSES
>* >
ConnectorList
;
58
typedef
ListConstIteratorSafe
<
MAKE_NAME
(
IConnector
)
59
<
LIST_CLASSES
>* >
ConnectorIterator
;
60
61
MAKE_NAME
(
BasicSignaler
)() {
GUM_CONSTRUCTOR
(
MAKE_NAME
(
BasicSignaler
)); }
62
63
MAKE_NAME
(
BasicSignaler
)
64
(
const
MAKE_NAME
(
BasicSignaler
) &
s
) :
ISignaler
(
s
) {
65
GUM_CONS_CPY
(
MAKE_NAME
(
BasicSignaler
));
66
67
for
(
const
auto
&
connector
:
connectors_
) {
68
connector
->
target
()->
attachSignal__
(
this
);
69
connectors_
.
pushBack
(
connector
->
clone
());
70
}
71
}
72
73
public
:
74
virtual
~
MAKE_NAME
(
BasicSignaler
)() {
75
GUM_DESTRUCTOR
(
MAKE_NAME
(
BasicSignaler
));
76
77
for
(
const
auto
&
connector
:
connectors_
) {
78
connector
->
target
()->
detachSignal__
(
this
);
79
delete
connector
;
80
}
81
82
connectors_
.
clear
();
83
}
84
85
bool
hasListener
() {
return
(!(
connectors_
.
empty
())); }
86
87
void
detach
(
Listener
*
target
) {
88
for
(
ConnectorIterator
it
89
=
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
115
=
connectors_
.
rbeginSafe
();
// safe iterator needed here
116
it
!=
connectors_
.
rendSafe
();) {
117
itprev
=
it
;
118
--
it
;
119
120
if
((*
itprev
)->
target
() ==
target
) {
121
delete
*
itprev
;
122
connectors_
.
erase
(
itprev
);
123
}
124
}
125
}
126
127
ConnectorList
connectors_
;
128
};
129
130
template
<
class
TargetClass, LIST_DECL_CLASSES >
131
class
MAKE_NAME(Connector) :
public
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
> {
132
public
:
133
MAKE_NAME
(
Connector
)() {
134
GUM_CONSTRUCTOR
(
MAKE_NAME
(
Connector
));
135
target__
=
NULL
;
136
action__
=
NULL
;
137
}
138
139
MAKE_NAME
(
Connector
)
140
(
TargetClass
*
target
,
141
void
(
TargetClass
::*
action
)(
const
void
*,
LIST_CLASSES
)) {
142
GUM_CONSTRUCTOR
(
MAKE_NAME
(
Connector
));
143
target__
=
target
;
144
action__
=
action
;
145
}
146
147
MAKE_NAME
(
Connector
)
148
(
const
MAKE_NAME
(
Connector
) <
TargetClass
,
LIST_CLASSES
> *
src
) :
149
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
>(
src
) {
150
GUM_CONS_CPY
(
MAKE_NAME
(
Connector
));
151
}
152
153
virtual
~
MAKE_NAME
(
Connector
)() {
GUM_DESTRUCTOR
(
MAKE_NAME
(
Connector
)); }
154
155
INLINE
virtual
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
>*
clone
() {
156
return
new
MAKE_NAME
(
Connector
)<
TargetClass
,
LIST_CLASSES
>(*
this
);
157
}
158
159
INLINE
virtual
MAKE_NAME
(
IConnector
)<
LIST_CLASSES
>*
duplicate
(
160
Listener
*
target
) {
161
return
new
MAKE_NAME
(
162
Connector
)<
TargetClass
,
LIST_CLASSES
>((
TargetClass
*)
target
,
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) :
180
public
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
> {
181
typedef
typename
__sig__
::
MAKE_NAME
(
182
BasicSignaler
)<
LIST_CLASSES
>::
ConnectorIterator
ConnectorIterator
;
183
184
public
:
185
using
BasicSignaler
=
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
>;
186
187
MAKE_NAME
(
Signaler
)() {
GUM_CONSTRUCTOR
(
MAKE_NAME
(
Signaler
)); }
188
189
MAKE_NAME
(
Signaler
)
190
(
const
MAKE_NAME
(
Signaler
) &
s
) :
191
__sig__
::
MAKE_NAME
(
BasicSignaler
)<
LIST_CLASSES
>(
s
) {
192
GUM_CONS_CPY
(
MAKE_NAME
(
Signaler
));
193
}
194
195
virtual
~
MAKE_NAME
(
Signaler
)() {
GUM_DESTRUCTOR
(
MAKE_NAME
(
Signaler
)); }
196
197
template
<
class
TargetClass
>
198
void
attach
(
TargetClass
*
target
,
199
void
(
TargetClass
::*
action
)(
const
void
*,
LIST_CLASSES
)) {
200
__sig__
::
MAKE_NAME
(
Connector
)<
TargetClass
,
LIST_CLASSES
>*
conn
201
=
new
__sig__
::
MAKE_NAME
(
Connector
)<
TargetClass
,
LIST_CLASSES
>(
target
,
202
action
);
203
this
->
connectors_
.
pushBack
(
conn
);
204
target
->
attachSignal__
(
this
);
205
}
206
207
INLINE
void
operator
()(
const
void
*
src
,
LIST_DECL_ARGS
) {
208
for
(
const
auto
&
connector
:
this
->
connectors_
) {
209
connector
->
notify
(
src
,
LIST_ARGS
);
210
}
211
}
212
};
213
214
}
// namespace gum
215
216
#
endif
// DOXYGEN_SHOULD_SKIP_THIS
217
218
#
undef
MAKE_NAME
219
#
undef
LIST_DECL_CLASSES
220
#
undef
LIST_CLASSES
221
#
undef
LIST_DECL_ARGS
222
#
undef
LIST_ARGS
223
#
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:669