1#ifndef ORIGINAL_ASYNC_H
2#define ORIGINAL_ASYNC_H
30 template<
typename TYPE>
35 mutable mutex mutex_{};
36 std::exception_ptr e_{};
45 void setValue(
TYPE&&
v);
51 void setException(
const std::exception_ptr&
e);
83 const TYPE& peek()
const;
94 void rethrowIfException()
const;
100 [[
nodiscard]] std::exception_ptr exception()
const;
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;
348 template<
typename TYPE,
typename Callback>
350 std::function<
TYPE()> c_{};
560 mutable mutex mutex_{};
561 std::exception_ptr e_{};
564 asyncWrapper() =
default;
575 void setException(
const std::exception_ptr&
e);
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;
771 template <
typename Callback>
773 std::function<
void()> c_{};
815 std::function<
void()> function();
835 this->ready_.store(
true);
837 this->cond_.notifyAll();
840template <
typename TYPE>
841void original::async::asyncWrapper<TYPE>::setException(
const std::exception_ptr &e)
844 uniqueLock lock{this->mutex_};
846 this->ready_.store(
true);
848 this->cond_.notifyAll();
851template <
typename TYPE>
852bool original::async::asyncWrapper<TYPE>::ready()
const
854 return *this->ready_;
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->cond_.wait(this->mutex_, [
this]{
882 return this->ready();
885 this->rethrowIfException();
887 TYPE result = std::move(*this->result_);
888 this->result_.reset();
892template <
typename TYPE>
893const TYPE& original::async::asyncWrapper<TYPE>::peek()
const
895 uniqueLock lock{this->mutex_};
896 this->cond_.wait(this->mutex_, [
this]{
897 return this->ready();
900 this->rethrowIfException();
901 return *this->result_;
904template <
typename TYPE>
907 this->rethrowIfException();
908 return this->result_;
911template <
typename TYPE>
912void original::async::asyncWrapper<TYPE>::rethrowIfException()
const
915 std::rethrow_exception(this->e_);
918template <
typename TYPE>
920original::async::asyncWrapper<TYPE>::exception()
const
922 uniqueLock lock{this->mutex_};
926template <
typename TYPE>
928 : awr_(
std::move(awr)) {}
930template <
typename TYPE>
933 return this->awr_ !=
nullptr;
936template <
typename TYPE>
943template <
typename TYPE>
946 if (!this->valid()) {
947 throw sysError(
"Access an invalid future");
949 return this->awr_->get();
952template <
typename TYPE>
955 if (!this->valid()) {
956 throw sysError(
"Access an invalid future");
958 return this->awr_->ready();
961template <
typename TYPE>
964 if (!this->valid()) {
967 return this->awr_->exception();
970template <
typename TYPE>
973 if (!this->valid()) {
974 throw sysError(
"Access an invalid future");
979template <
typename TYPE>
982 if (!this->valid()) {
983 throw sysError(
"Access an invalid future");
985 return this->awr_->waitFor(
timeout);
988template <
typename TYPE>
992template <
typename TYPE>
995 return this->awr_ !=
nullptr;
998template <
typename TYPE>
1001 if (!this->valid()) {
1002 throw sysError(
"Access an invalid sharedFuture");
1004 return this->awr_->peek();
1007template <
typename TYPE>
1010 if (!this->valid()) {
1011 throw sysError(
"Access an invalid sharedFuture");
1013 if (!this->ready()) {
1014 throw sysError(
"Cannot get a strongPtr from a sharedFuture that is not ready");
1019template <
typename TYPE>
1022 if (!this->valid()) {
1023 throw sysError(
"Access an invalid sharedFuture");
1025 return this->awr_->ready();
1028template <
typename TYPE>
1031 if (!this->valid()) {
1034 return this->awr_->exception();
1037template <
typename TYPE>
1040 return this->awr_ ==
other.awr_;
1043template <
typename TYPE>
1046 return this->awr_ !=
other.awr_;
1049template <
typename TYPE>
1052 if (!this->valid()) {
1053 throw sysError(
"Access an invalid sharedFuture");
1058template <
typename TYPE>
1061 if (!this->valid()) {
1062 throw sysError(
"Access an invalid sharedFuture");
1064 return this->awr_->waitFor(
timeout);
1067template <
typename TYPE>
1070 return this->awr_.
toHash();
1073template <
typename TYPE>
1076 return *
this ==
other;
1079template <
typename TYPE,
typename Callback>
1082 if (!
other.valid()){
1085 this->valid_ =
true;
1086 this->c_ = std::move(
other.c_);
1087 this->awr_ = std::move(
other.awr_);
1088 other.valid_ =
false;
1091template <
typename TYPE,
typename Callback>
1095 if (
this == &other || !other.valid()) {
1098 this->valid_ =
true;
1099 this->c_ = std::move(other.c_);
1100 this->awr_ = std::move(other.awr_);
1101 other.valid_ =
false;
1105template <
typename TYPE,
typename Callback>
1109template <
typename TYPE,
typename Callback>
1116template <
typename TYPE,
typename Callback>
1119 return this->valid_;
1122template <
typename TYPE,
typename Callback>
1125 if (!this->valid_) {
1126 throw sysError(
"Try to get an invalid task");
1128 this->valid_ =
false;
1129 return std::move(this->c_);
1132template <
typename TYPE,
typename Callback>
1135 if (!this->valid_) {
1136 throw sysError(
"Try to run an invalid task");
1139 this->awr_->setValue(this->c_());
1141 this->awr_->setException(std::current_exception());
1143 this->valid_ =
false;
1149 auto bound = [c = std::forward<Callback>(c),
1161 auto p =
makePromise(std::forward<Callback>(c), std::forward<Args>(
args)...);
1162 auto fut = p.getFuture();
1175template <
typename T,
typename Callback>
1178 using ResultType = std::invoke_result_t<Callback, T>;
1185template <
typename Callback>
1188 using ResultType = std::invoke_result_t<Callback>;
1196template <
typename T,
typename Callback>
1199 using ResultType = std::invoke_result_t<Callback, T>;
1201 return c(
sf.result());
1205template <
typename Callback>
1208 using ResultType = std::invoke_result_t<Callback>;
1215template <
typename T,
typename Callback1,
typename Callback2>
1219 throw sysError(
"Try to build a lazy pipeline from an invalid promise");
1221 using ResultType =
decltype(c(std::declval<T>()));
1228template <
typename Callback1,
typename Callback2>
1232 throw sysError(
"Try to build a lazy pipeline from an invalid promise");
1242inline void original::async::asyncWrapper<void>::setValue()
1246 this->result_.set();
1247 this->ready_.store(
true);
1249 this->cond_.notifyAll();
1252inline void original::async::asyncWrapper<void>::setException(
const std::exception_ptr&
e)
1257 this->ready_.store(
true);
1259 this->cond_.notifyAll();
1262inline bool original::async::asyncWrapper<void>::ready()
const
1264 return *this->ready_;
1267inline void original::async::asyncWrapper<void>::wait()
const
1270 this->cond_.wait(this->mutex_, [
this]
1272 return this->ready();
1279 return this->cond_.waitFor(this->mutex_,
timeout, [
this]
1281 return this->ready();
1285inline void original::async::asyncWrapper<void>::get()
1288 this->cond_.wait(this->mutex_, [
this] {
1289 return this->ready();
1292 this->rethrowIfException();
1293 this->result_.reset();
1296inline void original::async::asyncWrapper<void>::peek()
const
1299 this->cond_.wait(this->mutex_, [
this] {
1300 return this->ready();
1303 this->rethrowIfException();
1306inline void original::async::asyncWrapper<void>::rethrowIfException()
const
1309 std::rethrow_exception(this->e_);
1312inline std::exception_ptr
1324 return this->awr_ !=
nullptr;
1334 if (!this->valid()) {
1335 throw sysError(
"Access an invalid future");
1342 if (!this->valid()) {
1343 throw sysError(
"Access an invalid future");
1345 return this->awr_->ready();
1350 if (!this->valid()) {
1353 return this->awr_->exception();
1358 if (!this->valid()) {
1359 throw sysError(
"Access an invalid future");
1366 if (!this->valid()) {
1367 throw sysError(
"Access an invalid future");
1369 return this->awr_->waitFor(
timeout);
1377 return this->awr_ !=
nullptr;
1382 if (!this->valid()) {
1383 throw sysError(
"Access an invalid sharedFuture");
1390 if (!this->valid()) {
1391 throw sysError(
"Access an invalid sharedFuture");
1393 return this->awr_->ready();
1398 if (!this->valid()) {
1401 return this->awr_->exception();
1406 return this->awr_ ==
other.awr_;
1411 return this->awr_ !=
other.awr_;
1417 if (!this->valid()) {
1418 throw sysError(
"Access an invalid sharedFuture");
1425 if (!this->valid()) {
1426 throw sysError(
"Access an invalid sharedFuture");
1428 return this->awr_->waitFor(
timeout);
1433 return this->awr_.
toHash();
1438 return *
this ==
other;
1441template <
typename Callback>
1444 if (!
other.valid()){
1447 this->valid_ =
true;
1448 this->c_ = std::move(
other.c_);
1449 this->awr_ = std::move(
other.awr_);
1450 other.valid_ =
false;
1453template <
typename Callback>
1456 if (
this == &other || !other.valid()) {
1459 this->valid_ =
true;
1460 this->c_ = std::move(other.c_);
1461 this->awr_ = std::move(other.awr_);
1462 other.valid_ =
false;
1466template <
typename Callback>
1470template <
typename Callback>
1476template <
typename Callback>
1479 return this->valid_;
1482template <
typename Callback>
1485 if (!this->valid_) {
1486 throw sysError(
"Try to get an invalid task");
1488 this->valid_ =
false;
1489 return std::move(this->c_);
1492template <
typename Callback>
1495 if (!this->valid_) {
1496 throw sysError(
"Try to run an invalid task");
1500 this->awr_->setValue();
1502 this->awr_->setException(std::current_exception());
1504 this->valid_ =
false;
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:953
std::exception_ptr exception() const noexcept override
Gets the exception if computation failed.
Definition async.h:962
sharedFuture< TYPE > share()
Converts this future to a shared future.
Definition async.h:937
bool valid() const noexcept override
Checks if the future is valid (has an associated async wrapper)
Definition async.h:931
TYPE result()
Gets the result (blocks until ready)
Definition async.h:944
bool waitFor(time::duration timeout) const override
Waits for the result with a timeout.
Definition async.h:980
void wait() const override
Waits until the result becomes ready.
Definition async.h:971
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:1117
std::function< TYPE()> function()
Extracts the computation function from the promise.
Definition async.h:1123
promise(Callback &&c)
Constructs a promise with a computation callback.
Definition async.h:1106
future< TYPE > getFuture()
Gets the future associated with this promise.
Definition async.h:1111
void run()
Executes the computation and sets the result in the associated future.
Definition async.h:1133
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:993
TYPE result() const
Gets the result value (blocks until ready)
Definition async.h:999
u_integer toHash() const noexcept override
Generates a hash value for the shared future.
Definition async.h:1068
std::exception_ptr exception() const noexcept override
Gets the exception if computation failed.
Definition async.h:1029
bool equals(const sharedFuture &other) const noexcept override
Checks if two shared futures are equal.
Definition async.h:1074
void wait() const override
Waits until the result becomes ready.
Definition async.h:1050
strongPtr< const TYPE > strongPointer() const
Gets a strong pointer to the result value.
Definition async.h:1008
bool ready() const override
Checks if the result is ready.
Definition async.h:1020
bool waitFor(time::duration timeout) const override
Waits for the result with a timeout.
Definition async.h:1059
bool operator!=(const sharedFuture &other) const noexcept
Inequality comparison operator.
Definition async.h:1044
bool operator==(const sharedFuture &other) const noexcept
Equality comparison operator.
Definition async.h:1038
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:1158
static auto makePromise(Callback &&c, Args &&... args)
Creates a promise from a callable and arguments.
Definition async.h:1147
u_integer toHash() const noexcept override
Compute hash value for the pointer.
Definition autoPtr.h:735
Definition condition.h:209
Forward declaration of hashable interface template.
Definition hash.h:220
Unique ownership smart pointer with move semantics.
Definition ownerPtr.h:37
Shared ownership smart pointer with strong references.
Definition refCntPtr.h:108
Exception for generic system failure.
Definition error.h:413
High-level thread wrapper.
Definition thread.h:307
static constexpr auto AUTO_DETACH
Alias for joinPolicy::AUTO_DETACH.
Definition thread.h:353
Represents a time duration with nanosecond precision.
Definition zeit.h:143
Namespace-like class containing time-related utilities.
Definition zeit.h:49
RAII wrapper for single mutex locking.
Definition mutex.h:280
Condition variable implementation for thread synchronization.
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:755
bool operator==(const autoPtr< T, DER, DEL > &ptr, const std::nullptr_t &null)
Equality comparison with nullptr.
Definition autoPtr.h:750
auto makeAtomic()
Creates a default-constructed atomic object.
Definition atomic.h:867
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)
Bitwise OR operator for two bitSets.
Standard namespace extensions for original::alternative.
Definition allocator.h:351
Type-safe optional value container.
Reference-counted smart pointer hierarchy.
Thread management utilities.