Created
April 19, 2022 20:19
-
-
Save theanalyst/e94fa8e3d0196bb7110e3974aacf4b79 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#include <iostream> | |
#include <functional> | |
#include <string_view> | |
#include <mutex> | |
#include <map> | |
#include <thread> | |
#include <chrono> | |
#include <future> | |
template <typename ...Args> | |
class ObserverMgr | |
{ | |
public: | |
using observer_tag_t = uint64_t; | |
using callback_fn_t = std::function<void(Args...)>; | |
observer_tag_t addObserver(callback_fn_t&& cb) | |
{ | |
std::lock_guard lg{observer_mtx}; | |
callbacks.emplace(++index, std::forward<callback_fn_t>(cb)); | |
std::cout << "Added Observer: " << index << "\n"; | |
return index; | |
} | |
void removeObserver(observer_tag_t i) | |
{ | |
std::lock_guard lg{observer_mtx}; | |
std::cout << "Removed Observer: " << index << "\n"; | |
callbacks.erase(i); | |
} | |
void handleChange(Args&&... args) | |
{ | |
{ | |
std::lock_guard lg{observer_mtx}; | |
for (auto it : callbacks) { | |
callback_futures.emplace_back(std::async(std::launch::async, | |
it.second, | |
std::forward<Args>(args)...));; | |
} | |
} | |
callback_futures.erase(std::remove_if(callback_futures.begin(), | |
callback_futures.end(), | |
[](std::future<void>& fut) { | |
return (fut.wait_for(std::chrono::seconds(0)) == std::future_status::ready); | |
}), | |
callback_futures.end()); | |
} | |
private: | |
std::mutex observer_mtx; | |
observer_tag_t index = 0; | |
std::map<observer_tag_t, callback_fn_t> callbacks; | |
std::vector<std::future<void>> callback_futures; | |
}; | |
enum class Status { | |
SCHEDULED, | |
SUCCESS, | |
FAILURE | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
ObserverMgr<Status,std::string_view> mgr; | |
auto tag = mgr.addObserver([](Status s, std::string_view str) { | |
switch (s) { | |
case Status::SCHEDULED: | |
std::cout << "Scheduled tag: " << str << "\n"; | |
break; | |
case Status::SUCCESS: | |
std::cout << "Success! tag: " << str << "\n"; | |
break; | |
case Status::FAILURE: [[fallthrough]]; | |
default: | |
std::cerr << "Failed scheduling tag: " << str << "\n"; | |
} | |
}); | |
auto tag2 = mgr.addObserver([](Status s, std::string_view str) { | |
using namespace std::chrono_literals; | |
std::this_thread::sleep_for(20s); | |
std::cout << "Tracked tag: " << str << "\n"; | |
}); | |
mgr.handleChange(Status::SCHEDULED, "item1"); | |
std::cout << "Doing Something else in the main thread!" << std::endl; | |
mgr.handleChange(Status::FAILURE, "item0"); | |
mgr.removeObserver(tag2); | |
mgr.handleChange(Status::SUCCESS, "item3"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment