Last active
January 9, 2017 00:40
-
-
Save sean-parent/9ea6975e830e71e99c3e1e07132d7726 to your computer and use it in GitHub Desktop.
Playing with example of replacing mutex with serial queue.
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
#include <future> | |
#include <iostream> | |
#include <memory> | |
#include <string> | |
#include <thread> | |
#include <unordered_map> | |
#include <dispatch/dispatch.h> | |
using namespace std; | |
class serial_queue { | |
dispatch_queue_t _q = dispatch_queue_create("com.stlab.serial_queue", NULL); | |
public: | |
serial_queue() = default; | |
serial_queue(const char* name) : _q{ dispatch_queue_create(name, NULL) } { } | |
~serial_queue() { dispatch_release(_q); } | |
template <class Function, class... Args> | |
auto async(Function&& f, Args&&... args ) | |
{ | |
using result_type = std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>; | |
using packaged_type = std::packaged_task<result_type()>; | |
auto p = new packaged_type(std::bind([_f = std::forward<Function>(f)](Args&... args) { | |
return _f(std::move(args)...); | |
}, std::forward<Args>(args)...)); | |
auto result = p->get_future(); | |
dispatch_async_f(_q, | |
p, [](void* f_) { | |
packaged_type* f = static_cast<packaged_type*>(f_); | |
(*f)(); | |
delete f; | |
}); | |
return result; | |
} | |
}; | |
class registry { | |
mutex _mutex; | |
unordered_map<string, string> _map; | |
public: | |
void set(string key, string value) { | |
unique_lock<mutex> lock(mutex); | |
_map.emplace(move(key), move(value)); | |
} | |
string get(const string& key) { | |
unique_lock<mutex> lock(mutex); | |
return _map.at(key); | |
} | |
}; | |
class async_registry { | |
// NOTE: destruction order matters | |
serial_queue _q; | |
using map_t = unordered_map<string, string>; | |
shared_ptr<map_t> _map = make_shared<map_t>(); | |
public: | |
void set(string key, string value) { | |
_q.async([_map = _map](string key, string value) { | |
_map->emplace(move(key), move(value)); | |
}, move(key), move(value)) /* .detatch() */; | |
} | |
auto get(string key) { | |
return _q.async([_map = _map](string key) { | |
return _map->at(key); | |
}, move(key)); | |
} | |
}; | |
int main() { | |
std::future<string> result; | |
{ | |
async_registry registry; | |
registry.set("Hello", "world!"); | |
result = registry.get("Hello"); | |
} | |
try { | |
cout << result.get() << endl; | |
} catch (std::exception& error) { | |
cout << "error: " << error.what() << endl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment