Created
February 23, 2016 18:13
-
-
Save r-lyeh-archived/bd1489093b096cbb6b2a to your computer and use it in GitHub Desktop.
optimistic event dispatcher v2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if 0 | |
// [src] http://nercury.github.io/c++/interesting/2016/02/22/weak_ptr-and-event-cleanup.html | |
// optimistic event dispatcher v2 | |
// usage: | |
{ | |
OptimisticDispatcher<function<void (uint32_t, string)>> event; | |
auto subscriber = event.add([] (auto number, auto text) { | |
cout << "Number was " << number << " and text was " << text << endl; | |
}); | |
event.invoke(42, "Hello Universe!"); | |
// the subscriber is removed from event here automatically | |
} | |
#endif | |
#pragma once | |
#include <memory> | |
#include <vector> | |
/** | |
* Dispatches function on a number of callbacks and cleans up callbacks when | |
* they are dead. | |
*/ | |
template <typename C> class OptimisticDispatcher final { | |
private: | |
std::vector<std::weak_ptr<C>> callbacks; | |
int32_t concurrent_dispatcher_count = 0; | |
public: | |
std::shared_ptr<C> add(C && callback) { | |
auto shared = std::make_shared<C>(callback); | |
this->callbacks.push_back(shared); | |
return shared; | |
} | |
template <typename ...A> | |
void invoke(A && ... args) { | |
this->concurrent_dispatcher_count++; | |
// Go over all callbacks and dispatch on those that are still available. | |
typename std::vector<std::weak_ptr<C>>::iterator iter; | |
for (iter = this->callbacks.begin(); iter != this->callbacks.end(); ++iter) { | |
if (auto callback = iter->lock()) { | |
(*callback)(std::forward<A>(args)...); | |
} | |
} | |
this->concurrent_dispatcher_count--; | |
// Remove all callbacks that are gone, only if we are not dispatching. | |
if (0 == this->concurrent_dispatcher_count) { | |
std::cout << "callback count before erase " << callbacks.size() << std::endl; | |
this->callbacks.erase( | |
std::remove_if( | |
this->callbacks.begin(), | |
this->callbacks.end(), | |
[] (std::weak_ptr<C> callback) { return callback.expired(); } | |
), | |
this->callbacks.end() | |
); | |
std::cout << "callback count after erase " << callbacks.size() << std::endl; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment