flatten 20260225
This commit is contained in:
28
tjp/core/future/custom/Future.cpp
Executable file
28
tjp/core/future/custom/Future.cpp
Executable file
@@ -0,0 +1,28 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#include "Future.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
namespace futures {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//typedef std::list<Cancelable *> Stack;
|
||||
//ThreadSpecificSingleton<Stack> stack;
|
||||
|
||||
//CancelFrame::CancelFrame(Cancelable *c)
|
||||
//{
|
||||
// stack->push_back(c);
|
||||
//}
|
||||
|
||||
//CancelFrame::~CancelFrame()
|
||||
//{
|
||||
// stack->pop_back();
|
||||
//}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
6
tjp/core/future/custom/Future.h
Executable file
6
tjp/core/future/custom/Future.h
Executable file
@@ -0,0 +1,6 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Future_.h"
|
||||
#include "Future_void.h"
|
||||
14
tjp/core/future/custom/Future.hpp
Executable file
14
tjp/core/future/custom/Future.hpp
Executable file
@@ -0,0 +1,14 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
//#define FUTURES_ENABLE_LOG
|
||||
//#define FUTURES_THEN_ON_CONSTRUCT
|
||||
#define FUTURES_THEN_ON_SET
|
||||
//#define FUTURES_THEN_ON_WAIT
|
||||
|
||||
//#define CORE_FUTURE_USE_STRONG_EXCEPTION_PTR
|
||||
#define CORE_FUTURE_USE_STD_EXCEPTION_PTR
|
||||
|
||||
#include "Future_.hpp"
|
||||
#include "Future_void.hpp"
|
||||
69
tjp/core/future/custom/Future_.h
Executable file
69
tjp/core/future/custom/Future_.h
Executable file
@@ -0,0 +1,69 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
namespace futures {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct Shared;
|
||||
|
||||
template<typename T>
|
||||
struct Shared_;
|
||||
|
||||
template<typename T>
|
||||
struct Promise;
|
||||
|
||||
template<typename T>
|
||||
struct Future;
|
||||
|
||||
struct Dependency;
|
||||
|
||||
struct Cancelable;
|
||||
|
||||
struct CancelFrame;
|
||||
|
||||
template<typename T>
|
||||
struct Then;
|
||||
|
||||
template<typename T>
|
||||
struct Shared_;
|
||||
|
||||
template<typename T>
|
||||
struct Shared;
|
||||
|
||||
template<typename T>
|
||||
struct Promise_;
|
||||
|
||||
template<typename T>
|
||||
struct Promise;
|
||||
|
||||
template<typename T>
|
||||
struct Future_;
|
||||
|
||||
template<typename T>
|
||||
struct Future;
|
||||
|
||||
} // namespace
|
||||
|
||||
template<typename T>
|
||||
using Promise = detail::Promise<T>;
|
||||
|
||||
template<typename T>
|
||||
using Future = detail::Future<T>;
|
||||
|
||||
} // namespace
|
||||
|
||||
template<typename T>
|
||||
using Promise = futures::Promise<T>;
|
||||
|
||||
template<typename T>
|
||||
using Future = futures::Future<T>;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
|
||||
513
tjp/core/future/custom/Future_.hpp
Executable file
513
tjp/core/future/custom/Future_.hpp
Executable file
@@ -0,0 +1,513 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Future_Requirements.hpp"
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
namespace futures {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct Shared;
|
||||
|
||||
template<typename T>
|
||||
struct Shared_;
|
||||
|
||||
template<typename T>
|
||||
struct Promise;
|
||||
|
||||
template<typename T>
|
||||
struct Future;
|
||||
|
||||
struct Dependency {
|
||||
virtual ~Dependency() {}
|
||||
} ;
|
||||
|
||||
|
||||
#if defined(CORE_FUTURE_USE_STRONG_EXCEPTION_PTR)
|
||||
|
||||
using ExceptionPtr = StrongPtr<Exception>;
|
||||
|
||||
inline
|
||||
void future_rethrow_exception(const ExceptionPtr &exception)
|
||||
{
|
||||
throw *exception;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ExceptionPtr make_exception(T &&t)
|
||||
{
|
||||
return strong<std::decay_t<T>>(std::forward<T>(t));
|
||||
}
|
||||
|
||||
#define CORE_FUTURE_CATCH_BEGIN(e) \
|
||||
catch (Exception &e)
|
||||
|
||||
#define CORE_FUTURE_CATCH_END
|
||||
|
||||
|
||||
#elif defined(CORE_FUTURE_USE_STD_EXCEPTION_PTR)
|
||||
|
||||
using ExceptionPtr = std::exception_ptr;
|
||||
|
||||
inline
|
||||
void future_rethrow_exception(const ExceptionPtr &exception)
|
||||
{
|
||||
std::rethrow_exception(exception);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ExceptionPtr make_exception(T &&t)
|
||||
{
|
||||
try
|
||||
{
|
||||
throw t;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
ExceptionPtr make_exception(ExceptionPtr exception)
|
||||
{
|
||||
return exception;
|
||||
}
|
||||
|
||||
#define CORE_FUTURE_CATCH_BEGIN(e) \
|
||||
catch (...) \
|
||||
{ \
|
||||
auto e = std::current_exception(); \
|
||||
|
||||
|
||||
#define CORE_FUTURE_CATCH_END \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct Then : Dependency
|
||||
{
|
||||
StrongPtr<Shared<T>> dependency;
|
||||
|
||||
typedef std::function<void(const StrongPtr<Shared<T>> &)> F;
|
||||
F f;
|
||||
|
||||
Then(const StrongPtr<Shared<T>> &dependency_, F &&f_) :
|
||||
dependency(dependency_),
|
||||
f(std::move(f_))
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Then, logOfThis(this) << "constructor " << type_id<T>().name());
|
||||
}
|
||||
|
||||
~Then ()
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Then, logOfThis(this) << "destructor " << type_id<T>().name());
|
||||
}
|
||||
|
||||
void execute()
|
||||
{
|
||||
auto f_ = std::move(f);
|
||||
f_(dependency);
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Shared_
|
||||
{
|
||||
typedef Shared_<T> Self;
|
||||
StrongPtr<Dependency> dependency;
|
||||
ExceptionPtr exception;
|
||||
|
||||
bool isSet;
|
||||
mutable Event::Mutex mutex;
|
||||
mutable Event event;
|
||||
|
||||
Shared_(const Shared_ &) = delete;
|
||||
Shared_(Shared_ &&) = delete;
|
||||
|
||||
Shared_ () :
|
||||
isSet(false)
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Shared_, logOfThis(this) << "constructor " << type_id<T>().name());
|
||||
}
|
||||
|
||||
~Shared_ ()
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Shared_, logOfThis(this) << "destructor " << type_id<T>().name());
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
void except_hasLock(E &&e)
|
||||
{
|
||||
debug_assert(mutex.locked_by_caller());
|
||||
exception = make_exception(std::forward<E>(e));
|
||||
set_notify();
|
||||
}
|
||||
|
||||
void set_notify ()
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Shared_::set_notify, logOfThis(this) << type_id<T>().name());
|
||||
|
||||
debug_assert(!isSet);
|
||||
isSet = true;
|
||||
dependency = {};
|
||||
event.notify_all();
|
||||
}
|
||||
|
||||
void wait () const
|
||||
{
|
||||
// first time before lock, fast
|
||||
auto l = lock_of(mutex);
|
||||
while (!isSet)
|
||||
event.wait(l);
|
||||
|
||||
#ifdef FUTURES_THEN_ON_WAIT
|
||||
if (!thens.empty())
|
||||
const_cast<Self *>(this)->execute(l);
|
||||
#endif
|
||||
}
|
||||
|
||||
void raise () const
|
||||
{
|
||||
wait();
|
||||
|
||||
if (exception)
|
||||
future_rethrow_exception(exception);
|
||||
}
|
||||
|
||||
bool is_set () const
|
||||
{
|
||||
return isSet;
|
||||
}
|
||||
|
||||
typedef std::list<WeakPtr<Then<T>>> Thens;
|
||||
Thens thens;
|
||||
|
||||
template<typename R, typename F>
|
||||
auto generate_then(
|
||||
const StrongPtr<Shared<T>> &self,
|
||||
const WeakPtr<Shared<R>> &value,
|
||||
F &&f
|
||||
)
|
||||
{
|
||||
auto then = strong<Then<T>>(
|
||||
self,
|
||||
[value, f=std::move(f)](const StrongPtr<Shared<T>> &t) {
|
||||
if (auto value_ = strong(value))
|
||||
{
|
||||
Promise<R> promise(value_);
|
||||
promise.consume(f, Future<T>(t));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return then;
|
||||
}
|
||||
|
||||
template<typename R, typename F>
|
||||
auto then(const StrongPtr<Shared<T>> &self, F &&f)
|
||||
{
|
||||
auto value = strong<Shared<R>>();
|
||||
Future<R> future(value);
|
||||
|
||||
auto then__ = generate_then(self, weak(value), std::forward<F>(f));
|
||||
|
||||
value->dependency = then__;
|
||||
thens.push_back(weak(then__));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
#ifdef FUTURES_THEN_ON_WAIT
|
||||
virtual void execute (Event::Mutex::Lock &l) = 0;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Shared : Shared_<T>
|
||||
{
|
||||
typedef Shared_<T> Super;
|
||||
|
||||
Optional<T> value;
|
||||
|
||||
template<typename ... R>
|
||||
void set(R && ... value_)
|
||||
{
|
||||
Event::Mutex::Lock l(Super::mutex);
|
||||
value.emplace(std::forward<R>(value_)...);
|
||||
Super::set_notify();
|
||||
execute(l);
|
||||
}
|
||||
|
||||
// void set(const T &value_)
|
||||
// {
|
||||
// Event::Mutex::Lock l(Super::mutex);
|
||||
// value = value_;
|
||||
// Super::set_notify();
|
||||
// execute(l);
|
||||
// }
|
||||
|
||||
template<typename E>
|
||||
void except(E &&e)
|
||||
{
|
||||
Event::Mutex::Lock l(Super::mutex);
|
||||
Super::except_hasLock(std::forward<E>(e));
|
||||
execute(l);
|
||||
}
|
||||
|
||||
// const T &get () const
|
||||
// {
|
||||
// Super::raise();
|
||||
// return value;
|
||||
// }
|
||||
|
||||
T &get ()
|
||||
{
|
||||
Super::raise();
|
||||
return *value;
|
||||
}
|
||||
|
||||
#ifdef FUTURES_THEN_ON_CONSTRUCT
|
||||
template<typename F>
|
||||
auto then(const StrongPtr<Shared<T>> &self, F &&f)
|
||||
{
|
||||
using R = decltype(f(Future<T>(this)));
|
||||
|
||||
Super::wait();
|
||||
|
||||
Promise<R> promise;
|
||||
promise.consume(f, Future<T>(self));
|
||||
return promise.get_future();
|
||||
}
|
||||
#else
|
||||
template<typename F>
|
||||
auto then(const StrongPtr<Shared<T>> &self, F &&f)
|
||||
{
|
||||
Event::Mutex::Lock l(Super::mutex);
|
||||
using R = decltype(f(Future<T>(self)));
|
||||
|
||||
auto future = Super::template then<R>(self, std::forward<F>(f));
|
||||
|
||||
if (Super::is_set())
|
||||
execute(l);
|
||||
|
||||
return future;
|
||||
}
|
||||
#endif
|
||||
|
||||
void execute (Event::Mutex::Lock &l)
|
||||
#ifdef FUTURES_THEN_ON_WAIT
|
||||
override
|
||||
#endif
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Shared_::execute, logOfThis(this) << type_id<T>().name());
|
||||
|
||||
auto thens_ = std::move(Super::thens);
|
||||
l.unlock();
|
||||
|
||||
while (!thens_.empty())
|
||||
{
|
||||
auto &then = thens_.front();
|
||||
if (auto then_ = strong(then))
|
||||
then_->execute();
|
||||
|
||||
thens_.pop_front();
|
||||
}
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct Promise_
|
||||
{
|
||||
using shared_ptr = StrongPtr<Shared<T>>;
|
||||
shared_ptr shared;
|
||||
|
||||
Promise_() :
|
||||
shared(strong<Shared<T>>())
|
||||
{
|
||||
}
|
||||
|
||||
Promise_(const StrongPtr<Shared<T>> &shared_) : shared(shared_) {}
|
||||
|
||||
template<typename E>
|
||||
static void set_exception(shared_ptr &shared, E &&exception)
|
||||
{
|
||||
shared->except(std::forward<E>(exception));
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
void set_exception(E &&exception)
|
||||
{
|
||||
set_exception(shared, std::forward<E>(exception));
|
||||
}
|
||||
|
||||
Future<T> get_future ()
|
||||
{
|
||||
return Future<T>(shared);
|
||||
}
|
||||
|
||||
bool is_set ()
|
||||
{
|
||||
return shared->is_set();
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Promise : public Promise_<T>
|
||||
{
|
||||
typedef Promise_<T> Super;
|
||||
using shared_ptr = typename Super::shared_ptr;
|
||||
|
||||
Promise() {}
|
||||
Promise(const StrongPtr<Shared<T>> &value_) : Super(value_) {}
|
||||
~Promise () {}
|
||||
|
||||
template<typename ... R>
|
||||
static void set_value(shared_ptr &shared, R && ...t)
|
||||
{
|
||||
shared->set(std::forward<R>(t)...);
|
||||
}
|
||||
|
||||
// static void set_value(shared_ptr &shared, const T &t)
|
||||
// {
|
||||
// shared->set(t);
|
||||
// }
|
||||
|
||||
template<typename ... R>
|
||||
void set_value(R && ...t)
|
||||
{
|
||||
set_value(Super::shared, std::forward<R>(t)...);
|
||||
}
|
||||
|
||||
// void set_value(const T &t)
|
||||
// {
|
||||
// set_value(Super::shared, t);
|
||||
// }
|
||||
|
||||
template<typename F, typename ... V>
|
||||
void consume(const F &f, V && ...v)
|
||||
{
|
||||
auto shared_ = weak(Super::shared);
|
||||
|
||||
try
|
||||
{
|
||||
auto result = f(std::forward<V>(v)...);
|
||||
if (auto shared = strong(shared_))
|
||||
set_value(shared, std::forward<decltype(result)>(result));
|
||||
}
|
||||
CORE_FUTURE_CATCH_BEGIN(e)
|
||||
{
|
||||
if (auto shared = strong(shared_))
|
||||
Super::set_exception(shared, e);
|
||||
}
|
||||
CORE_FUTURE_CATCH_END
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void consume(const F &f)
|
||||
{
|
||||
auto shared_ = weak(Super::shared);
|
||||
|
||||
try
|
||||
{
|
||||
auto result = f();
|
||||
if (auto shared = strong(shared_))
|
||||
this->set_value(shared, std::forward<decltype(result)>(result));
|
||||
}
|
||||
CORE_FUTURE_CATCH_BEGIN(e)
|
||||
{
|
||||
if (auto shared = strong(shared_))
|
||||
Super::set_exception(shared, e);
|
||||
}
|
||||
CORE_FUTURE_CATCH_END
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Future_
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
StrongPtr<Shared<T>> shared;
|
||||
|
||||
Future_(const StrongPtr<Shared<T>> &shared_) : shared(shared_) {}
|
||||
Future_() {}
|
||||
|
||||
~Future_ ()
|
||||
{
|
||||
FuturesLogDebug(tjp::core::futures::Future_, logOfThis(this) << " destructing " << type_id<T>().name() << ": " << SmartPtrBase::getInfoFor(ptr_of(shared)));
|
||||
}
|
||||
|
||||
void wait () const
|
||||
{
|
||||
shared->wait();
|
||||
}
|
||||
|
||||
bool valid () const
|
||||
{
|
||||
return (bool)shared;
|
||||
}
|
||||
|
||||
bool is_set () const
|
||||
{
|
||||
return shared->is_set();
|
||||
}
|
||||
|
||||
void cancel ()
|
||||
{
|
||||
shared->cancel();
|
||||
}
|
||||
} ;
|
||||
|
||||
template<typename T>
|
||||
struct Future : public Future_<T>
|
||||
{
|
||||
typedef Future_<T> Super;
|
||||
typedef T value_type;
|
||||
|
||||
Future(const StrongPtr<Shared<T>> &promise_) : Super(promise_) {}
|
||||
Future() {}
|
||||
|
||||
T &get ()
|
||||
{
|
||||
return Super::shared->get();
|
||||
}
|
||||
|
||||
void raise() const
|
||||
{
|
||||
return Super::shared->raise();
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
auto then(F &&f)
|
||||
{
|
||||
return Super::shared->then(Super::shared, std::forward<F>(f));
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace
|
||||
|
||||
template<typename T>
|
||||
using Promise = detail::Promise<T>;
|
||||
|
||||
template<typename T>
|
||||
using Future = detail::Future<T>;
|
||||
|
||||
} // namespace
|
||||
|
||||
template<typename T>
|
||||
using Promise = futures::Promise<T>;
|
||||
|
||||
template<typename T>
|
||||
using Future = futures::Future<T>;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||