diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2019-09-04 13:30:11 +0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2019-09-04 13:30:11 +0200 |
commit | e302ba0e65ba875b7bafd6265285e5f06384b617 (patch) | |
tree | fe52d8a58f8f9bb3f57b8aee5b06aee52937c714 /src/libutil | |
parent | 2dbd69dbf4538d5b7947d192979ff4feab322c2e (diff) | |
parent | b774845af7a645b44bff69cf9f655c47fe4b9fb2 (diff) |
Merge remote-tracking branch 'origin/master' into flakes
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/util.hh | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 1f3d1e2ae..2bf9725af 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -469,21 +469,34 @@ string get(const T & map, const string & key, const string & def = "") type T or an exception. (We abuse std::future<T> to pass the value or exception.) */ template<typename T> -struct Callback +class Callback { std::function<void(std::future<T>)> fun; + std::atomic_flag done = ATOMIC_FLAG_INIT; + +public: Callback(std::function<void(std::future<T>)> fun) : fun(fun) { } - void operator()(T && t) const + Callback(Callback && callback) : fun(std::move(callback.fun)) + { + auto prev = callback.done.test_and_set(); + if (prev) done.test_and_set(); + } + + void operator()(T && t) noexcept { + auto prev = done.test_and_set(); + assert(!prev); std::promise<T> promise; promise.set_value(std::move(t)); fun(promise.get_future()); } - void rethrow(const std::exception_ptr & exc = std::current_exception()) const + void rethrow(const std::exception_ptr & exc = std::current_exception()) noexcept { + auto prev = done.test_and_set(); + assert(!prev); std::promise<T> promise; promise.set_exception(exc); fun(promise.get_future()); |