22 template<
class Source_,
typename... Params_>
24 virtual void Fire(std::mutex &locker, Source_ *, Params_...) = 0;
26 virtual ~HandlerBase() {}
29 template<
class Source_,
typename... Params_>
30 struct EmptyHandlerFn :
public HandlerBase<Source_, Params_...> {
31 EmptyHandlerFn(std::function<
void()> fn) : fn(fn) { }
33 virtual void Fire(std::mutex &locker, Source_ *, Params_...) {
39 std::function<void()> fn;
42 template<
class Source_,
typename... Params_>
43 struct ArgsHandlerFn :
public HandlerBase<Source_, Params_...> {
44 ArgsHandlerFn(std::function<
void(Params_...)> fn) : fn(fn) { }
46 virtual void Fire(std::mutex &locker, Source_ *, Params_... args) {
49 f(std::forward<Params_>(args)...);
52 std::function<void(Params_...)> fn;
55 template<
class Source_,
typename... Params_>
56 struct FullHandlerFn :
public HandlerBase<Source_, Params_...> {
57 static_assert(!std::is_same<Source_, void>::value,
"No source class exists for this event (void cannot be passed around)");
59 FullHandlerFn(std::function<
void(Source_&, Params_...)> fn) : fn(fn) { }
61 virtual void Fire(std::mutex &locker, Source_ *source, Params_... args) {
64 f(*source, std::forward<Params_>(args)...);
67 std::function<void(Source_&, Params_...)> fn;
70 template<
class Source_,
class... Params_>
71 static HandlerBase<Source_, Params_...>& createhandlerfn(
void(*fn)()) {
72 return *
new EmptyHandlerFn<Source_, Params_...>(fn);
75 template<
class Source_,
class... Params_>
76 static HandlerBase<Source_, Params_...>& createhandlerfn(
void(*fn)(Params_...)) {
77 return *
new ArgsHandlerFn<Source_, Params_...>(fn);
80 template<
class Source_,
class... Params_>
81 static HandlerBase<Source_, Params_...>& createhandlerfn(
void(*fn)(Source_ &, Params_...)) {
82 return *
new FullHandlerFn<Source_, Params_...>(fn);
85 template<
class F_,
class Source_,
int N,
class... Params_>
86 static typename std::enable_if<TMP::FunctionTraits<F_>::Arity==0, HandlerBase<Source_, Params_...>&>::type
87 createhandler_internal(F_ fn) {
88 return *
new EmptyHandlerFn<Source_, Params_...>(fn);
91 template<
class F_,
class Source_,
int N,
typename... Params_>
92 static typename std::enable_if<TMP::FunctionTraits<F_>::Arity!=0 && TMP::FunctionTraits<F_>::Arity==
N, HandlerBase<Source_, Params_...>&>::type
93 createhandler_internal(F_ fn) {
94 return *
new ArgsHandlerFn<Source_, Params_...>(fn);
97 template<
class F_,
class Source_,
int N,
class... Params_>
98 static typename std::enable_if<TMP::FunctionTraits<F_>::Arity==
N+1, HandlerBase<Source_, Params_...>&>::type
99 createhandler_internal(F_ fn) {
100 return *
new FullHandlerFn<Source_, Params_...>(fn);
103 template<
class F_,
class Source_,
class... Params_>
104 typename std::enable_if<TMP::HasParanthesisOperator<F_>::value, HandlerBase<Source_, Params_...>&>::type
105 create_handler(F_ fn) {
106 return createhandler_internal<F_, Source_,
sizeof...(Params_), Params_...>(fn);
109 template<
class F_,
class Source_,
class... Params_,
typename N=
void>
110 typename std::enable_if<!TMP::HasParanthesisOperator<F_>::value, HandlerBase<Source_, Params_...>&>::type
111 create_handler(F_ fn) {
112 return createhandlerfn<Source_, Params_...>(fn);
133 template<
class Source_=void,
typename... Params_>
143 static_assert( std::is_same<Source_, void>::value ,
"Empty constructor cannot be used." );
147 template <
class S_ = Source_>
148 explicit Event(
typename std::enable_if<!std::is_same<S_, void>::value, S_>::type &source) : source(&source) {
150 static_assert(!std::is_same<Source_, void>::value,
"Filling constructor is not required, use the default.");
154 template <
class S_ = Source_>
155 explicit Event(
typename std::enable_if<!std::is_same<S_, void>::value, S_>::type *source) : source(source) {
156 ASSERT(source,
"Source cannot be nullptr");
158 static_assert(!std::is_same<Source_, void>::value,
"Filling constructor is not required, use the default.");
166 event.movedout =
true;
173 ASSERT(!fire.test_and_set(),
"An event cannot be destroyed while its being fired.");
174 std::lock_guard<std::mutex> g(access);
187 if(&other==
this)
return *
this;
189 std::lock_guard<std::mutex> g(access);
191 ASSERT(!fire.test_and_set(),
"An event cannot be moved into while its being fired.");
204 if(&other==
this)
return;
208 ASSERT(!fire.test_and_set() && !other.fire.test_and_set(),
"An event cannot be swapped while its being fired.");
210 swap(source, other.source);
211 swap(handlers, other.handlers);
225 ASSERT(!movedout,
"This event is moved out of");
227 auto &handler=internal::event::create_handler<F_, Source_, Params_...>(fn);
229 std::lock_guard<std::mutex> g(access);
230 handlers.Add(handler);
232 return reinterpret_cast<Token>(&handler);
244 template<
class C_,
typename... A_>
247 ASSERT(!movedout,
"This event is moved out of");
261 ASSERT(!movedout,
"This event is moved out of");
263 std::lock_guard<std::mutex> g(access);
265 auto item=
reinterpret_cast<internal::event::HandlerBase<Source_, Params_...
>*>(token);
267 auto l=handlers.FindLocation(item);
270 if(iterator.IsValid() && iterator.CurrentPtr()==item) {
285 std::lock_guard<std::recursive_mutex> g(firemtx);
287 ASSERT(!movedout,
"This event is moved out of");
290 for(iterator=handlers.begin(); iterator.IsValid(); iterator.Next()) {
294 iterator->Fire(access, source, std::forward<Params_>(args)...);
313 std::lock_guard<std::recursive_mutex> g1(firemtx);
314 std::lock_guard<std::mutex> g2(access);
317 ASSERT(!fire.test_and_set(),
"Recursion detected during event execution.");
320 if(fire.test_and_set())
return;
325 handlers.DeleteAll();
334 bool movedout =
false;
339 std::atomic_flag fire;
343 std::recursive_mutex firemtx;
346 template<
class C_,
class ...P_>
347 const typename Event<C_, P_...>::Token
Event<C_, P_...>::EmptyToken = 0;
350 template<
class Source_,
class... Args_>