SDL3pp
A slim C++ wrapper for SDL3
Loading...
Searching...
No Matches
SDL3pp_callbackWrapper.h
1#ifndef SDL3PP_CALLBACK_WRAPPER_H_
2#define SDL3PP_CALLBACK_WRAPPER_H_
3
4#include <functional>
5#include <map>
6#include <memory>
7#include <SDL3/SDL_assert.h>
8
9namespace SDL {
10
21{
22 void* id;
23
24public:
26 constexpr explicit CallbackHandle(void* id = nullptr)
27 : id(id)
28 {
29 }
31 constexpr void* get() const { return id; }
32
34 constexpr operator bool() const { return id != 0; }
35};
36
38template<class Result, class... Args>
40{
42 using ValueType = std::function<Result(Args...)>;
43
45 static const ValueType& Unwrap(void* handle)
46 {
47 return *static_cast<ValueType*>(handle);
48 }
49
51 static Result Call(void* handle, Args... args)
52 {
53 auto& f = Unwrap(handle);
54 return f(args...);
55 }
56
58 static Result CallSuffixed(Args... args, void* handle)
59 {
60 auto& f = Unwrap(handle);
61 return f(args...);
62 }
63};
64
65template<class F>
67
78template<class Result, class... Args>
79struct CallbackWrapper<std::function<Result(Args...)>>
80 : CallbackWrapperBase<Result, Args...>
81{
82 CallbackWrapper() = delete;
83
85 using ValueType = std::function<Result(Args...)>;
86
93 static ValueType* Wrap(ValueType&& cb)
94 {
95 return new ValueType(std::move(cb));
96 }
97
99 static Result CallOnce(void* handle, Args... args)
100 {
101 auto f = release(handle);
102 return f(args...);
103 }
104
106 static Result CallOnceSuffixed(Args... args, void* handle)
107 {
108 auto f = release(handle);
109 return f(args...);
110 }
111
119 static ValueType release(void* handle)
120 {
121 if (handle == nullptr) return {};
122 auto ptr = static_cast<ValueType*>(handle);
123 ValueType value{std::move(*ptr)};
124 delete ptr;
125 return value;
126 }
127
129 static const ValueType release(CallbackHandle handle)
130 {
131 return release(handle.get());
132 }
133};
134
143template<class KEY, class VALUE, size_t VARIANT = 0>
145{
146 static_assert(sizeof(KEY) <= sizeof(void*));
147 KeyValueWrapper() = delete;
148
150 using KeyType = KEY;
151
153 using ValueType = VALUE;
154
162 static ValueType* Wrap(KeyType key, ValueType&& value)
163 {
164 auto lockGuard = lock();
165 return &Values().insert_or_assign(key, std::move(value)).first->second;
166 }
167
169 static bool contains(KeyType handle)
170 {
171 auto lockGuard = lock();
172 return Values().contains(handle);
173 }
174
176 static const ValueType& at(KeyType handle)
177 {
178 auto lockGuard = lock();
179 return Values().at(handle);
180 }
181
184 {
185 auto lockGuard = lock();
186 auto& values = Values();
187 auto it = values.find(key);
188 if (it == values.end()) return {};
189 ValueType value{std::move(it->second)};
190 values.erase(it);
191 return value;
192 }
193
200 static bool erase(KeyType key)
201 {
202 auto lockGuard = lock();
203 return Values().erase(key);
204 }
205
206private:
207 static std::map<KeyType, ValueType>& Values()
208 {
209 static std::map<KeyType, ValueType> values;
210 return values;
211 }
212
213 static std::lock_guard<std::mutex> lock()
214 {
215 static std::mutex uniqueMutex;
216 return std::lock_guard{uniqueMutex};
217 }
218};
219
221template<class KEY, class VALUE, size_t VARIANT = 0>
223
225template<class KEY, class Result, class... Args, size_t VARIANT>
226struct KeyValueCallbackWrapper<KEY, std::function<Result(Args...)>, VARIANT>
227 : CallbackWrapperBase<Result, Args...>
228 , KeyValueWrapper<KEY, std::function<Result(Args...)>, VARIANT>
229{
230 KeyValueCallbackWrapper() = delete;
231
233 using ValueType = std::function<Result(Args...)>;
234};
235
241template<class VALUE>
243
247template<class Result, class... Args>
248struct UniqueCallbackWrapper<std::function<Result(Args...)>>
249 : CallbackWrapperBase<Result, Args...>
250{
251 UniqueCallbackWrapper() = delete;
252
254 using ValueType = std::function<Result(Args...)>;
255
262 static ValueType* Wrap(ValueType&& value)
263 {
264 auto lockGuard = lock();
265 auto& v = Value();
266 v = std::move(value);
267 return &v;
268 }
269
271 static bool contains(void* handle)
272 {
273 auto lockGuard = lock();
274 auto& v = Value();
275 return bool(v) && &v == handle;
276 }
277
279 static ValueType at(void* handle)
280 {
281 if (&get() == handle) {
283 }
284 return {};
285 }
286
288 static const ValueType& get()
289 {
290 auto lockGuard = lock();
291 return Value();
292 }
293
296 {
297 auto lockGuard = lock();
298 ValueType value{std::move(Value())};
299 return value;
300 }
301
303 static ValueType release(void* handle)
304 {
305 SDL_assert_paranoid(&get() == handle);
306 return release();
307 }
308
310 static void erase()
311 {
312 auto lockGuard = lock();
313 Value() = {};
314 }
315
316private:
317 static ValueType& Value()
318 {
319 static ValueType value;
320 return value;
321 }
322
323 static std::lock_guard<std::mutex> lock()
324 {
325 static std::mutex uniqueMutex;
326 return std::lock_guard{uniqueMutex};
327 }
328};
329
331
332} // namespace SDL
333
334#endif /* SDL3PP_CALLBACK_WRAPPER_H_ */
A typesafe handle for callback.
Definition SDL3pp_callbackWrapper.h:21
constexpr void * get() const
Get Internal id.
Definition SDL3pp_callbackWrapper.h:31
#define SDL_assert_paranoid(condition)
An assertion test that is performed only when built with paranoid settings.
Definition SDL3pp_assert.h:374
the main namespace where all SDL3pp public functions and types live
Definition SDL3pp_assert.h:7
Base class for callback wrappers.
Definition SDL3pp_callbackWrapper.h:40
static Result CallSuffixed(Args... args, void *handle)
Call with suffix handle.
Definition SDL3pp_callbackWrapper.h:58
static Result Call(void *handle, Args... args)
Call.
Definition SDL3pp_callbackWrapper.h:51
std::function< Result(Args...)> ValueType
The wrapped std::function type.
Definition SDL3pp_callbackWrapper.h:42
static const ValueType & Unwrap(void *handle)
Return unwrapped value of handle.
Definition SDL3pp_callbackWrapper.h:45
static Result CallOnce(void *handle, Args... args)
Call once and release.
Definition SDL3pp_callbackWrapper.h:99
static ValueType release(void *handle)
Transfer ownership from the function and delete handle.
Definition SDL3pp_callbackWrapper.h:119
static Result CallOnceSuffixed(Args... args, void *handle)
Call once and release with suffix handle.
Definition SDL3pp_callbackWrapper.h:106
static ValueType * Wrap(ValueType &&cb)
Change the callback into a void* pointer.
Definition SDL3pp_callbackWrapper.h:93
static const ValueType release(CallbackHandle handle)
Return unwrapped value of handle.
Definition SDL3pp_callbackWrapper.h:129
std::function< Result(Args...)> ValueType
The wrapped std::function type.
Definition SDL3pp_callbackWrapper.h:85
Definition SDL3pp_callbackWrapper.h:66
std::function< Result(Args...)> ValueType
Wrapped type.
Definition SDL3pp_callbackWrapper.h:233
Store callbacks by key.
Definition SDL3pp_callbackWrapper.h:222
Wrapper key to value result callbacks.
Definition SDL3pp_callbackWrapper.h:145
static ValueType release(KeyType key)
Return unwrapped value associated by key and remove association.
Definition SDL3pp_callbackWrapper.h:183
KEY KeyType
Key type.
Definition SDL3pp_callbackWrapper.h:150
static bool erase(KeyType key)
Remove association.
Definition SDL3pp_callbackWrapper.h:200
static bool contains(KeyType handle)
True if handle is stored.
Definition SDL3pp_callbackWrapper.h:169
VALUE ValueType
Value type.
Definition SDL3pp_callbackWrapper.h:153
static ValueType * Wrap(KeyType key, ValueType &&value)
Change the value into a void* pointer held by key.
Definition SDL3pp_callbackWrapper.h:162
static const ValueType & at(KeyType handle)
Return unwrapped value of handle.
Definition SDL3pp_callbackWrapper.h:176
static const ValueType & get()
Return wrapped type, if handle is contained.
Definition SDL3pp_callbackWrapper.h:288
static void erase()
Erase value from store.
Definition SDL3pp_callbackWrapper.h:310
static ValueType release(void *handle)
Return wrapped type and erase it from store.
Definition SDL3pp_callbackWrapper.h:303
static bool contains(void *handle)
True if handle equals to wrapped value.
Definition SDL3pp_callbackWrapper.h:271
std::function< Result(Args...)> ValueType
Wrapped type.
Definition SDL3pp_callbackWrapper.h:254
static ValueType release()
Return wrapped type and erase it from store.
Definition SDL3pp_callbackWrapper.h:295
static ValueType at(void *handle)
Return wrapped type, if handle is contained.
Definition SDL3pp_callbackWrapper.h:279
static ValueType * Wrap(ValueType &&value)
Change the value into a void* pointer held uniquely by this type.
Definition SDL3pp_callbackWrapper.h:262
Stored Wrapper unique by type result callbacks.
Definition SDL3pp_callbackWrapper.h:242