Anklang-0.3.0.dev956+gd75ac925 anklang-0.3.0.dev956+gd75ac925
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
callback.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#pragma once
3
4#include <ase/defs.hh>
5#include <algorithm>
6
7namespace Ase {
8
9// == CallbackList<> ==
11template<class... A>
12class CallbackList : public std::enable_shared_from_this<CallbackList<A...>> {
13 CallbackList() {}
14public:
16 using Callback = std::function<void(const A&...)>;
18 bool empty () const { return funcs_.empty(); }
20 bool del (size_t id) { return del_id (id); }
22 size_t add (const Callback &f) { return add_id (f); }
24 std::function<void()>
26 {
27 std::shared_ptr<CallbackList> callbacklistp = this->shared_from_this();
28 ASE_ASSERT_RETURN (callbacklistp != nullptr, {});
29 const size_t id = add_id (f);
30 auto destroy_callback = [id, callbacklistp] () { callbacklistp->del (id); };
31 return destroy_callback;
32 }
34 void
35 call (const std::function<void(const Callback&, const A&...)> &wrapper, const A &...args)
36 {
37 size_t next = 0;
38 iters_.push_back (&next);
39 while (next < funcs_.size())
40 // increment next *before* calling callback to be accurate and adjusted by del_id()
41 wrapper (funcs_[next++].func, std::forward<const A> (args)...);
42 const size_t old_size = iters_.size();
43 iters_.erase (std::remove_if (iters_.begin(), iters_.end(),
44 [&next] (const size_t *p) { return p == &next; }),
45 iters_.end());
46 ASE_ASSERT_RETURN (1 == old_size - iters_.size());
47 }
49 void
50 operator() (const A &...args)
51 {
52 auto caller = [] (const Callback &cb, const A &...args) { cb (std::forward<const A> (args)...); };
53 return call (caller, std::forward<const A> (args)...);
54 }
55private:
56 struct Entry { Callback func; size_t id = 0; };
57 std::vector<Entry> funcs_;
59 static size_t
60 newid()
61 {
62 static size_t counter = 0;
63 return ++counter;
64 }
65 size_t
66 add_id (const Callback &f)
67 {
68 const size_t id = newid();
69 funcs_.push_back ({ f, id });
70 return id;
71 }
72 bool
73 del_id (const size_t id)
74 {
75 for (size_t j = 0; j < funcs_.size(); j++)
76 if (funcs_[j].id == id) {
77 funcs_.erase (funcs_.begin() + j);
78 for (size_t i = 0; i < iters_.size(); i++)
79 if (j < *iters_[i]) // if a callback *before* next
80 *iters_[i] -= 1; // was deleted, adjust next
81 return true;
82 }
83 return false;
84 }
85 ASE_CLASS_NON_COPYABLE (CallbackList);
86};
87
88// == RtCall ==
90struct RtCall {
92 template<typename T> RtCall (T &o, void (T::*f) ());
94 template<typename T> RtCall (void (*f) (T*), T *d);
96 /*ctor*/ RtCall (void (*f) ());
98 explicit RtCall (const RtCall &call);
100 void invoke ();
102 /*dtor*/ ~RtCall ();
103private:
104 static constexpr int pdsize = 4;
105 ptrdiff_t mem_[pdsize] = { 0, 0, 0, 0 };
106 struct Callable {
107 virtual void call () const = 0;
108 };
109 const Callable* callable () const;
110};
111
112// == JobQueue for cross-thread invocations ==
113struct JobQueue {
114 using Caller = std::function<void (const std::function<void()>&)>;
115 explicit JobQueue (const Caller &caller);
116 template<typename F> std::invoke_result_t<F>
117 inline operator+= (const F &job);
118private:
119 const Caller caller_;
120};
121
122// == Implementation Details ==
123template<typename T>
124RtCall::RtCall (T &o, void (T::*f) ())
125{
126 struct Wrapper : Callable {
127 Wrapper (T &o, void (T::*f) ()) : f_ (f), o_ (&o) {}
128 void call() const override { return (o_->*f_)(); }
129 void (T::*f_) (); T *o_;
130 };
131 static_assert (sizeof (mem_) >= sizeof (Wrapper));
132 Wrapper *w = new (mem_) Wrapper { o, f };
133 ASE_ASSERT_RETURN (w == (void*) mem_);
134}
135
136template<typename T>
137RtCall::RtCall (void (*f) (T*), T *d)
138{
139 struct Wrapper : Callable {
140 Wrapper (void (*f) (T*), T *d) : f_ (f), d_ (d) {}
141 void call() const override { return f_ (d_); }
142 void (*f_) (T*); T *d_;
143 };
144 static_assert (sizeof (mem_) >= sizeof (Wrapper));
145 Wrapper *w = new (mem_) Wrapper { f, d };
146 ASE_ASSERT_RETURN (w == (void*) mem_);
147}
148
149template<typename F> std::invoke_result_t<F>
150JobQueue::operator+= (const F &job)
151{
152 using JobReturnType = std::invoke_result_t<F>;
154 caller_ (job);
155}
156
157} // Ase
158
T begin(T... args)
Reentrant callback list with configurable arguments.
Definition callback.hh:12
void call(const std::function< void(const Callback &, const A &...)> &wrapper, const A &...args)
Call all callbacks in the order they were added via wrapper function.
Definition callback.hh:35
void operator()(const A &...args)
Call all callbacks in the order they were added.
Definition callback.hh:50
size_t add(const Callback &f)
Add a callback, returns an id that can be used for deletion.
Definition callback.hh:22
bool del(size_t id)
Delete a previously added callback via its id, returns if any was found.
Definition callback.hh:20
std::function< void()> add_delcb(const Callback &f)
Add a callback and return a deleter that removes the callback when invoked.
Definition callback.hh:25
bool empty() const
Check if the callback list is empty, i.e. invocation will not call any callbacks.
Definition callback.hh:18
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
Definition cxxaux.hh:81
#define ASE_DEFINE_MAKE_SHARED(CLASS)
Define a member function static shared_ptr<CLASS> make_shared(ctorargs...);.
Definition cxxaux.hh:274
#define ASE_CLASS_NON_COPYABLE(ClassName)
Delete copy ctor and assignment operator.
Definition cxxaux.hh:110
T empty(T... args)
T end(T... args)
T erase(T... args)
The Anklang C++ API namespace.
Definition api.hh:8
T push_back(T... args)
T remove_if(T... args)
T size(T... args)
Wrap simple callback pointers, without using malloc (obstruction free).
Definition callback.hh:90
void invoke()
Invoke the wrapped function call.
Definition callback.cc:43
~RtCall()
Clear function pointers.
Definition callback.cc:11
RtCall(T &o, void(T::*f)())
Wrap a simple void func() object member function call.
Definition callback.hh:124