171 lines
3.0 KiB
C++
Executable File
171 lines
3.0 KiB
C++
Executable File
// License: Modified MIT (NON-AI)
|
|
// See the LICENSE file in the root directory for license information.
|
|
// Copyright 2026 Timothy Prepscius
|
|
|
|
#pragma once
|
|
|
|
#include "PromiseLocked.h"
|
|
#include "Future.hpp"
|
|
#include <tjp/core/type_traits/is_callable.hpp>
|
|
|
|
namespace tjp {
|
|
namespace core {
|
|
|
|
template<typename T>
|
|
struct PromiseLocked
|
|
{
|
|
Mutex m;
|
|
bool owned = false;
|
|
Promise<T> promise;
|
|
|
|
std::tuple<bool, Future<T>> own_future()
|
|
{
|
|
auto l = lock_of(m);
|
|
|
|
if (promise.is_set() || owned)
|
|
return { false, promise.get_future() };
|
|
|
|
owned = true;
|
|
return { true, promise.get_future() };
|
|
}
|
|
|
|
template <typename U=T,
|
|
typename std::enable_if<!std::is_void<U>::value, U>::type* = nullptr
|
|
>
|
|
void set_value (U &&t)
|
|
{
|
|
auto l = lock_of(m);
|
|
debug_assert(owned);
|
|
|
|
promise.set_value(t);
|
|
owned = false;
|
|
}
|
|
|
|
template <typename U=T,
|
|
typename std::enable_if<!std::is_void<U>::value, U>::type* = nullptr
|
|
>
|
|
void set_value (const U &t)
|
|
{
|
|
auto l = lock_of(m);
|
|
debug_assert(owned);
|
|
|
|
promise.set_value(t);
|
|
owned = false;
|
|
}
|
|
|
|
template <typename U=void,
|
|
typename std::enable_if<std::is_void<U>::value, U>::type* = nullptr
|
|
>
|
|
void set_value ()
|
|
{
|
|
auto l = lock_of(m);
|
|
debug_assert(owned);
|
|
promise.set_value();
|
|
|
|
owned = false;
|
|
}
|
|
|
|
void set_exception (Exception &&e)
|
|
{
|
|
auto l = lock_of(m);
|
|
debug_assert(owned);
|
|
promise.set_exception(std::move(e));
|
|
|
|
owned = false;
|
|
}
|
|
|
|
template<typename F,
|
|
typename std::enable_if<std::is_invocable<F>::value>::type* = nullptr
|
|
>
|
|
void consume (F &&f)
|
|
{
|
|
auto l = lock_of(m);
|
|
|
|
debug_assert(owned);
|
|
promise.consume(std::forward<F>(f));
|
|
|
|
owned = false;
|
|
}
|
|
|
|
template<typename F,
|
|
typename std::enable_if<std::is_invocable<F>::value>::type* = nullptr
|
|
>
|
|
void reset_consume (F &&f)
|
|
{
|
|
debug_assert(owned);
|
|
Promise<T> o = reset();
|
|
|
|
o.consume(std::forward<F>(f));
|
|
}
|
|
|
|
template<typename F,
|
|
typename std::enable_if<!std::is_invocable<F>::value>::type* = nullptr
|
|
>
|
|
void consume (F &&f)
|
|
{
|
|
consume([&f]() { return f.get(); });
|
|
}
|
|
|
|
template<typename F,
|
|
typename std::enable_if<!std::is_invocable<F>::value>::type* = nullptr
|
|
>
|
|
void reset_consume (F &&f)
|
|
{
|
|
reset_consume([&f]() { return f.get(); });
|
|
}
|
|
|
|
template<typename V>
|
|
void consume_value (const V &v)
|
|
{
|
|
auto l = lock_of(m);
|
|
debug_assert(owned);
|
|
set_value(v);
|
|
|
|
owned = false;
|
|
}
|
|
|
|
template<typename V>
|
|
void reset_consume_value (const V &v)
|
|
{
|
|
debug_assert(owned);
|
|
|
|
Promise<T> o = reset();
|
|
o.set_value(v);
|
|
}
|
|
|
|
void release ()
|
|
{
|
|
auto l = lock_of(m);
|
|
debug_assert(owned);
|
|
|
|
owned = false;
|
|
}
|
|
|
|
Promise<T> reset ()
|
|
{
|
|
auto l = lock_of(m);
|
|
|
|
owned = false;
|
|
auto r = std::move(promise);
|
|
promise = {};
|
|
|
|
return r;
|
|
}
|
|
} ;
|
|
|
|
template<typename R, typename F>
|
|
PromiseLocked<R> &promise_of_and_reset(PromiseLocked<R> &p, F &&f)
|
|
{
|
|
p.reset_consume(std::forward<F>(f));
|
|
return p;
|
|
}
|
|
|
|
template<typename R, typename V>
|
|
PromiseLocked<R> &promise_of_and_reset_value(PromiseLocked<R> &p, const V &v)
|
|
{
|
|
p.reset_consume_value(v);
|
|
return p;
|
|
}
|
|
} // namespace
|
|
} // namespace
|