Skip to content

Instantly share code, notes, and snippets.

@r-lyeh-archived
Created February 23, 2016 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r-lyeh-archived/bd1489093b096cbb6b2a to your computer and use it in GitHub Desktop.
Save r-lyeh-archived/bd1489093b096cbb6b2a to your computer and use it in GitHub Desktop.
optimistic event dispatcher v2
#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