Gazebo Common
API Reference
6.0.0
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 <functional>
22
#include <list>
23
#include <map>
24
#include <memory>
25
#include <mutex>
26
#include <utility>
27
28
#include <gz/common/config.hh>
29
#include <gz/common/events/Export.hh>
30
#include <
gz/common/events/Types.hh
>
31
32
namespace
gz
33
{
34
namespace
common
35
{
38
class
GZ_COMMON_EVENTS_VISIBLE
Event
39
{
41
public
:
Event
();
42
44
public
:
virtual
~Event
();
45
48
public
:
virtual
void
Disconnect
(
int
_id) = 0;
49
52
public
:
bool
Signaled
()
const
;
53
56
public
:
void
SetSignaled
(
bool
_sig);
57
59
private
:
bool
signaled;
60
};
61
63
class
GZ_COMMON_EVENTS_VISIBLE
Connection
64
{
68
public
:
Connection
(
Event
*_e,
int
_i);
69
71
public
:
~Connection
();
72
75
public
:
int
Id
()
const
;
76
78
private
:
Event
*
event
=
nullptr
;
79
81
private
:
int
id
= -1;
82
83
#ifdef _WIN32
84
// Disable warning C4251
85
#pragma warning(push)
86
#pragma warning(disable: 4251)
87
#endif
89
private
:
std::chrono::time_point<std::chrono::system_clock>
creationTime;
90
#ifdef _WIN32
91
#pragma warning(pop)
92
#endif
93
95
public
:
template
<
typename
T,
typename
N>
friend
class
EventT
;
96
};
97
102
template
<
typename
T,
typename
N =
void
>
103
class
EventT
:
public
Event
104
{
105
public
:
using
CallbackT
=
std::function<T>
;
106
static_assert
(
std::is_same<typename CallbackT::result_type, void>::value
,
107
"Event callback must have void return type"
);
108
110
public
:
EventT
();
111
113
public
:
virtual
~EventT
();
114
119
public
:
ConnectionPtr
Connect
(
const
CallbackT
&_subscriber);
120
123
public
:
virtual
void
Disconnect
(
int
_id);
124
127
public
:
unsigned
int
ConnectionCount
()
const
;
128
130
public
:
template
<
typename
... Args>
131
void
operator()
(Args && ... args)
132
{
133
this->
Signal
(std::forward<Args>(args)...);
134
}
135
137
public
:
template
<
typename
... Args>
138
void
Signal
(Args && ... args)
139
{
140
this->Cleanup();
141
142
this->
SetSignaled
(
true
);
143
for
(
const
auto
&iter : this->connections)
144
{
145
if
(iter.second->on)
146
iter.second->callback(std::forward<Args>(args)...);
147
}
148
}
149
153
private
:
void
Cleanup();
154
156
private
:
class
EventConnection
157
{
159
public
: EventConnection(
bool
_on,
const
std::function<T>
&_cb,
160
const
ConnectionPtr
&_publicConn)
161
: callback(_cb), publicConnection(_publicConn)
162
{
163
// Windows Visual Studio 2012 does not have atomic_bool constructor,
164
// so we have to set "on" using operator=
165
this->on = _on;
166
}
167
169
public
: std::atomic_bool on;
170
172
public
:
std::function<T>
callback;
173
177
public
:
std::weak_ptr<Connection>
publicConnection;
178
};
179
182
typedef
std::map<int, std::unique_ptr<EventConnection>
> EvtConnectionMap;
183
185
private
: EvtConnectionMap connections;
186
188
private
:
std::mutex
mutex;
189
191
private
:
std::list<typename EvtConnectionMap::const_iterator>
192
connectionsToRemove;
193
};
194
196
template
<
typename
T,
typename
N>
197
EventT<T, N>::EventT
()
198
:
Event
()
199
{
200
}
201
203
template
<
typename
T,
typename
N>
204
EventT<T, N>::~EventT
()
205
{
206
// Clear the Event pointer on all connections so that they are not
207
// accessed after this Event is destructed.
208
for
(
auto
&conn : this->connections)
209
{
210
auto
publicCon = conn.second->publicConnection.lock();
211
if
(publicCon)
212
{
213
publicCon->event =
nullptr
;
214
}
215
}
216
this->connections.clear();
217
}
218
221
template
<
typename
T,
typename
N>
222
ConnectionPtr
EventT<T, N>::Connect
(
const
std::function<T>
&_subscriber)
223
{
224
int
index = 0;
225
if
(!this->connections.empty())
226
{
227
auto
const
&iter = this->connections.rbegin();
228
index = iter->first + 1;
229
}
230
auto
connection =
ConnectionPtr
(
new
Connection
(
this
, index));
231
this->connections[index].reset(
232
new
EventConnection(
true
, _subscriber, connection));
233
return
connection;
234
}
235
238
template
<
typename
T,
typename
N>
239
unsigned
int
EventT<T, N>::ConnectionCount
()
const
240
{
241
return
this->connections.size();
242
}
243
246
template
<
typename
T,
typename
N>
247
void
EventT<T, N>::Disconnect
(
int
_id)
248
{
249
// Find the connection
250
auto
const
&it = this->connections.find(_id);
251
252
if
(it != this->connections.end())
253
{
254
it->second->on =
false
;
255
// The destructor of std::function seems to crashes if the function it
256
// points to is in a shared library and has been unloaded by the time
257
// the destructor is invoked. It's not clear whether this is a bug in
258
// the implementation of std::function or not. To avoid the crash,
259
// we call the destructor here by setting `callback = nullptr` because
260
// it is likely that EventT::Disconnect is called before the shared
261
// library is unloaded via Connection::~Connection.
262
it->second->callback =
nullptr
;
263
this->connectionsToRemove.push_back(it);
264
}
265
}
266
268
template
<
typename
T,
typename
N>
269
void
EventT<T, N>::Cleanup
()
270
{
271
std::lock_guard<std::mutex>
lock(this->mutex);
272
// Remove all queue connections.
273
for
(
auto
&conn : this->connectionsToRemove)
274
this->connections.erase(conn);
275
this->connectionsToRemove.clear();
276
}
277
}
278
}
279
#endif