Gazebo Common
API Reference
6.0.2
insert_drive_file
Tutorials
library_books
Classes
toc
Namespaces
insert_drive_file
Files
launch
Gazebo Website
Index
List
Hierarchy
Members: All
Members: Functions
Members: Variables
Members: Typedefs
Members: Enumerations
Members: Enumerator
List
Members
Functions
Typedefs
Variables
Enumerations
Enumerator
src
gz-common
events
include
gz
common
Event.hh
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2016 Open Source Robotics Foundation
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
* http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*
16
*/
17
#ifndef GZ_COMMON_EVENT_HH_
18
#define GZ_COMMON_EVENT_HH_
19
20
#include <atomic>
21
#include <chrono>
22
#include <functional>
23
#include <list>
24
#include <map>
25
#include <memory>
26
#include <mutex>
27
#include <utility>
28
29
#include <gz/common/config.hh>
30
#include <gz/common/events/Export.hh>
31
#include <
gz/common/events/Types.hh
>
32
33
namespace
gz
34
{
35
namespace
common
36
{
39
class
GZ_COMMON_EVENTS_VISIBLE
Event
40
{
42
public
:
Event
();
43
45
public
:
virtual
~Event
();
46
49
public
:
virtual
void
Disconnect
(
int
_id) = 0;
50
53
public
:
bool
Signaled
()
const
;
54
57
public
:
void
SetSignaled
(
bool
_sig);
58
60
private
:
bool
signaled;
61
};
62
64
class
GZ_COMMON_EVENTS_VISIBLE
Connection
65
{
69
public
:
Connection
(
Event
*_e,
int
_i);
70
72
public
:
~Connection
();
73
76
public
:
int
Id
()
const
;
77
79
private
:
Event
*
event
=
nullptr
;
80
82
private
:
int
id
= -1;
83
84
#ifdef _WIN32
85
// Disable warning C4251
86
#pragma warning(push)
87
#pragma warning(disable: 4251)
88
#endif
90
private
:
std::chrono::time_point<std::chrono::system_clock>
creationTime;
91
#ifdef _WIN32
92
#pragma warning(pop)
93
#endif
94
96
public
:
template
<
typename
T,
typename
N>
friend
class
EventT
;
97
};
98
103
template
<
typename
T,
typename
N =
void
>
104
class
EventT
:
public
Event
105
{
106
public
:
using
CallbackT
=
std::function<T>
;
107
static_assert
(
std::is_same<typename CallbackT::result_type, void>::value
,
108
"Event callback must have void return type"
);
109
111
public
:
EventT
();
112
114
public
:
virtual
~EventT
();
115
120
public
:
ConnectionPtr
Connect
(
const
CallbackT
&_subscriber);
121
124
public
:
virtual
void
Disconnect
(
int
_id);
125
128
public
:
unsigned
int
ConnectionCount
()
const
;
129
131
public
:
template
<
typename
... Args>
132
void
operator()
(Args && ... args)
133
{
134
this->
Signal
(std::forward<Args>(args)...);
135
}
136
138
public
:
template
<
typename
... Args>
139
void
Signal
(Args && ... args)
140
{
141
this->Cleanup();
142
143
this->
SetSignaled
(
true
);
144
for
(
const
auto
&iter : this->connections)
145
{
146
if
(iter.second->on)
147
iter.second->callback(std::forward<Args>(args)...);
148
}
149
}
150
154
private
:
void
Cleanup();
155
157
private
:
class
EventConnection
158
{
160
public
: EventConnection(
bool
_on,
const
std::function<T>
&_cb,
161
const
ConnectionPtr
&_publicConn)
162
: callback(_cb), publicConnection(_publicConn)
163
{
164
// Windows Visual Studio 2012 does not have atomic_bool constructor,
165
// so we have to set "on" using operator=
166
this->on = _on;
167
}
168
170
public
: std::atomic_bool on;
171
173
public
:
std::function<T>
callback;
174
178
public
:
std::weak_ptr<Connection>
publicConnection;
179
};
180
183
typedef
std::map<int, std::unique_ptr<EventConnection>
> EvtConnectionMap;
184
186
private
: EvtConnectionMap connections;
187
189
private
:
std::mutex
mutex;
190
192
private
:
std::list<typename EvtConnectionMap::const_iterator>
193
connectionsToRemove;
194
};
195
197
template
<
typename
T,
typename
N>
198
EventT<T, N>::EventT
()
199
:
Event
()
200
{
201
}
202
204
template
<
typename
T,
typename
N>
205
EventT<T, N>::~EventT
()
206
{
207
// Clear the Event pointer on all connections so that they are not
208
// accessed after this Event is destructed.
209
for
(
auto
&conn : this->connections)
210
{
211
auto
publicCon = conn.second->publicConnection.lock();
212
if
(publicCon)
213
{
214
publicCon->event =
nullptr
;
215
}
216
}
217
this->connections.clear();
218
}
219
222
template
<
typename
T,
typename
N>
223
ConnectionPtr
EventT<T, N>::Connect
(
const
std::function<T>
&_subscriber)
224
{
225
int
index = 0;
226
if
(!this->connections.empty())
227
{
228
auto
const
&iter = this->connections.rbegin();
229
index = iter->first + 1;
230
}
231
auto
connection =
ConnectionPtr
(
new
Connection
(
this
, index));
232
this->connections[index].reset(
233
new
EventConnection(
true
, _subscriber, connection));
234
return
connection;
235
}
236
239
template
<
typename
T,
typename
N>
240
unsigned
int
EventT<T, N>::ConnectionCount
()
const
241
{
242
return
this->connections.size();
243
}
244
247
template
<
typename
T,
typename
N>
248
void
EventT<T, N>::Disconnect
(
int
_id)
249
{
250
// Find the connection
251
auto
const
&it = this->connections.find(_id);
252
253
if
(it != this->connections.end())
254
{
255
it->second->on =
false
;
256
// The destructor of std::function seems to crashes if the function it
257
// points to is in a shared library and has been unloaded by the time
258
// the destructor is invoked. It's not clear whether this is a bug in
259
// the implementation of std::function or not. To avoid the crash,
260
// we call the destructor here by setting `callback = nullptr` because
261
// it is likely that EventT::Disconnect is called before the shared
262
// library is unloaded via Connection::~Connection.
263
it->second->callback =
nullptr
;
264
this->connectionsToRemove.push_back(it);
265
}
266
}
267
269
template
<
typename
T,
typename
N>
270
void
EventT<T, N>::Cleanup
()
271
{
272
std::lock_guard<std::mutex>
lock(this->mutex);
273
// Remove all queue connections.
274
for
(
auto
&conn : this->connectionsToRemove)
275
this->connections.erase(conn);
276
this->connectionsToRemove.clear();
277
}
278
}
279
}
280
#endif