Clio
develop
The XRP Ledger API server.
Theme:
Default
Round
Robot
Toggle main menu visibility
Loading...
Searching...
No Matches
TrackableSignal.hpp
1
#pragma once
2
3
#include "util/Mutex.hpp"
4
5
#include <boost/signals2.hpp>
6
#include <boost/signals2/connection.hpp>
7
#include <boost/signals2/variadic_signal.hpp>
8
9
#include <cstddef>
10
#include <functional>
11
#include <memory>
12
#include <mutex>
13
#include <unordered_map>
14
15
namespace
feed::impl {
16
25
template
<
typename
Session,
typename
... Args>
26
class
TrackableSignal
{
27
using
ConnectionPtr = Session*;
28
using
ConnectionSharedPtr = std::shared_ptr<Session>;
29
30
// map of connection and signal connection, key is the pointer of the connection object
31
// allow disconnect to be called in the destructor of the connection
32
using
ConnectionsMap = std::unordered_map<ConnectionPtr, boost::signals2::connection>;
33
util::Mutex<ConnectionsMap>
connections_;
34
35
using
SignalType = boost::signals2::signal<void(Args...)>;
36
SignalType signal_;
37
38
public
:
49
bool
50
connectTrackableSlot
(ConnectionSharedPtr
const
& trackable, std::function<
void
(Args...)> slot)
51
{
52
auto
connections = connections_.template lock<std::scoped_lock>();
53
if
(connections->contains(trackable.get())) {
54
return
false
;
55
}
56
57
// This class can't hold the trackable's shared_ptr, because disconnect should be able to be
58
// called in the the trackable's destructor. However, the trackable can not be destroyed
59
// when the slot is being called either. `track_foreign` is racey when one shared_ptr is
60
// tracked by multiple signals. Therefore we are storing a weak_ptr of the trackable and
61
// using weak_ptr::lock() to atomically check existence and acquire a shared_ptr during slot
62
// invocation. This guarantees to keep the trackable alive for the duration of the slot call
63
// and avoids potential race conditions.
64
connections->emplace(
65
trackable.get(),
66
signal_.connect([slot, weakTrackable = std::weak_ptr(trackable)](Args&&... args) {
67
if (auto const lifeExtender = weakTrackable.lock(); lifeExtender)
68
std::invoke(slot, std::forward<Args...>(args)...);
69
})
70
);
71
return
true
;
72
}
73
83
bool
84
disconnect
(ConnectionPtr trackablePtr)
85
{
86
if
(
auto
connections = connections_.template lock<std::scoped_lock>();
87
connections->contains(trackablePtr)) {
88
connections->operator[](trackablePtr).
disconnect
();
89
connections->erase(trackablePtr);
90
return
true
;
91
}
92
return
false
;
93
}
94
100
void
101
emit
(Args
const
&... args)
const
102
{
103
signal_(args...);
104
}
105
109
[[nodiscard]] std::size_t
110
count
()
const
111
{
112
return
connections_.template lock<std::scoped_lock>()->size();
113
}
114
};
115
}
// namespace feed::impl
feed::impl::TrackableSignal
A thread-safe class to manage a signal and its tracking connections.
Definition
TrackableSignal.hpp:26
feed::impl::TrackableSignal::disconnect
bool disconnect(ConnectionPtr trackablePtr)
Disconnect a slot to the signal.
Definition
TrackableSignal.hpp:84
feed::impl::TrackableSignal::count
std::size_t count() const
Get the number of connections.
Definition
TrackableSignal.hpp:110
feed::impl::TrackableSignal::emit
void emit(Args const &... args) const
Calling all slots.
Definition
TrackableSignal.hpp:101
feed::impl::TrackableSignal::connectTrackableSlot
bool connectTrackableSlot(ConnectionSharedPtr const &trackable, std::function< void(Args...)> slot)
Connect a slot to the signal, the slot will be called when the signal is emitted and trackable is sti...
Definition
TrackableSignal.hpp:50
util::Mutex
A container for data that is protected by a mutex. Inspired by Mutex in Rust.
Definition
Mutex.hpp:82
src
feed
impl
TrackableSignal.hpp
Generated by
1.17.0