12#include "Stroika/Foundation/Execution/Throw.h"
21 template <
typename... ARGS>
22 inline CallbackRegistry<void (ARGS...)>::Entry_::Entry_ (ID
id,
const Callback& callback)
27 template <
typename... ARGS>
28 inline CallbackRegistry<void (ARGS...)>::~CallbackRegistry ()
31 [[maybe_unused]] lock_guard critSec{fMutex_};
32 for ([[maybe_unused]]
const shared_ptr<Entry_>& e : fEntries_) {
33 Require (e->fRunningOn.empty ());
37 template <
typename... ARGS>
38 auto CallbackRegistry<void (ARGS...)>::Add (
const Callback& callback) -> ID
40 Require (callback !=
nullptr);
41 auto e = Memory::MakeSharedPtr<Entry_> (ID::New (), callback);
43 [[maybe_unused]] lock_guard critSec{fMutex_};
44 fEntries_.push_back (e);
47 template <
typename... ARGS>
48 void CallbackRegistry<void (ARGS...)>::Remove (ID
id)
noexcept
50 unique_lock critSec{fMutex_};
51 auto i = find_if (fEntries_.begin (), fEntries_.end (), [&] (
const shared_ptr<Entry_>& e) { return e->fID == id; });
52 if (i == fEntries_.end ()) {
55 shared_ptr<Entry_> e = *i;
59 const thread::id me = this_thread::get_id ();
60 fCallEnded_.wait (critSec,
61 [&] () {
return all_of (e->fRunningOn.begin (), e->fRunningOn.end (), [&] (thread::id t) { return t == me; }); });
63 template <
typename... ARGS>
64 void CallbackRegistry<void (ARGS...)>::RemoveAll () noexcept
66 unique_lock critSec{fMutex_};
67 vector<shared_ptr<Entry_>> removed;
68 removed.swap (fEntries_);
69 for (
const shared_ptr<Entry_>& e : removed) {
73 const thread::id me = this_thread::get_id ();
74 fCallEnded_.wait (critSec, [&] () {
75 return all_of (removed.begin (), removed.end (), [&] (
const shared_ptr<Entry_>& e) {
76 return all_of (e->fRunningOn.begin (), e->fRunningOn.end (), [&] (thread::id t) { return t == me; });
80 template <
typename... ARGS>
81 void CallbackRegistry<void (ARGS...)>::Call (ARGS... args)
83 using namespace Characters::Literals;
84 vector<shared_ptr<Entry_>> entries;
86 [[maybe_unused]] lock_guard critSec{fMutex_};
89 const thread::id me = this_thread::get_id ();
90 for (
const shared_ptr<Entry_>& e : entries) {
92 [[maybe_unused]] lock_guard critSec{fMutex_};
96 e->fRunningOn.push_back (me);
98 [[maybe_unused]]
auto&& cleanup =
Finally ([&] ()
noexcept {
100 [[maybe_unused]] lock_guard critSec{fMutex_};
101 e->fRunningOn.erase (find (e->fRunningOn.begin (), e->fRunningOn.end (), me));
103 fCallEnded_.notify_all ();
106 e->fCallback (args...);
108 catch (
const Thread::AbortException&) {
112 DbgTrace (
"CallbackRegistry: ignoring exception from a callback: {}"_f, current_exception ());
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >