diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2021-09-15 20:33:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-15 20:33:44 +0200 |
commit | 79152e307e7eef667c3de9c21571d017654a7c32 (patch) | |
tree | 67fd413bcf0b42c5ada7eddc41a04f7bd99df3a8 /src/libutil/callback.hh | |
parent | 7349f257da8278af9aae35544b15c9a204e2a57b (diff) | |
parent | 3b82c1a5fef521ebadea5df12384390c8c24100c (diff) |
Merge pull request #5212 from mkenigs/auto-uid-allocation
Merge master into #3600
Diffstat (limited to 'src/libutil/callback.hh')
-rw-r--r-- | src/libutil/callback.hh | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/libutil/callback.hh b/src/libutil/callback.hh new file mode 100644 index 000000000..ef31794be --- /dev/null +++ b/src/libutil/callback.hh @@ -0,0 +1,46 @@ +#pragma once + +#include <future> +#include <functional> + +namespace nix { + +/* A callback is a wrapper around a lambda that accepts a valid of + type T or an exception. (We abuse std::future<T> to pass the value or + exception.) */ +template<typename T> +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) { } + + 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()) noexcept + { + auto prev = done.test_and_set(); + assert(!prev); + std::promise<T> promise; + promise.set_exception(exc); + fun(promise.get_future()); + } +}; + +} |