ORIGINAL
Loading...
Searching...
No Matches
async.h
1#ifndef ORIGINAL_ASYNC_H
2#define ORIGINAL_ASYNC_H
3
4#include "atomic.h"
5#include "condition.h"
6#include "optional.h"
7#include "refCntPtr.h"
8#include "thread.h"
9#include <exception>
10#include <functional>
11#include <utility>
12
13namespace original {
14
21 class async {
22 // ==================== Async Wrapper (Internal) ====================
23
30 template<typename TYPE>
31 class asyncWrapper {
32 atomic<bool> ready_{makeAtomic(false)};
33 strongPtr<TYPE> result_;
34 mutable pCondition cond_{};
35 mutable pMutex mutex_{};
36 std::exception_ptr e_{};
37
38 public:
39 asyncWrapper();
40
45 void setValue(TYPE&& v);
46
51 void setException(std::exception_ptr e);
52
57 [[nodiscard]] bool ready() const;
58
62 void wait() const;
63
69 bool waitFor(time::duration timeout) const;
70
76 TYPE get();
77
83 const TYPE& peek() const;
84
89 strongPtr<TYPE> getPtr() const;
90
94 void rethrowIfException() const;
95
100 [[nodiscard]] std::exception_ptr exception() const;
101 };
102
103 public:
118 public:
123 [[nodiscard]] virtual bool valid() const noexcept = 0;
124
128 virtual void wait() const = 0;
129
135 virtual bool waitFor(time::duration timeout) const = 0;
136
141 [[nodiscard]] virtual std::exception_ptr exception() const noexcept = 0;
142
147 [[nodiscard]] virtual bool ready() const = 0;
148
149 virtual ~futureBase() = default;
150 };
151
152 // ==================== Future Class ====================
153
154 template<typename TYPE>
155 class sharedFuture;
156
164 template<typename TYPE>
165 class future final : public futureBase {
167
168 friend class async;
169 explicit future(strongPtr<asyncWrapper<TYPE>> awr);
170
171 public:
172 future() = default;
173
174 // Disable copying
175 future(const future&) = delete;
176 future& operator=(const future&) = delete;
177
178 // Allow moving
179 future(future&&) = default;
180 future& operator=(future&&) = default;
181
186 [[nodiscard]] bool valid() const noexcept override;
187
192 sharedFuture<TYPE> share();
193
199 TYPE result();
200
205 [[nodiscard]] bool ready() const override;
206
211 [[nodiscard]] std::exception_ptr exception() const noexcept override;
212
216 void wait() const override;
217
223 bool waitFor(time::duration timeout) const override;
224 };
225
234 template<typename TYPE>
235 class sharedFuture final : public futureBase, public hashable<sharedFuture<TYPE>> {
237
238 friend class async;
239 explicit sharedFuture(strongPtr<asyncWrapper<TYPE>> awr);
240
241 public:
242 sharedFuture() = default;
243
244 // Allow copying and moving
245 sharedFuture(const sharedFuture&) = default;
246 sharedFuture& operator=(const sharedFuture&) = default;
247 sharedFuture(sharedFuture&&) = default;
248 sharedFuture& operator=(sharedFuture&&) = default;
249
254 [[nodiscard]] bool valid() const noexcept override;
255
261 TYPE result() const;
262
275 strongPtr<const TYPE> strongPointer() const;
276
281 [[nodiscard]] bool ready() const override;
282
287 [[nodiscard]] std::exception_ptr exception() const noexcept override;
288
294 bool operator==(const sharedFuture& other) const noexcept;
295
301 bool operator!=(const sharedFuture& other) const noexcept;
302
306 void wait() const override;
307
313 bool waitFor(time::duration timeout) const override;
314
319 [[nodiscard]] u_integer toHash() const noexcept override;
320
326 bool equals(const sharedFuture& other) const noexcept override;
327
328 ~sharedFuture() override = default;
329 };
330
331 // ==================== Promise Class ====================
332
348 template<typename TYPE, typename Callback>
349 class promise {
350 std::function<TYPE()> c_{};
352 bool valid_{false};
353
354 public:
355 // Disable copying to prevent multiple executions of the same computation
356 promise(const promise&) = delete;
357 promise& operator=(const promise&) = delete;
358
359 // Allow moving to transfer ownership of the computation
360 promise(promise&& other) noexcept;
361
362 promise& operator=(promise&& other) noexcept;
363
369 promise() = default;
370
377 explicit promise(Callback&& c);
378
386
395 [[nodiscard]] bool valid() const noexcept;
396
407 std::function<TYPE()> function();
408
418 void run();
419 };
420
421 // ==================== Static Factory Methods ====================
422
433 template <typename Callback, typename... Args>
434 static auto makePromise(Callback&& c, Args&&... args);
435
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>...>>;
446 };
447
460 template<typename T, typename Callback>
461 auto operator|(async::future<T> f, Callback&& c);
462
474 template <typename Callback>
475 auto operator|(async::future<void> f, Callback&& c);
476
489 template<typename T, typename Callback>
490 auto operator|(async::sharedFuture<T> sf, Callback&& c);
491
503 template <typename Callback>
504 auto operator|(async::sharedFuture<void> sf, Callback&& c);
505
526 template<typename T, typename Callback1, typename Callback2>
527 auto operator|(async::promise<T, Callback1> p, Callback2&& c);
528
546 template<typename Callback1, typename Callback2>
547 auto operator|(async::promise<void, Callback1> p, Callback2&& c);
548
549
550 // ==================== Void Specializations ====================
551
555 template <>
556 class async::asyncWrapper<void> {
557 atomic<bool> ready_{makeAtomic(false)};
558 alternative<void> result_;
559 mutable pCondition cond_{};
560 mutable pMutex mutex_{};
561 std::exception_ptr e_{};
562
563 public:
564 asyncWrapper() = default;
565
569 void setValue();
570
575 void setException(std::exception_ptr e);
576
581 [[nodiscard]] bool ready() const;
582
586 void wait() const;
587
593 bool waitFor(time::duration timeout) const;
594
599 void get();
600
605 void peek() const;
606
611 void rethrowIfException() const;
612
617 [[nodiscard]] std::exception_ptr exception() const noexcept;
618 };
619
623 template <>
624 class async::future<void> final : public futureBase {
626
627 friend class async;
628 explicit future(strongPtr<asyncWrapper<void>> awr);
629
630 public:
631 future() = default;
632
633 // Disable copying
634 future(const future&) = delete;
635 future& operator=(const future&) = delete;
636
637 // Allow moving
638 future(future&&) = default;
639 future& operator=(future&&) = default;
640
645 [[nodiscard]] bool valid() const noexcept override;
646
651 sharedFuture<void> share();
652
657 void result();
658
663 [[nodiscard]] bool ready() const override;
664
669 [[nodiscard]] std::exception_ptr exception() const noexcept override;
670
674 void wait() const override;
675
681 bool waitFor(time::duration timeout) const override;
682 };
683
684 template <>
685 class async::sharedFuture<void> final : public futureBase, public hashable<sharedFuture<void>> {
687
688 friend class async;
689 explicit sharedFuture(strongPtr<asyncWrapper<void>> awr);
690
691 public:
692 sharedFuture() = default;
693
694 // Allow copying and moving
695 sharedFuture(const sharedFuture&) = default;
696 sharedFuture& operator=(const sharedFuture&) = default;
697 sharedFuture(sharedFuture&&) = default;
698 sharedFuture& operator=(sharedFuture&&) = default;
699
704 [[nodiscard]] bool valid() const noexcept override;
705
710 void result() const;
711
716 [[nodiscard]] bool ready() const override;
717
722 [[nodiscard]] std::exception_ptr exception() const noexcept override;
723
729 bool operator==(const sharedFuture& other) const noexcept;
730
736 bool operator!=(const sharedFuture& other) const noexcept;
737
741 void wait() const override;
742
748 bool waitFor(time::duration timeout) const override;
749
754 [[nodiscard]] u_integer toHash() const noexcept override;
755
761 [[nodiscard]] bool equals(const sharedFuture& other) const noexcept override;
762
763 ~sharedFuture() override = default;
764 };
765
771 template <typename Callback>
772 class async::promise<void, Callback> {
773 std::function<void()> c_{};
775 bool valid_{false};
776
777 public:
778 // Disable copying to prevent multiple executions of the same computation
779 promise(const promise&) = delete;
780 promise& operator=(const promise&) = delete;
781
782 // Allow moving to transfer ownership of the computation
783 promise(promise&& other) noexcept;
784
785 promise& operator=(promise&& other) noexcept;
786
790 promise() = default;
791
796 explicit promise(Callback&& c);
797
802 [[nodiscard]] future<void> getFuture() const;
803
808 [[nodiscard]] bool valid() const noexcept;
809
815 std::function<void()> function();
816
822 void run();
823 };
824} // namespace original
825
826template <typename TYPE>
827original::async::asyncWrapper<TYPE>::asyncWrapper() = default;
828
829template <typename TYPE>
830void original::async::asyncWrapper<TYPE>::setValue(TYPE&& v)
831{
832 {
833 uniqueLock lock{this->mutex_};
834 this->result_ = makeStrongPtr<TYPE>(std::move(v));
835 this->ready_.store(true);
836 }
837 this->cond_.notify();
838}
839
840template <typename TYPE>
841void original::async::asyncWrapper<TYPE>::setException(std::exception_ptr e)
842{
843 {
844 uniqueLock lock{this->mutex_};
845 this->e_ = std::move(e);
846 this->ready_.store(true);
847 }
848 this->cond_.notify();
849}
850
851template <typename TYPE>
852bool original::async::asyncWrapper<TYPE>::ready() const
853{
854 return this->ready_.load();
855}
856
857template <typename TYPE>
858void original::async::asyncWrapper<TYPE>::wait() const
859{
860 uniqueLock lock{this->mutex_};
861 this->cond_.wait(this->mutex_, [this]
862 {
863 return this->ready();
864 });
865}
866
867template <typename TYPE>
868bool original::async::asyncWrapper<TYPE>::waitFor(time::duration timeout) const
869{
870 uniqueLock lock{this->mutex_};
871 return this->cond_.waitFor(this->mutex_, timeout, [this]
872 {
873 return this->ready();
874 });
875}
876
877template <typename TYPE>
878TYPE original::async::asyncWrapper<TYPE>::get()
879{
880 uniqueLock lock{this->mutex_};
881 this->rethrowIfException();
882 if (this->result_) {
883 TYPE result = std::move(*this->result_);
884 this->result_.reset();
885 return result;
886 }
887 this->cond_.wait(this->mutex_, [this]{
888 return this->ready();
889 });
890
891 this->rethrowIfException();
892
893 TYPE result = std::move(*this->result_);
894 this->result_.reset();
895 return result;
896}
897
898template <typename TYPE>
899const TYPE& original::async::asyncWrapper<TYPE>::peek() const
900{
901 uniqueLock lock{this->mutex_};
902 this->rethrowIfException();
903 if (this->result_) {
904 return *this->result_;
905 }
906 this->cond_.wait(this->mutex_, [this]{
907 return this->ready();
908 });
909
910 this->rethrowIfException();
911 return *this->result_;
912}
913
914template <typename TYPE>
915original::strongPtr<TYPE> original::async::asyncWrapper<TYPE>::getPtr() const
916{
917 this->rethrowIfException();
918 return this->result_;
919}
920
921template <typename TYPE>
922void original::async::asyncWrapper<TYPE>::rethrowIfException() const
923{
924 if (this->e_)
925 std::rethrow_exception(this->e_);
926}
927
928template <typename TYPE>
929std::exception_ptr
930original::async::asyncWrapper<TYPE>::exception() const
931{
932 uniqueLock lock{this->mutex_};
933 return this->e_;
934}
935
936template <typename TYPE>
937original::async::future<TYPE>::future(strongPtr<asyncWrapper<TYPE>> awr)
938 : awr_(std::move(awr)) {}
939
940template <typename TYPE>
942{
943 return this->awr_ != nullptr;
944}
945
946template <typename TYPE>
951
952
953template <typename TYPE>
955{
956 if (!this->valid()) {
957 throw sysError("Access an invalid future");
958 }
959 return this->awr_->get();
960}
961
962template <typename TYPE>
964{
965 if (!this->valid()) {
966 throw sysError("Access an invalid future");
967 }
968 return this->awr_->ready();
969}
970
971template <typename TYPE>
972std::exception_ptr original::async::future<TYPE>::exception() const noexcept
973{
974 if (!this->valid()) {
975 return {};
976 }
977 return this->awr_->exception();
978}
979
980template <typename TYPE>
982{
983 if (!this->valid()) {
984 throw sysError("Access an invalid future");
985 }
986 this->awr_->wait();
987}
988
989template <typename TYPE>
991{
992 if (!this->valid()) {
993 throw sysError("Access an invalid future");
994 }
995 return this->awr_->waitFor(timeout);
996}
997
998template <typename TYPE>
1000 : awr_(std::move(awr)) {}
1001
1002template <typename TYPE>
1004{
1005 return this->awr_ != nullptr;
1006}
1007
1008template <typename TYPE>
1010{
1011 if (!this->valid()) {
1012 throw sysError("Access an invalid sharedFuture");
1013 }
1014 return this->awr_->peek();
1015}
1016
1017template <typename TYPE>
1019{
1020 if (!this->valid()) {
1021 throw sysError("Access an invalid sharedFuture");
1022 }
1023 if (!this->ready()) {
1024 throw sysError("Cannot get a strongPtr from a sharedFuture that is not ready");
1025 }
1026 return this->awr_->getPtr().template constCastTo<const TYPE>();
1027}
1028
1029template <typename TYPE>
1031{
1032 if (!this->valid()) {
1033 throw sysError("Access an invalid sharedFuture");
1034 }
1035 return this->awr_->ready();
1036}
1037
1038template <typename TYPE>
1039std::exception_ptr original::async::sharedFuture<TYPE>::exception() const noexcept
1040{
1041 if (!this->valid()) {
1042 return {};
1043 }
1044 return this->awr_->exception();
1045}
1046
1047template <typename TYPE>
1049{
1050 return this->awr_ == other.awr_;
1051}
1052
1053template <typename TYPE>
1055{
1056 return this->awr_ != other.awr_;
1057}
1058
1059template <typename TYPE>
1061{
1062 if (!this->valid()) {
1063 throw sysError("Access an invalid sharedFuture");
1064 }
1065 this->awr_->wait();
1066}
1067
1068template <typename TYPE>
1070{
1071 if (!this->valid()) {
1072 throw sysError("Access an invalid sharedFuture");
1073 }
1074 return this->awr_->waitFor(timeout);
1075}
1076
1077template <typename TYPE>
1079{
1080 return this->awr_.toHash();
1081}
1082
1083template <typename TYPE>
1085{
1086 return *this == other;
1087}
1088
1089template <typename TYPE, typename Callback>
1091{
1092 if (!other.valid()){
1093 return;
1094 }
1095 this->valid_ = true;
1096 this->c_ = std::move(other.c_);
1097 this->awr_ = std::move(other.awr_);
1098 other.valid_ = false;
1099}
1100
1101template <typename TYPE, typename Callback>
1104{
1105 if (this == &other || !other.valid()) {
1106 return *this;
1107 }
1108 this->valid_ = true;
1109 this->c_ = std::move(other.c_);
1110 this->awr_ = std::move(other.awr_);
1111 other.valid_ = false;
1112 return *this;
1113}
1114
1115template <typename TYPE, typename Callback>
1117 : c_(std::forward<Callback>(c)), awr_(makeStrongPtr<asyncWrapper<TYPE>>()), valid_(true) {}
1118
1119template <typename TYPE, typename Callback>
1125
1126template <typename TYPE, typename Callback>
1128{
1129 return this->valid_;
1130}
1131
1132template <typename TYPE, typename Callback>
1134{
1135 if (!this->valid_) {
1136 throw sysError("Try to get an invalid task");
1137 }
1138 this->valid_ = false;
1139 return std::move(this->c_);
1140}
1141
1142template <typename TYPE, typename Callback>
1144{
1145 if (!this->valid_) {
1146 throw sysError("Try to run an invalid task");
1147 }
1148 try {
1149 this->awr_->setValue(this->c_());
1150 } catch (...) {
1151 this->awr_->setException(std::current_exception());
1152 }
1153 this->valid_ = false;
1154}
1155
1156template <typename Callback, typename... Args>
1157auto original::async::makePromise(Callback&& c, Args&&... 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 {
1161 return c(args...);
1162 };
1163
1164 return promise<Return, decltype(bound)>{std::move(bound)};
1165}
1166
1167template <typename Callback, typename ... Args>
1168auto original::async::get(Callback&& c, Args&&... args)
1169 -> future<std::invoke_result_t<std::decay_t<Callback>, std::decay_t<Args>...>>
1170{
1171 auto p = makePromise(std::forward<Callback>(c), std::forward<Args>(args)...);
1172 auto fut = p.getFuture();
1173
1174 auto p_shared = makeStrongPtr<decltype(p)>(std::move(p));
1175 thread t{
1176 [p_shared]() mutable {
1177 p_shared->run();
1178 },
1180 };
1181
1182 return fut;
1183}
1184
1185template <typename T, typename Callback>
1187{
1188 using ResultType = std::invoke_result_t<Callback, T>;
1189 strongPtr<async::future<T>> shared_f = makeStrongPtr<async::future<T>>(std::move(f));
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());
1193 } else {
1194 shared_f->result();
1195 return c();
1196 }
1197 });
1198}
1199
1200template <typename Callback>
1202{
1203 using ResultType = std::invoke_result_t<Callback>;
1204 strongPtr<async::future<void>> shared_f = makeStrongPtr<async::future<void>>(std::move(f));
1205 return async::get([shared_f, c = std::forward<Callback>(c)]() mutable -> ResultType {
1206 shared_f->result();
1207 return c();
1208 });
1209}
1210
1211template <typename T, typename Callback>
1213{
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>) {
1217 return c(sf.result());
1218 } else {
1219 sf.result();
1220 return c();
1221 }
1222 }).share();
1223}
1224
1225template <typename Callback>
1227{
1228 using ResultType = std::invoke_result_t<Callback>;
1229 return async::get([sf, c = std::forward<Callback>(c)]() mutable -> ResultType {
1230 sf.result();
1231 return c();
1232 }).share();
1233}
1234
1235template <typename T, typename Callback1, typename Callback2>
1237{
1238 if (!p.valid()) {
1239 throw sysError("Try to build a lazy pipeline from an invalid promise");
1240 }
1241 using ResultType = decltype(c(std::declval<T>()));
1242 strongPtr<async::promise<T,Callback1>> shared_p = makeStrongPtr<async::promise<T, Callback1>>(std::move(p));
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()());
1246 } else {
1247 shared_p->function()();
1248 return c();
1249 }
1250 });
1251}
1252
1253template <typename Callback1, typename Callback2>
1255{
1256 if (!p.valid()) {
1257 throw sysError("Try to build a lazy pipeline from an invalid promise");
1258 }
1259 using ResultType = decltype(c());
1260 strongPtr<async::promise<void, Callback1>> shared_p = makeStrongPtr<async::promise<void, Callback1>>(std::move(p));
1261 return async::makePromise([shared_p, c = std::forward<Callback2>(c)]() mutable -> ResultType {
1262 shared_p->function()();
1263 return c();
1264 });
1265}
1266
1267inline void original::async::asyncWrapper<void>::setValue()
1268{
1269 {
1270 uniqueLock lock{this->mutex_};
1271 this->result_.set();
1272 this->ready_.store(true);
1273 }
1274 this->cond_.notify();
1275}
1276
1277inline void original::async::asyncWrapper<void>::setException(std::exception_ptr e)
1278{
1279 {
1280 uniqueLock lock{this->mutex_};
1281 this->e_ = std::move(e);
1282 this->ready_.store(true);
1283 }
1284 this->cond_.notify();
1285}
1286
1287inline bool original::async::asyncWrapper<void>::ready() const
1288{
1289 return this->ready_.load();
1290}
1291
1292inline void original::async::asyncWrapper<void>::wait() const
1293{
1294 uniqueLock lock{this->mutex_};
1295 this->cond_.wait(this->mutex_, [this]
1296 {
1297 return this->ready();
1298 });
1299}
1300
1301inline bool original::async::asyncWrapper<void>::waitFor(time::duration timeout) const
1302{
1303 uniqueLock lock{this->mutex_};
1304 return this->cond_.waitFor(this->mutex_, std::move(timeout), [this]
1305 {
1306 return this->ready();
1307 });
1308}
1309
1310inline void original::async::asyncWrapper<void>::get()
1311{
1312 uniqueLock lock{this->mutex_};
1313 this->rethrowIfException();
1314 if (this->result_) {
1315 this->result_.reset();
1316 return;
1317 }
1318 this->cond_.wait(this->mutex_, [this] {
1319 return this->ready();
1320 });
1321
1322 this->rethrowIfException();
1323 this->result_.reset();
1324}
1325
1326inline void original::async::asyncWrapper<void>::peek() const
1327{
1328 uniqueLock lock{this->mutex_};
1329 this->rethrowIfException();
1330 if (this->result_) {
1331 return;
1332 }
1333 this->cond_.wait(this->mutex_, [this] {
1334 return this->ready();
1335 });
1336
1337 this->rethrowIfException();
1338}
1339
1340inline void original::async::asyncWrapper<void>::rethrowIfException() const
1341{
1342 if (this->e_)
1343 std::rethrow_exception(this->e_);
1344}
1345
1346inline std::exception_ptr
1347original::async::asyncWrapper<void>::exception() const noexcept
1348{
1349 uniqueLock lock{this->mutex_};
1350 return this->e_;
1351}
1352
1353inline original::async::future<void>::future(strongPtr<asyncWrapper<void>> awr)
1354 : awr_(std::move(awr)) {}
1355
1356inline bool original::async::future<void>::valid() const noexcept
1357{
1358 return this->awr_ != nullptr;
1359}
1360
1362{
1363 return sharedFuture(std::move(this->awr_));
1364}
1365
1367{
1368 if (!this->valid()) {
1369 throw sysError("Access an invalid future");
1370 }
1371 this->awr_->get();
1372}
1373
1375{
1376 if (!this->valid()) {
1377 throw sysError("Access an invalid future");
1378 }
1379 return this->awr_->ready();
1380}
1381
1382inline std::exception_ptr original::async::future<void>::exception() const noexcept
1383{
1384 if (!this->valid()) {
1385 return {};
1386 }
1387 return this->awr_->exception();
1388}
1389
1391{
1392 if (!this->valid()) {
1393 throw sysError("Access an invalid future");
1394 }
1395 this->awr_->wait();
1396}
1397
1399{
1400 if (!this->valid()) {
1401 throw sysError("Access an invalid future");
1402 }
1403 return this->awr_->waitFor(timeout);
1404}
1405
1407 : awr_(std::move(awr)) {}
1408
1410{
1411 return this->awr_ != nullptr;
1412}
1413
1415{
1416 if (!this->valid()) {
1417 throw sysError("Access an invalid sharedFuture");
1418 }
1419 this->awr_->peek();
1420}
1421
1423{
1424 if (!this->valid()) {
1425 throw sysError("Access an invalid sharedFuture");
1426 }
1427 return this->awr_->ready();
1428}
1429
1430inline std::exception_ptr original::async::sharedFuture<void>::exception() const noexcept
1431{
1432 if (!this->valid()) {
1433 return {};
1434 }
1435 return this->awr_->exception();
1436}
1437
1439{
1440 return this->awr_ == other.awr_;
1441}
1442
1444{
1445 return this->awr_ != other.awr_;
1446}
1447
1448
1450{
1451 if (!this->valid()) {
1452 throw sysError("Access an invalid sharedFuture");
1453 }
1454 this->awr_->wait();
1455}
1456
1458{
1459 if (!this->valid()) {
1460 throw sysError("Access an invalid sharedFuture");
1461 }
1462 return this->awr_->waitFor(timeout);
1463}
1464
1466{
1467 return this->awr_.toHash();
1468}
1469
1470inline bool original::async::sharedFuture<void>::equals(const sharedFuture& other) const noexcept
1471{
1472 return *this == other;
1473}
1474
1475template <typename Callback>
1477{
1478 if (!other.valid()){
1479 return;
1480 }
1481 this->valid_ = true;
1482 this->c_ = std::move(other.c_);
1483 this->awr_ = std::move(other.awr_);
1484 other.valid_ = false;
1485}
1486
1487template <typename Callback>
1489{
1490 if (this == &other || !other.valid()) {
1491 return *this;
1492 }
1493 this->valid_ = true;
1494 this->c_ = std::move(other.c_);
1495 this->awr_ = std::move(other.awr_);
1496 other.valid_ = false;
1497 return *this;
1498}
1499
1500template <typename Callback>
1502 : c_(std::forward<Callback>(c)), awr_(makeStrongPtr<asyncWrapper<void>>()), valid_(true) {}
1503
1504template <typename Callback>
1509
1510template <typename Callback>
1512{
1513 return this->valid_;
1514}
1515
1516template <typename Callback>
1518{
1519 if (!this->valid_) {
1520 throw sysError("Try to get an invalid task");
1521 }
1522 this->valid_ = false;
1523 return std::move(this->c_);
1524}
1525
1526template <typename Callback>
1528{
1529 if (!this->valid_) {
1530 throw sysError("Try to run an invalid task");
1531 }
1532 try {
1533 this->c_();
1534 this->awr_->setValue();
1535 } catch (...) {
1536 this->awr_->setException(std::current_exception());
1537 }
1538 this->valid_ = false;
1539}
1540
1541#endif // ORIGINAL_ASYNC_H
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.