Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
TrackableSignal.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2024, the clio developers.
5
6 Permission to use, copy, modify, and distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#pragma once
21
22#include "util/Mutex.hpp"
23
24#include <boost/signals2.hpp>
25#include <boost/signals2/connection.hpp>
26#include <boost/signals2/variadic_signal.hpp>
27
28#include <cstddef>
29#include <functional>
30#include <memory>
31#include <mutex>
32#include <unordered_map>
33
34namespace feed::impl {
35
43template <typename Session, typename... Args>
45 using ConnectionPtr = Session*;
46 using ConnectionSharedPtr = std::shared_ptr<Session>;
47
48 // map of connection and signal connection, key is the pointer of the connection object
49 // allow disconnect to be called in the destructor of the connection
50 using ConnectionsMap = std::unordered_map<ConnectionPtr, boost::signals2::connection>;
51 util::Mutex<ConnectionsMap> connections_;
52
53 using SignalType = boost::signals2::signal<void(Args...)>;
54 SignalType signal_;
55
56public:
66 bool
67 connectTrackableSlot(ConnectionSharedPtr const& trackable, std::function<void(Args...)> slot)
68 {
69 auto connections = connections_.template lock<std::scoped_lock>();
70 if (connections->contains(trackable.get())) {
71 return false;
72 }
73
74 // This class can't hold the trackable's shared_ptr, because disconnect should be able to be called in the
75 // the trackable's destructor. However, the trackable can not be destroied when the slot is being called
76 // either. track_foreign will hold a weak_ptr to the connection, which makes sure the connection is valid when
77 // the slot is called.
78 connections->emplace(
79 trackable.get(), signal_.connect(typename SignalType::slot_type(slot).track_foreign(trackable))
80 );
81 return true;
82 }
83
91 bool
92 disconnect(ConnectionPtr trackablePtr)
93 {
94 if (auto connections = connections_.template lock<std::scoped_lock>(); connections->contains(trackablePtr)) {
95 connections->operator[](trackablePtr).disconnect();
96 connections->erase(trackablePtr);
97 return true;
98 }
99 return false;
100 }
101
107 void
108 emit(Args const&... args) const
109 {
110 signal_(args...);
111 }
112
116 std::size_t
117 count() const
118 {
119 return connections_.template lock<std::scoped_lock>()->size();
120 }
121};
122} // namespace feed::impl
A thread-safe class to manage a signal and its tracking connections.
Definition TrackableSignal.hpp:44
bool disconnect(ConnectionPtr trackablePtr)
Disconnect a slot to the signal.
Definition TrackableSignal.hpp:92
std::size_t count() const
Get the number of connections.
Definition TrackableSignal.hpp:117
void emit(Args const &... args) const
Calling all slots.
Definition TrackableSignal.hpp:108
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:67
A container for data that is protected by a mutex. Inspired by Mutex in Rust.
Definition Mutex.hpp:96