1#ifndef ORIGINAL_ASYNC_H
2#define ORIGINAL_ASYNC_H
30 template<
typename TYPE>
32 atomic<bool> ready_{makeAtomic(
false)};
36 std::exception_ptr e_{};
45 void setValue(TYPE&& v);
51 void setException(std::exception_ptr e);
57 [[nodiscard]]
bool ready()
const;
83 const TYPE& peek()
const;
94 void rethrowIfException()
const;
100 [[nodiscard]] std::exception_ptr exception()
const;
123 [[nodiscard]]
virtual bool valid() const noexcept = 0;
141 [[nodiscard]] virtual std::exception_ptr
exception() const noexcept = 0;
147 [[nodiscard]] virtual
bool ready() const = 0;
154 template<typename TYPE>
164 template<typename TYPE>
186 [[nodiscard]]
bool valid()
const noexcept override;
205 [[nodiscard]]
bool ready()
const override;
211 [[nodiscard]] std::exception_ptr
exception()
const noexcept override;
216 void wait()
const override;
234 template<
typename TYPE>
254 [[nodiscard]]
bool valid()
const noexcept override;
281 [[nodiscard]]
bool ready()
const override;
287 [[nodiscard]] std::exception_ptr exception()
const noexcept override;
306 void wait()
const override;
319 [[nodiscard]]
u_integer toHash()
const noexcept override;
326 bool equals(
const sharedFuture& other)
const noexcept override;
348 template<
typename TYPE,
typename Callback>
350 std::function<TYPE()> c_{};
395 [[nodiscard]]
bool valid() const noexcept;
407 std::function<TYPE()> function();
433 template <typename Callback, typename... Args>
434 static auto makePromise(Callback&& c, Args&&... args);
444 template <typename Callback, typename... Args>
445 static auto get(Callback&& c, Args&&... args) ->
future<std::invoke_result_t<std::decay_t<Callback>, std::decay_t<Args>...>>;
460 template<typename T, typename Callback>
474 template <typename Callback>
475 auto operator|(
async::
future<
void> f, Callback&& c);
489 template<typename T, typename Callback>
503 template <typename Callback>
526 template<typename T, typename Callback1, typename Callback2>
527 auto operator|(
async::
promise<T, Callback1> p, Callback2&& c);
546 template<typename Callback1, typename Callback2>
547 auto operator|(
async::
promise<
void, Callback1> p, Callback2&& c);
557 atomic<bool> ready_{makeAtomic(
false)};
561 std::exception_ptr e_{};
564 asyncWrapper() =
default;
575 void setException(std::exception_ptr e);
581 [[nodiscard]]
bool ready()
const;
611 void rethrowIfException()
const;
617 [[nodiscard]] std::exception_ptr exception()
const noexcept;
645 [[nodiscard]]
bool valid()
const noexcept override;
663 [[nodiscard]]
bool ready()
const override;
669 [[nodiscard]] std::exception_ptr exception()
const noexcept override;
674 void wait()
const override;
704 [[nodiscard]]
bool valid()
const noexcept override;
716 [[nodiscard]]
bool ready()
const override;
722 [[nodiscard]] std::exception_ptr exception()
const noexcept override;
741 void wait()
const override;
754 [[nodiscard]]
u_integer toHash()
const noexcept override;
761 [[nodiscard]]
bool equals(
const sharedFuture& other)
const noexcept override;
771 template <
typename Callback>
773 std::function<void()> c_{};
796 explicit promise(Callback&& c);
808 [[nodiscard]]
bool valid() const noexcept;
815 std::function<
void()> function();
826template <typename TYPE>
827original::
async::asyncWrapper<TYPE>::asyncWrapper() = default;
829template <typename TYPE>
834 this->result_ = makeStrongPtr<TYPE>(std::move(v));
835 this->ready_.store(
true);
837 this->cond_.notify();
840template <
typename TYPE>
841void original::async::asyncWrapper<TYPE>::setException(std::exception_ptr e)
844 uniqueLock lock{this->mutex_};
845 this->e_ = std::move(e);
846 this->ready_.store(
true);
848 this->cond_.notify();
851template <
typename TYPE>
852bool original::async::asyncWrapper<TYPE>::ready()
const
854 return this->ready_.load();
857template <
typename TYPE>
858void original::async::asyncWrapper<TYPE>::wait()
const
860 uniqueLock lock{this->mutex_};
861 this->cond_.wait(this->mutex_, [
this]
863 return this->ready();
867template <
typename TYPE>
868bool original::async::asyncWrapper<TYPE>::waitFor(time::duration timeout)
const
870 uniqueLock lock{this->mutex_};
871 return this->cond_.waitFor(this->mutex_, timeout, [
this]
873 return this->ready();
877template <
typename TYPE>
878TYPE original::async::asyncWrapper<TYPE>::get()
880 uniqueLock lock{this->mutex_};
881 this->rethrowIfException();
883 TYPE result = std::move(*this->result_);
884 this->result_.reset();
887 this->cond_.wait(this->mutex_, [
this]{
888 return this->ready();
891 this->rethrowIfException();
893 TYPE result = std::move(*this->result_);
894 this->result_.reset();
898template <
typename TYPE>
899const TYPE& original::async::asyncWrapper<TYPE>::peek()
const
901 uniqueLock lock{this->mutex_};
902 this->rethrowIfException();
904 return *this->result_;
906 this->cond_.wait(this->mutex_, [
this]{
907 return this->ready();
910 this->rethrowIfException();
911 return *this->result_;
914template <
typename TYPE>
917 this->rethrowIfException();
918 return this->result_;
921template <
typename TYPE>
922void original::async::asyncWrapper<TYPE>::rethrowIfException()
const
925 std::rethrow_exception(this->e_);
928template <
typename TYPE>
930original::async::asyncWrapper<TYPE>::exception()
const
932 uniqueLock lock{this->mutex_};
936template <
typename TYPE>
938 : awr_(std::move(awr)) {}
940template <
typename TYPE>
943 return this->awr_ !=
nullptr;
946template <
typename TYPE>
953template <
typename TYPE>
956 if (!this->valid()) {
957 throw sysError(
"Access an invalid future");
959 return this->awr_->get();
962template <
typename TYPE>
965 if (!this->valid()) {
966 throw sysError(
"Access an invalid future");
968 return this->awr_->ready();
971template <
typename TYPE>
974 if (!this->valid()) {
977 return this->awr_->exception();
980template <
typename TYPE>
983 if (!this->valid()) {
984 throw sysError(
"Access an invalid future");
989template <
typename TYPE>
992 if (!this->valid()) {
993 throw sysError(
"Access an invalid future");
995 return this->awr_->waitFor(timeout);
998template <
typename TYPE>
1000 : awr_(std::move(awr)) {}
1002template <
typename TYPE>
1005 return this->awr_ !=
nullptr;
1008template <
typename TYPE>
1011 if (!this->valid()) {
1012 throw sysError(
"Access an invalid sharedFuture");
1014 return this->awr_->peek();
1017template <
typename TYPE>
1020 if (!this->valid()) {
1021 throw sysError(
"Access an invalid sharedFuture");
1023 if (!this->ready()) {
1024 throw sysError(
"Cannot get a strongPtr from a sharedFuture that is not ready");
1026 return this->awr_->getPtr().template constCastTo<const TYPE>();
1029template <
typename TYPE>
1032 if (!this->valid()) {
1033 throw sysError(
"Access an invalid sharedFuture");
1035 return this->awr_->ready();
1038template <
typename TYPE>
1041 if (!this->valid()) {
1044 return this->awr_->exception();
1047template <
typename TYPE>
1050 return this->awr_ == other.awr_;
1053template <
typename TYPE>
1056 return this->awr_ != other.awr_;
1059template <
typename TYPE>
1062 if (!this->valid()) {
1063 throw sysError(
"Access an invalid sharedFuture");
1068template <
typename TYPE>
1071 if (!this->valid()) {
1072 throw sysError(
"Access an invalid sharedFuture");
1074 return this->awr_->waitFor(timeout);
1077template <
typename TYPE>
1080 return this->awr_.toHash();
1083template <
typename TYPE>
1086 return *
this == other;
1089template <
typename TYPE,
typename Callback>
1092 if (!other.valid()){
1095 this->valid_ =
true;
1096 this->c_ = std::move(other.c_);
1097 this->awr_ = std::move(other.awr_);
1098 other.valid_ =
false;
1101template <
typename TYPE,
typename Callback>
1105 if (
this == &other || !other.valid()) {
1108 this->valid_ =
true;
1109 this->c_ = std::move(other.c_);
1110 this->awr_ = std::move(other.awr_);
1111 other.valid_ =
false;
1115template <
typename TYPE,
typename Callback>
1117 : c_(std::forward<Callback>(c)), awr_(
makeStrongPtr<asyncWrapper<TYPE>>()), valid_(true) {}
1119template <
typename TYPE,
typename Callback>
1126template <
typename TYPE,
typename Callback>
1129 return this->valid_;
1132template <
typename TYPE,
typename Callback>
1135 if (!this->valid_) {
1136 throw sysError(
"Try to get an invalid task");
1138 this->valid_ =
false;
1139 return std::move(this->c_);
1142template <
typename TYPE,
typename Callback>
1145 if (!this->valid_) {
1146 throw sysError(
"Try to run an invalid task");
1149 this->awr_->setValue(this->c_());
1151 this->awr_->setException(std::current_exception());
1153 this->valid_ =
false;
1156template <
typename Callback,
typename... Args>
1158 using Return = std::invoke_result_t<Callback, Args...>;
1159 auto bound = [c = std::forward<Callback>(c),
1160 ... args = std::forward<Args>(args)]()
mutable -> Return {
1164 return promise<Return,
decltype(bound)>{std::move(bound)};
1167template <
typename Callback,
typename ... Args>
1171 auto p =
makePromise(std::forward<Callback>(c), std::forward<Args>(args)...);
1172 auto fut = p.getFuture();
1174 auto p_shared = makeStrongPtr<decltype(p)>(std::move(p));
1176 [p_shared]()
mutable {
1185template <
typename T,
typename Callback>
1188 using ResultType = std::invoke_result_t<Callback, T>;
1190 return async::get([shared_f, c = std::forward<Callback>(c)]
mutable -> ResultType {
1191 if constexpr (!std::is_void_v<ResultType>) {
1192 return c(shared_f->result());
1200template <
typename Callback>
1203 using ResultType = std::invoke_result_t<Callback>;
1205 return async::get([shared_f, c = std::forward<Callback>(c)]()
mutable -> ResultType {
1211template <
typename T,
typename Callback>
1214 using ResultType = std::invoke_result_t<Callback, T>;
1215 return async::get([sf, c = std::forward<Callback>(c)]
mutable -> ResultType {
1216 if constexpr (!std::is_void_v<ResultType>) {
1225template <
typename Callback>
1228 using ResultType = std::invoke_result_t<Callback>;
1229 return async::get([sf, c = std::forward<Callback>(c)]()
mutable -> ResultType {
1235template <
typename T,
typename Callback1,
typename Callback2>
1239 throw sysError(
"Try to build a lazy pipeline from an invalid promise");
1241 using ResultType =
decltype(c(std::declval<T>()));
1243 return async::makePromise([shared_p, c = std::forward<Callback2>(c)]()
mutable -> ResultType {
1244 if constexpr (!std::is_void_v<ResultType>) {
1245 return c(shared_p->function()());
1247 shared_p->function()();
1253template <
typename Callback1,
typename Callback2>
1257 throw sysError(
"Try to build a lazy pipeline from an invalid promise");
1259 using ResultType =
decltype(c());
1261 return async::makePromise([shared_p, c = std::forward<Callback2>(c)]()
mutable -> ResultType {
1262 shared_p->function()();
1267inline void original::async::asyncWrapper<void>::setValue()
1271 this->result_.set();
1272 this->ready_.store(
true);
1274 this->cond_.notify();
1277inline void original::async::asyncWrapper<void>::setException(std::exception_ptr e)
1281 this->e_ = std::move(e);
1282 this->ready_.store(
true);
1284 this->cond_.notify();
1287inline bool original::async::asyncWrapper<void>::ready()
const
1289 return this->ready_.load();
1292inline void original::async::asyncWrapper<void>::wait()
const
1295 this->cond_.wait(this->mutex_, [
this]
1297 return this->ready();
1301inline bool original::async::asyncWrapper<void>::waitFor(
time::duration timeout)
const
1304 return this->cond_.waitFor(this->mutex_, std::move(timeout), [
this]
1306 return this->ready();
1310inline void original::async::asyncWrapper<void>::get()
1313 this->rethrowIfException();
1314 if (this->result_) {
1315 this->result_.reset();
1318 this->cond_.wait(this->mutex_, [
this] {
1319 return this->ready();
1322 this->rethrowIfException();
1323 this->result_.reset();
1326inline void original::async::asyncWrapper<void>::peek()
const
1329 this->rethrowIfException();
1330 if (this->result_) {
1333 this->cond_.wait(this->mutex_, [
this] {
1334 return this->ready();
1337 this->rethrowIfException();
1340inline void original::async::asyncWrapper<void>::rethrowIfException()
const
1343 std::rethrow_exception(this->e_);
1346inline std::exception_ptr
1347original::async::asyncWrapper<void>::exception() const noexcept
1354 : awr_(std::move(awr)) {}
1358 return this->awr_ !=
nullptr;
1368 if (!this->valid()) {
1369 throw sysError(
"Access an invalid future");
1376 if (!this->valid()) {
1377 throw sysError(
"Access an invalid future");
1379 return this->awr_->ready();
1384 if (!this->valid()) {
1387 return this->awr_->exception();
1392 if (!this->valid()) {
1393 throw sysError(
"Access an invalid future");
1400 if (!this->valid()) {
1401 throw sysError(
"Access an invalid future");
1403 return this->awr_->waitFor(timeout);
1407 : awr_(std::move(awr)) {}
1411 return this->awr_ !=
nullptr;
1416 if (!this->valid()) {
1417 throw sysError(
"Access an invalid sharedFuture");
1424 if (!this->valid()) {
1425 throw sysError(
"Access an invalid sharedFuture");
1427 return this->awr_->ready();
1432 if (!this->valid()) {
1435 return this->awr_->exception();
1440 return this->awr_ == other.awr_;
1445 return this->awr_ != other.awr_;
1451 if (!this->valid()) {
1452 throw sysError(
"Access an invalid sharedFuture");
1459 if (!this->valid()) {
1460 throw sysError(
"Access an invalid sharedFuture");
1462 return this->awr_->waitFor(timeout);
1467 return this->awr_.toHash();
1472 return *
this == other;
1475template <
typename Callback>
1478 if (!other.valid()){
1481 this->valid_ =
true;
1482 this->c_ = std::move(other.c_);
1483 this->awr_ = std::move(other.awr_);
1484 other.valid_ =
false;
1487template <
typename Callback>
1490 if (
this == &other || !other.valid()) {
1493 this->valid_ =
true;
1494 this->c_ = std::move(other.c_);
1495 this->awr_ = std::move(other.awr_);
1496 other.valid_ =
false;
1500template <
typename Callback>
1502 : c_(std::forward<Callback>(c)), awr_(
makeStrongPtr<asyncWrapper<void>>()), valid_(true) {}
1504template <
typename Callback>
1510template <
typename Callback>
1513 return this->valid_;
1516template <
typename Callback>
1519 if (!this->valid_) {
1520 throw sysError(
"Try to get an invalid task");
1522 this->valid_ =
false;
1523 return std::move(this->c_);
1526template <
typename Callback>
1529 if (!this->valid_) {
1530 throw sysError(
"Try to run an invalid task");
1534 this->awr_->setValue();
1536 this->awr_->setException(std::current_exception());
1538 this->valid_ =
false;
A type-safe container that may or may not contain a value.
Definition optional.h:45
Abstract base interface for asynchronous consumers.
Definition async.h:117
virtual bool waitFor(time::duration timeout) const =0
Waits for the result with a timeout.
virtual void wait() const =0
Waits until the result becomes ready.
virtual bool ready() const =0
Checks if the result is ready.
virtual std::exception_ptr exception() const noexcept=0
Gets the stored exception if computation failed.
virtual bool valid() const noexcept=0
Checks if the future is valid (has an associated async wrapper)
Represents a one-shot future result of an asynchronous computation.
Definition async.h:165
bool ready() const override
Checks if the result is ready.
Definition async.h:963
std::exception_ptr exception() const noexcept override
Gets the exception if computation failed.
Definition async.h:972
sharedFuture< TYPE > share()
Converts this future to a shared future.
Definition async.h:947
bool valid() const noexcept override
Checks if the future is valid (has an associated async wrapper)
Definition async.h:941
TYPE result()
Gets the result (blocks until ready)
Definition async.h:954
bool waitFor(time::duration timeout) const override
Waits for the result with a timeout.
Definition async.h:990
void wait() const override
Waits until the result becomes ready.
Definition async.h:981
promise()=default
Default constructor creates an invalid promise.
Represents a one-time asynchronous producer with result setting capability.
Definition async.h:349
promise()=default
Default constructor creates an invalid promise.
bool valid() const noexcept
Checks if the promise is still valid (can be executed or have function extracted)
Definition async.h:1127
std::function< TYPE()> function()
Extracts the computation function from the promise.
Definition async.h:1133
promise(Callback &&c)
Constructs a promise with a computation callback.
Definition async.h:1116
future< TYPE > getFuture()
Gets the future associated with this promise.
Definition async.h:1121
void run()
Executes the computation and sets the result in the associated future.
Definition async.h:1143
Represents a sharable asynchronous result.
Definition async.h:235
bool valid() const noexcept override
Checks if the shared future is valid (has an associated async wrapper)
Definition async.h:1003
TYPE result() const
Gets the result value (blocks until ready)
Definition async.h:1009
u_integer toHash() const noexcept override
Generates a hash value for the shared future.
Definition async.h:1078
std::exception_ptr exception() const noexcept override
Gets the exception if computation failed.
Definition async.h:1039
bool equals(const sharedFuture &other) const noexcept override
Checks if two shared futures are equal.
Definition async.h:1084
void wait() const override
Waits until the result becomes ready.
Definition async.h:1060
strongPtr< const TYPE > strongPointer() const
Gets a strong pointer to the result value.
Definition async.h:1018
bool ready() const override
Checks if the result is ready.
Definition async.h:1030
bool waitFor(time::duration timeout) const override
Waits for the result with a timeout.
Definition async.h:1069
bool operator!=(const sharedFuture &other) const noexcept
Inequality comparison operator.
Definition async.h:1054
bool operator==(const sharedFuture &other) const noexcept
Equality comparison operator.
Definition async.h:1048
Asynchronous programming utilities with future/promise pattern.
Definition async.h:21
static auto get(Callback &&c, Args &&... args) -> future< std::invoke_result_t< std::decay_t< Callback >, std::decay_t< Args >... > >
Executes a callable asynchronously and returns a future for the result.
Definition async.h:1168
static auto makePromise(Callback &&c, Args &&... args)
Creates a promise from a callable and arguments.
Definition async.h:1157
Forward declaration of hashable interface template.
Definition hash.h:206
POSIX condition variable implementation.
Definition condition.h:114
POSIX thread mutex implementation.
Definition mutex.h:153
Shared ownership smart pointer with strong references.
Definition refCntPtr.h:108
Exception for generic system failure.
Definition error.h:306
High-level thread wrapper.
Definition thread.h:263
static constexpr auto AUTO_DETACH
Alias for joinPolicy::AUTO_DETACH.
Definition thread.h:305
Represents a time duration with nanosecond precision.
Definition zeit.h:134
Namespace-like class containing time-related utilities.
Definition zeit.h:40
RAII wrapper for single mutex locking.
Definition mutex.h:216
Condition variable implementation for thread synchronization.
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:263
Main namespace for the project Original.
Definition algorithms.h:21
bool operator!=(const autoPtr< T, DER, DEL > &ptr, const std::nullptr_t &null)
Inequality comparison with nullptr.
Definition autoPtr.h:666
bool operator==(const autoPtr< T, DER, DEL > &ptr, const std::nullptr_t &null)
Equality comparison with nullptr.
Definition autoPtr.h:661
strongPtr< T, DEL > makeStrongPtr(Args &&... args)
Creates a new strongPtr managing a shared object.
Definition refCntPtr.h:633
bitSet< ALLOC_ > operator|(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Type-safe optional value container.
Reference-counted smart pointer hierarchy.
Thread management utilities.