Skip to content

Instantly share code, notes, and snippets.

@sean-parent
Created January 29, 2017 23:34
Show Gist options
  • Save sean-parent/24df3eefd51068ba34c482f6e71da2c2 to your computer and use it in GitHub Desktop.
Save sean-parent/24df3eefd51068ba34c482f6e71da2c2 to your computer and use it in GitHub Desktop.
#include <functional>
#include <future>
#include <memory>
#include <type_traits>
#include <dispatch/dispatch.h>
namespace stlab {
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()>;
struct shared_t {
packaged_type _f;
std::future<result_type> _result;
std::atomic_flag _start = ATOMIC_FLAG_INIT;
explicit shared_t(packaged_type f) : _f(std::move(f)), _result(_f.get_future()) { }
void run() { if (!_start.test_and_set()) _f(); }
};
auto shared = std::make_shared<shared_t>(packaged_type(std::bind([_f = std::forward<Function>(f)](Args&... args) {
return _f(std::move(args)...);
}, std::forward<Args>(args)...)));
dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
new std::weak_ptr<shared_t>(shared), [](void* _p){
auto p = static_cast<std::weak_ptr<shared_t>*>(_p);
auto lock = p->lock();
if (lock) lock->run();
delete p;
});
return std::async(std::launch::deferred, [_shared = shared] {
_shared->run(); return _shared->_result.get();
});
}
} // namespace stlab
#include <iostream>
using namespace std;
struct annotate {
annotate() { cout << "annotate ctor" << endl; }
annotate(const annotate&) { cout << "annotate copy-ctor" << endl; }
annotate(annotate&&) noexcept { cout << "annotate move-ctor" << endl; }
annotate& operator=(const annotate&) { cout << "annotate assign" << endl; return *this; }
annotate& operator=(annotate&&) noexcept { cout << "annotate move-assign" << endl; return *this; }
~annotate() { cout << "annotate dtor" << endl; }
friend inline void swap(annotate&, annotate&) { cout << "annotate swap" << endl; }
friend inline bool operator==(const annotate&, const annotate&) { return true; }
friend inline bool operator!=(const annotate&, const annotate&) { return false; }
};
int main() {
{
auto x = stlab::async([_a = annotate()]{
cout << "executed" << endl;
});
x.get();
}
cout << "cancel" << endl;
stlab::async([_a = annotate()]{
cout << "executed" << endl;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment