Skip to content

Instantly share code, notes, and snippets.

@sean-parent
Last active January 9, 2017 00:40
Show Gist options
  • Save sean-parent/9ea6975e830e71e99c3e1e07132d7726 to your computer and use it in GitHub Desktop.
Save sean-parent/9ea6975e830e71e99c3e1e07132d7726 to your computer and use it in GitHub Desktop.
Playing with example of replacing mutex with serial queue.
#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