aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-09-04 13:30:11 +0200
committerEelco Dolstra <edolstra@gmail.com>2019-09-04 13:30:11 +0200
commite302ba0e65ba875b7bafd6265285e5f06384b617 (patch)
treefe52d8a58f8f9bb3f57b8aee5b06aee52937c714 /src/libutil
parent2dbd69dbf4538d5b7947d192979ff4feab322c2e (diff)
parentb774845af7a645b44bff69cf9f655c47fe4b9fb2 (diff)
Merge remote-tracking branch 'origin/master' into flakes
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.hh19
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());