16 #ifndef INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 17 #define INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 21 #include "nn/nlib/Swap.h" 26 #include "nn/nlib/threading/LimitedSharedPtr.h" 34 template <
class FutureResult>
51 virtual void DoContinuation() {}
57 template <
class FUTURE,
class R,
typename CONT>
58 class FutureContinuation;
60 template <
class Derived>
64 #ifdef __cpp_rvalue_references 65 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 66 FutureBase(FutureBase&& rhs) =
default;
67 FutureBase& operator=(FutureBase&& rhs) =
default;
73 static_cast<Derived&
>(*this).value_.swap(rhs.value_);
78 bool IsValid() const NLIB_NOEXCEPT {
79 const Derived& ref =
static_cast<const Derived&
>(*this);
84 Derived& ref =
static_cast<Derived&
>(*this);
85 return ref.value_.MakeSharedFrom(f.value_);
91 bool IsReady_() const NLIB_NOEXCEPT {
92 return static_cast<const Derived&
>(*this).value_->common.IsReady();
96 template <
class Derived>
97 bool FutureBase<Derived>::IsReady() const NLIB_NOEXCEPT {
98 const Derived& ref =
static_cast<const Derived&
>(*this);
100 ref.value_->common.Lock();
101 bool rval = IsReady_();
102 ref.value_->common.Unlock();
109 template <
class Derived>
110 errno_t FutureBase<Derived>::Wait() NLIB_NOEXCEPT {
111 Derived& ref =
static_cast<Derived&
>(*this);
112 NLIB_ASSERT(ref.value_);
113 if (!ref.value_)
return EINVAL;
114 ref.value_->common.Lock();
115 while (!IsReady_()) {
116 errno_t e = ref.value_->common.Wait();
118 ref.value_->common.Unlock();
119 NLIB_ASSERT_NOERR(e);
123 ref.value_->common.Unlock();
127 template <
class Derived>
128 errno_t FutureBase<Derived>::WaitFor(
const TimeSpan& span) NLIB_NOEXCEPT {
129 Derived& ref =
static_cast<Derived&
>(*this);
130 NLIB_ASSERT(ref.value_);
131 if (!ref.value_)
return EINVAL;
133 errno_t e = DateTime::GetNow(&abstime);
135 if (e != 0)
return e;
136 ref.value_->common.Lock();
137 while (!IsReady_()) {
144 &ref.value_->common.lock,
147 ref.value_->common.Unlock();
151 ref.value_->common.Unlock();
155 template <
class Derived>
156 errno_t FutureBase<Derived>::WaitUntil(
const DateTime& datetime) NLIB_NOEXCEPT {
157 Derived& ref =
static_cast<Derived&
>(*this);
158 NLIB_ASSERT(ref.value_);
159 if (!ref.value_)
return EINVAL;
160 ref.value_->common.Lock();
161 while (!IsReady_()) {
163 &ref.value_->common.lock,
164 datetime.ToTimeValue().tick);
166 ref.value_->common.Unlock();
170 ref.value_->common.Unlock();
177 template <
class Derived>
180 PromiseBase() NLIB_NOEXCEPT {}
181 #ifdef __cpp_rvalue_references 182 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 183 PromiseBase(PromiseBase&& rhs) =
default;
184 PromiseBase& operator=(PromiseBase&&) =
default;
189 Derived& ref =
static_cast<Derived&
>(*this);
190 swap(ref.value_, rhs.value_);
194 bool IsValid() const NLIB_NOEXCEPT {
195 const Derived& ref =
static_cast<const Derived&
>(*this);
203 struct NLIB_CAPABILITY("mutex") CommonStatus {
205 detail::FutureContinuationBase* cont;
209 CommonStatus() NLIB_NOEXCEPT
210 : status(0), cont(NULL), err(0) {
214 NLIB_ASSERT_NOERR(e);
216 NLIB_ASSERT_NOERR(e);
218 ~CommonStatus() NLIB_NOEXCEPT {
219 if (cont)
delete cont;
223 NLIB_ASSERT_NOERR(e);
225 NLIB_ASSERT_NOERR(e);
227 void Lock() NLIB_NOEXCEPT NLIB_ACQUIRE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
231 NLIB_ASSERT_NOERR(e);
233 void Unlock() NLIB_NOEXCEPT NLIB_RELEASE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
237 NLIB_ASSERT_NOERR(e);
239 errno_t Wait() NLIB_NOEXCEPT NLIB_REQUIRES(*this) NLIB_NO_THREAD_SAFETY_ANALYSIS {
242 bool IsReady() NLIB_NOEXCEPT {
243 return status == 20120915L;
245 bool SetReady() NLIB_NOEXCEPT {
246 if (status != 20120915L) {
253 void NotifyAndContinuation() NLIB_NOEXCEPT {
256 NLIB_ASSERT_NOERR(e);
258 if (cont) cont->DoContinuation();
261 void NotifyAndContinuation() NLIB_NOEXCEPT {
262 static_cast<Derived&
>(*this).value_->common.NotifyAndContinuation();
269 template <
class Derived>
270 errno_t PromiseBase<Derived>::Init() NLIB_NOEXCEPT {
274 Derived& ref =
static_cast<Derived&
>(*this);
275 if (ref.value_)
return EALREADY;
276 ref.value_.reset(
new (std::nothrow)
typename Derived::Status());
277 if (!ref.value_)
return ENOMEM;
281 template <
class Derived>
283 if (e == 0)
return 0;
284 Derived& ref =
static_cast<Derived&
>(*this);
287 if (ee != 0)
return ee;
290 ref.value_->common.Lock();
291 if (ref.value_->common.SetReady()) {
292 ref.value_->common.err = e;
293 ref.value_->common.Unlock();
295 ref.value_->common.Unlock();
299 this->NotifyAndContinuation();
303 template <
class Derived>
305 errno_t PromiseBase<Derived>::GetFuture(F* p) NLIB_NOEXCEPT {
306 if (!p)
return EINVAL;
307 Derived& ref =
static_cast<Derived&
>(*this);
310 if (e != 0)
return e;
312 errno_t e = p->value_.MakeSharedFrom(ref.value_);
313 if (e != 0)
return e;
320 class Promise :
public detail::PromiseBase<Promise<R> > {
321 typedef detail::PromiseBase<Promise<R> > BaseType;
327 #ifdef __cpp_rvalue_references 328 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 334 value_ = std::move(rhs.value_);
344 errno_t SetValue(
const R& value);
353 return BaseType::GetFuture(p);
358 typename BaseType::CommonStatus common;
361 LimitedSharedPtr<Status> value_;
366 friend class detail::PromiseBase;
373 if (e != 0)
return e;
377 if (value_->common.SetReady()) {
379 value_->data = value;
381 #ifdef __cpp_exceptions 382 NLIB_RETHROW_UNWIND {
383 this->SetError(ECANCELED);
387 return this->SetError(EINVAL);
394 this->NotifyAndContinuation();
398 template <
class T,
class DEL>
399 class Promise<UniquePtr<T, DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
400 typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
405 #ifdef __cpp_rvalue_references 406 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 412 value_ = std::move(rhs.value_);
426 typename BaseType::CommonStatus common;
429 LimitedSharedPtr<Status> value_;
434 friend class detail::PromiseBase;
437 template <
class T,
class DEL>
441 if (e != 0)
return e;
444 value_->common.Lock();
445 if (value_->common.SetReady()) {
446 value_->data.reset(value);
447 value_->common.Unlock();
449 value_->common.Unlock();
453 this->NotifyAndContinuation();
457 template <
class T,
class DEL>
458 class Promise<UniquePtr<T[], DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
459 typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
464 #ifdef __cpp_rvalue_references 465 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 471 value_ = std::move(rhs.value_);
485 typename BaseType::CommonStatus common;
488 LimitedSharedPtr<Status> value_;
493 friend class detail::PromiseBase;
496 template <
class T,
class DEL>
500 if (e != 0)
return e;
503 value_->common.Lock();
504 if (value_->common.SetReady()) {
505 value_->data.reset(value);
506 value_->common.Unlock();
508 value_->common.Unlock();
512 this->NotifyAndContinuation();
517 class Promise<void> :
public detail::PromiseBase<Promise<void> > {
518 typedef detail::PromiseBase<Promise<void> > BaseType;
523 #ifdef __cpp_rvalue_references 524 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 530 value_ = std::move(rhs.value_);
544 BaseType::CommonStatus common;
546 LimitedSharedPtr<Status> value_;
551 friend class detail::PromiseBase;
555 class Promise<Future<R> > :
public detail::PromiseBase<Promise<Future<R> > > {
556 typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
561 #ifdef __cpp_rvalue_references 562 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 568 value_ = std::move(rhs.value_);
585 typename BaseType::CommonStatus common;
588 LimitedSharedPtr<Status> value_;
593 friend class detail::PromiseBase;
600 if (e != 0)
return e;
603 value_->common.Lock();
604 if (value_->common.SetReady()) {
605 errno_t e = value_->data.MakeSharedFrom(value);
606 value_->common.Unlock();
611 value_->common.Unlock();
615 this->NotifyAndContinuation();
620 class Future :
public detail::FutureBase<Future<R> > {
621 typedef detail::FutureBase<Future<R> > BaseType;
625 #ifdef __cpp_rvalue_references 626 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 627 Future(Future&& rhs) =
default;
628 Future& operator=(Future&& rhs) =
default;
630 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
631 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
632 value_ = std::move(rhs.value_);
646 NLIB_ASSERT_NOERR(e);
650 if (!ptr)
return EINVAL;
652 errno_t e = value_->common.err;
657 #ifdef __cpp_exceptions 658 NLIB_RETHROW_UNWIND {
667 bool IsValid() const NLIB_NOEXCEPT {
return BaseType::IsValid(); }
668 bool IsReady() const NLIB_NOEXCEPT {
return BaseType::IsReady(); }
671 return BaseType::WaitFor(span);
674 return BaseType::WaitUntil(datetime);
676 template <
class RNEXT>
678 return BaseType::Then(next, cont);
683 LimitedSharedPtr<typename Promise<R>::Status> value_;
688 friend class detail::FutureBase;
690 friend class detail::PromiseBase;
693 template <
class T,
class DEL>
694 class Future<UniquePtr<T, DEL> > :
public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
695 typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
698 Future() NLIB_NOEXCEPT {}
699 #ifdef __cpp_rvalue_references 700 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 701 Future(Future&& rhs) =
default;
702 Future& operator=(Future&& rhs) =
default;
704 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
705 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
706 value_ = std::move(rhs.value_);
712 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
716 T* Get() NLIB_NOEXCEPT {
718 return value_->data.get();
720 errno_t Get(T** ptr) NLIB_NOEXCEPT {
721 if (!ptr)
return EINVAL;
723 errno_t e = value_->common.err;
724 if (e == 0) *ptr = value_->data.get();
727 T* Release() NLIB_NOEXCEPT {
729 return value_->data.release();
733 LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> value_;
738 friend class detail::FutureBase;
740 friend class detail::PromiseBase;
743 template <
class T,
class DEL>
744 class Future<UniquePtr<T[], DEL> > :
public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
745 typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
748 Future() NLIB_NOEXCEPT {}
749 #ifdef __cpp_rvalue_references 750 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 751 Future(Future&& rhs) =
default;
752 Future& operator=(Future&& rhs) =
default;
754 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
755 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
756 value_ = std::move(rhs.value_);
762 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
766 T* Get() NLIB_NOEXCEPT {
768 return value_->data.get();
770 errno_t Get(T** ptr) NLIB_NOEXCEPT {
771 if (!ptr)
return EINVAL;
773 errno_t e = value_->common.err;
774 if (e == 0) *ptr = value_->data.get();
777 T* Release() NLIB_NOEXCEPT {
779 return value_->common.data.release();
783 LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> value_;
788 friend class detail::FutureBase;
790 friend class detail::PromiseBase;
794 class Future<void> :
public detail::FutureBase<Future<void> > {
795 typedef detail::FutureBase<Future<void> > BaseType;
798 Future() NLIB_NOEXCEPT {}
799 #ifdef __cpp_rvalue_references 800 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 801 Future(Future&& rhs) =
default;
802 Future& operator=(Future&& rhs) =
default;
804 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
805 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
806 value_ = std::move(rhs.value_);
812 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
818 return value_->common.err;
822 LimitedSharedPtr<Promise<void>::Status> value_;
827 friend class detail::FutureBase;
829 friend class detail::PromiseBase;
833 class Future<Future<R> > :
public detail::FutureBase<Future<Future<R> > > {
834 typedef detail::FutureBase<Future<Future<R> > > BaseType;
837 Future() NLIB_NOEXCEPT {}
838 #ifdef __cpp_rvalue_references 839 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 840 Future(Future&& rhs) =
default;
841 Future& operator=(Future&& rhs) =
default;
843 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
844 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
845 value_ = std::move(rhs.value_);
851 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
856 if (!inner)
return EINVAL;
858 errno_t e = value_->common.err;
859 if (e != 0)
return e;
864 LimitedSharedPtr<typename Promise<Future<R> >::Status> value_;
869 friend class detail::FutureBase;
871 friend class detail::PromiseBase;
877 class FuncHolderBase0 {
879 virtual ~FuncHolderBase0() {}
880 virtual R operator()() = 0;
883 template <
class R,
class T1>
884 class FuncHolderBase1 {
886 virtual ~FuncHolderBase1() {}
887 virtual R operator()(T1 NLIB_RREF arg1) = 0;
890 template <
class R,
class T1,
class T2>
891 class FuncHolderBase2 {
893 virtual ~FuncHolderBase2() {}
894 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0;
897 template <
class R,
class T1,
class T2,
class T3>
898 class FuncHolderBase3 {
900 virtual ~FuncHolderBase3() {}
901 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0;
904 template <
class R,
class T1,
class T2,
class T3,
class T4>
905 class FuncHolderBase4 {
907 virtual ~FuncHolderBase4() {}
908 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
909 T4 NLIB_RREF arg4) = 0;
912 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
913 class FuncHolderBase5 {
915 virtual ~FuncHolderBase5() {}
916 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
917 T5 NLIB_RREF arg5) = 0;
920 template <
class FUNC,
bool USESWAP>
927 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
934 template <
class FUNC>
935 class FuncWrap_<FUNC, false> {
937 FuncWrap_(FUNC& func) : func_(func) {}
938 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
945 template <
class FUNC>
946 class FuncWrap :
public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
947 typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
950 FuncWrap(FUNC& func) : BaseType(func) {}
954 class FuncWrap<R()> {
957 explicit FuncWrap(FUNC func) : func_(func) {}
958 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
965 template <
class R,
class T1>
966 class FuncWrap<R(T1)> {
968 typedef R (*FUNC)(T1);
969 explicit FuncWrap(FUNC func) : func_(func) {}
970 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
977 template <
class R,
class T1,
class T2>
978 class FuncWrap<R(T1, T2)> {
980 typedef R (*FUNC)(T1, T2);
981 explicit FuncWrap(FUNC func) : func_(func) {}
982 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
989 template <
class R,
class T1,
class T2,
class T3>
990 class FuncWrap<R(T1, T2, T3)> {
992 typedef R (*FUNC)(T1, T2, T3);
993 explicit FuncWrap(FUNC func) : func_(func) {}
994 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
1001 template <
class R,
class T1,
class T2,
class T3,
class T4>
1002 class FuncWrap<R(T1, T2, T3, T4)> {
1004 typedef R (*FUNC)(T1, T2, T3, T4);
1005 explicit FuncWrap(FUNC func) : func_(func) {}
1006 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
1013 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1014 class FuncWrap<R(T1, T2, T3, T4, T5)> {
1016 typedef R (*FUNC)(T1, T2, T3, T4, T5);
1017 explicit FuncWrap(FUNC func) : func_(func) {}
1018 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
1025 template <
class FUNC,
class R>
1026 class FuncHolder0 :
public FuncHolderBase0<R> {
1028 FuncHolder0(FUNC& f) : func_(f) {}
1031 return func_.get()();
1035 FuncWrap<FUNC> func_;
1038 template <
class FUNC,
class R,
class T1>
1039 class FuncHolder1 :
public FuncHolderBase1<R, T1> {
1041 FuncHolder1(FUNC& f) : func_(f) {}
1044 return func_.get()(NLIB_FWD(T1, arg1));
1048 FuncWrap<FUNC> func_;
1051 template <
class FUNC,
class R,
class T1,
class T2>
1052 class FuncHolder2 :
public FuncHolderBase2<R, T1, T2> {
1054 FuncHolder2(FUNC& f) : func_(f) {}
1056 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)
NLIB_OVERRIDE {
1057 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1061 FuncWrap<FUNC> func_;
1064 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1065 class FuncHolder3 :
public FuncHolderBase3<R, T1, T2, T3> {
1067 FuncHolder3(FUNC& f) : func_(f) {}
1069 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)
NLIB_OVERRIDE {
1070 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1074 FuncWrap<FUNC> func_;
1077 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1078 class FuncHolder4 :
public FuncHolderBase4<R, T1, T2, T3, T4> {
1080 FuncHolder4(FUNC& f) : func_(f) {}
1082 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1084 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1085 NLIB_FWD(T4, arg4));
1089 FuncWrap<FUNC> func_;
1092 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1093 class FuncHolder5 :
public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
1095 FuncHolder5(FUNC& f) : func_(f) {}
1097 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1099 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1100 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1104 FuncWrap<FUNC> func_;
1114 template <class FUNC>
1117 errno_t GetFuture(Future<R>* p) NLIB_NOEXCEPT;
1124 typedef R ReturnType;
1127 #ifdef __cpp_rvalue_references 1128 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1133 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {}
1135 func_ = std::move(rhs.func_);
1136 promise_ = std::move(rhs.promise_);
1142 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {}
1144 func_.reset(rhs.func_.release());
1145 promise_.assign(rhs.promise_,
move_tag());
1150 swap(func_, rhs.func_);
1151 swap(promise_, rhs.promise_);
1153 template <
class FUNC>
1156 if (e != 0)
return e;
1157 func_.reset(
new (std::nothrow) detail::FuncHolder0<FUNC, R>(func));
1158 return !func_ ? ENOMEM : 0;
1166 template <
class DUMMY>
1167 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec() {
1169 R rval = (*func_)();
1172 promise_.SetValue(rval);
1174 promise_.SetError(e);
1177 #ifdef __cpp_exceptions 1178 NLIB_RETHROW_UNWIND {
1179 promise_.SetError(ECANCELED);
1182 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1185 template <
class DUMMY>
1186 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec() {
1189 promise_.SetValue();
1191 #ifdef __cpp_exceptions 1192 NLIB_RETHROW_UNWIND {
1193 promise_.SetError(ECANCELED);
1196 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1205 template <
class R,
class T1>
1208 typedef R ReturnType;
1211 #ifdef __cpp_rvalue_references 1212 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1217 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1220 func_ = std::move(rhs.func_);
1221 promise_ = std::move(rhs.promise_);
1227 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1230 func_.reset(rhs.func_.release());
1231 promise_.assign(rhs.promise_,
move_tag());
1236 swap(func_, rhs.func_);
1237 swap(promise_, rhs.promise_);
1239 template <
class FUNC>
1242 if (e != 0)
return e;
1243 func_.reset(
new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func));
1244 return !func_ ? ENOMEM : 0;
1247 void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1250 template <
class DUMMY>
1251 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(T1 NLIB_RREF arg1) {
1253 R rval = (*func_)(NLIB_FWD(T1, arg1));
1256 promise_.SetValue(rval);
1258 promise_.SetError(e);
1261 #ifdef __cpp_exceptions 1262 NLIB_RETHROW_UNWIND {
1263 promise_.SetError(ECANCELED);
1266 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1269 template <
class DUMMY>
1270 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(T1 NLIB_RREF arg1) {
1272 (*func_)(NLIB_FWD(T1, arg1));
1273 promise_.SetValue();
1275 #ifdef __cpp_exceptions 1276 NLIB_RETHROW_UNWIND {
1277 promise_.SetError(ECANCELED);
1280 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1289 template <
class R,
class T1,
class T2>
1292 typedef R ReturnType;
1295 #ifdef __cpp_rvalue_references 1296 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1301 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1304 func_ = std::move(rhs.func_);
1305 promise_ = std::move(rhs.promise_);
1311 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1314 func_.reset(rhs.func_.release());
1315 promise_.assign(rhs.promise_,
move_tag());
1320 swap(func_, rhs.func_);
1321 swap(promise_, rhs.promise_);
1323 template <
class FUNC>
1326 if (e != 0)
return e;
1327 func_.reset(
new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func));
1328 return !func_ ? ENOMEM : 0;
1331 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1332 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1336 template <
class DUMMY>
1337 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1338 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1340 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1343 promise_.SetValue(rval);
1345 promise_.SetError(e);
1348 #ifdef __cpp_exceptions 1349 NLIB_RETHROW_UNWIND {
1350 promise_.SetError(ECANCELED);
1353 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1356 template <
class DUMMY>
1357 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1358 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1360 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1361 promise_.SetValue();
1363 #ifdef __cpp_exceptions 1364 NLIB_RETHROW_UNWIND {
1365 promise_.SetError(ECANCELED);
1368 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1377 template <
class R,
class T1,
class T2,
class T3>
1380 typedef R ReturnType;
1383 #ifdef __cpp_rvalue_references 1384 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1389 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1392 func_ = std::move(rhs.func_);
1393 promise_ = std::move(rhs.promise_);
1399 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1402 func_.reset(rhs.func_.release());
1403 promise_.assign(rhs.promise_,
move_tag());
1408 swap(func_, rhs.func_);
1409 swap(promise_, rhs.promise_);
1411 template <
class FUNC>
1414 if (e != 0)
return e;
1415 func_.reset(
new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func));
1416 return !func_ ? ENOMEM : 0;
1419 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1420 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1424 template <
class DUMMY>
1425 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1426 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1428 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1431 promise_.SetValue(rval);
1433 promise_.SetError(e);
1436 #ifdef __cpp_exceptions 1437 NLIB_RETHROW_UNWIND {
1438 promise_.SetError(ECANCELED);
1441 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1444 template <
class DUMMY>
1445 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1446 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1448 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1449 promise_.SetValue();
1451 #ifdef __cpp_exceptions 1452 NLIB_RETHROW_UNWIND {
1453 promise_.SetError(ECANCELED);
1456 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1465 template <
class R,
class T1,
class T2,
class T3,
class T4>
1468 typedef R ReturnType;
1471 #ifdef __cpp_rvalue_references 1472 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1477 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1480 func_ = std::move(rhs.func_);
1481 promise_ = std::move(rhs.promise_);
1487 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1490 func_.reset(rhs.func_.release());
1491 promise_.assign(rhs.promise_,
move_tag());
1496 swap(func_, rhs.func_);
1497 swap(promise_, rhs.promise_);
1499 template <
class FUNC>
1502 if (e != 0)
return e;
1503 func_.reset(
new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func));
1504 return !func_ ? ENOMEM : 0;
1507 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1508 T4 NLIB_RREF arg4) {
1509 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1513 template <
class DUMMY>
1514 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1515 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1517 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1518 NLIB_FWD(T4, arg4));
1521 promise_.SetValue(rval);
1523 promise_.SetError(e);
1526 #ifdef __cpp_exceptions 1527 NLIB_RETHROW_UNWIND {
1528 promise_.SetError(ECANCELED);
1531 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1534 template <
class DUMMY>
1535 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1536 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1538 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1539 NLIB_FWD(T4, arg4));
1540 promise_.SetValue();
1542 #ifdef __cpp_exceptions 1543 NLIB_RETHROW_UNWIND {
1544 promise_.SetError(ECANCELED);
1547 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1556 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1559 typedef R ReturnType;
1562 #ifdef __cpp_rvalue_references 1563 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1568 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1571 func_ = std::move(rhs.func_);
1572 promise_ = std::move(rhs.promise_);
1578 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1581 func_.reset(rhs.func_.release());
1582 promise_.assign(rhs.promise_,
move_tag());
1587 swap(func_, rhs.func_);
1588 swap(promise_, rhs.promise_);
1590 template <
class FUNC>
1593 if (e != 0)
return e;
1594 func_.reset(
new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func));
1595 return !func_ ? ENOMEM : 0;
1598 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1599 T5 NLIB_RREF arg5) {
1600 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1601 NLIB_FWD(T5, arg5));
1605 template <
class DUMMY>
1606 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1607 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1608 T5 NLIB_RREF arg5) {
1610 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1611 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1614 promise_.SetValue(rval);
1616 promise_.SetError(e);
1619 #ifdef __cpp_exceptions 1620 NLIB_RETHROW_UNWIND {
1621 promise_.SetError(ECANCELED);
1624 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1627 template <
class DUMMY>
1628 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1629 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1630 T5 NLIB_RREF arg5) {
1632 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1633 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1634 promise_.SetValue();
1636 #ifdef __cpp_exceptions 1637 NLIB_RETHROW_UNWIND {
1638 promise_.SetError(ECANCELED);
1641 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1652 template <
class T,
bool B>
1654 explicit XHolder(
const T& value_) : value() {
1656 swap(const_cast<T&>(value_), value);
1662 struct XHolder<T, false> {
1663 explicit XHolder(
const T& value_) : value(value_) {}
1668 struct XHolder<R(), false> {
1669 XHolder(R (*value_)()) : value(value_) {}
1673 template <
class R,
class T1>
1674 struct XHolder<R(T1), false> {
1675 XHolder(R (*value_)(T1)) : value(value_) {}
1679 template <
class R,
class T1,
class T2>
1680 struct XHolder<R(T1, T2), false> {
1681 XHolder(R (*value_)(T1, T2)) : value(value_) {}
1685 template <
class R,
class T1,
class T2,
class T3>
1686 struct XHolder<R(T1, T2, T3), false> {
1687 XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1688 R (*value)(T1, T2, T3);
1691 template <
class R,
class T1,
class T2,
class T3,
class T4>
1692 struct XHolder<R(T1, T2, T3, T4), false> {
1693 XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1694 R (*value)(T1, T2, T3, T4);
1697 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1698 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1699 XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1700 R (*value)(T1, T2, T3, T4, T5);
1703 #define NLIB_ASYNC_HOLDER(T, B) \ 1704 XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value> 1705 #ifdef __cpp_rvalue_references 1706 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1707 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && \ 1708 !IsPointer<FUNC>::value> 1710 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1711 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && \ 1712 !IsPointer<FUNC>::value> 1715 template <
class FUNC,
class R,
class BF>
1719 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1721 if (e != 0)
return e;
1723 if (e != 0)
return e;
1729 template <
class FUNC,
class R,
class BF,
class T1>
1734 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1736 if (e != 0)
return e;
1738 if (e != 0)
return e;
1740 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1745 template <
class FUNC,
class R,
class BF,
class T1,
class T2>
1746 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
1750 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1752 if (e != 0)
return e;
1754 if (e != 0)
return e;
1756 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1757 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1758 e = th.
Start(settings, task, arg1_.value, arg2_.value,
move_tag());
1762 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3>
1763 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1767 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1769 if (e != 0)
return e;
1771 if (e != 0)
return e;
1773 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1774 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1775 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1776 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value,
move_tag());
1780 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4>
1781 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1785 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1787 if (e != 0)
return e;
1789 if (e != 0)
return e;
1791 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1792 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1793 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1794 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1795 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value,
move_tag());
1799 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4,
class T5>
1800 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1801 const T4& arg4,
const T5& arg5,
const ThreadSettings& settings, BF) {
1804 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1806 if (e != 0)
return e;
1808 if (e != 0)
return e;
1810 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1811 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1812 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1813 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1814 NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1815 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1820 #undef NLIB_ASYNC_HOLDER 1821 #undef NLIB_ASYNC_HOLDER_F 1825 template <
class FUNC,
class R>
1827 return detail::Async_(future, func, settings, FalseType());
1830 template <
class FUNC,
class R>
1833 return detail::Async_(future, func, settings, TrueType());
1836 template <
class FUNC,
class R>
1840 return Async(future, func, settings);
1843 template <
class FUNC,
class R>
1850 template <
class FUNC,
class R,
class T1>
1853 return detail::Async_(future, func, arg1, settings, FalseType());
1856 template <
class FUNC,
class R,
class T1>
1859 return detail::Async_(future, func, arg1, settings, TrueType());
1862 template <
class FUNC,
class R,
class T1>
1866 return Async(future, func, arg1, settings);
1869 template <
class FUNC,
class R,
class T1>
1876 template <
class FUNC,
class R,
class T1,
class T2>
1879 return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1882 template <
class FUNC,
class R,
class T1,
class T2>
1885 return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1888 template <
class FUNC,
class R,
class T1,
class T2>
1892 return Async(future, func, arg1, arg2, settings);
1895 template <
class FUNC,
class R,
class T1,
class T2>
1900 return Async(future, func, arg1, arg2, settings,
move_tag());
1903 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1906 return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1909 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1912 return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1915 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1920 return Async(future, func, arg1, arg2, arg3, settings);
1923 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1928 return Async(future, func, arg1, arg2, arg3, settings,
move_tag());
1931 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1933 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings) {
1934 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1937 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1940 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1943 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1945 const T3& arg3,
const T4& arg4) {
1948 return Async(future, func, arg1, arg2, arg3, arg4, settings);
1951 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1953 const T3& arg3,
const T4& arg4,
move_tag) {
1956 return Async(future, func, arg1, arg2, arg3, arg4, settings,
move_tag());
1959 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1961 const T3& arg3,
const T4& arg4,
const T5& arg5,
1963 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1966 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1968 const T3& arg3,
const T4& arg4,
const T5& arg5,
const ThreadSettings& settings,
1970 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1973 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1975 const T3& arg3,
const T4& arg4,
const T5& arg5) {
1978 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1981 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1983 const T3& arg3,
const T4& arg4,
const T5& arg5,
move_tag) {
1986 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings,
move_tag());
1991 if (!future)
return EINVAL;
1994 if (e != 0)
return e;
1996 if (e != 0)
return e;
1998 if (e != 0)
return e;
2003 template <
class FUTURE,
class R,
typename CONT>
2004 class FutureContinuation :
public FutureContinuationBase {
2006 FutureContinuation(FUTURE& f, CONT cont) NLIB_NOEXCEPT
2010 errno_t Init() NLIB_NOEXCEPT {
return next_.Init(); }
2011 errno_t GetFuture(
Future<R>* future) NLIB_NOEXCEPT {
return next_.GetFuture(future); }
2012 virtual ~FutureContinuation() NLIB_NOEXCEPT
NLIB_OVERRIDE {}
2022 template <
class FUTURE,
class R,
typename CONT>
2023 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
2024 int32_t expected = 0;
2028 R rval = func_(parent_);
2031 (void)next_.SetValue(rval);
2033 (void)next_.SetError(e);
2036 #ifdef __cpp_exceptions 2037 NLIB_RETHROW_UNWIND {
2038 next_.SetError(ECANCELED);
2041 NLIB_CATCH(...) { (void)next_.SetError(EINVAL); }
2046 template <
class Derived>
2048 errno_t FutureBase<Derived>::Then(
Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT {
2049 Derived& ref =
static_cast<Derived&
>(*this);
2050 if (!ref.value_)
return EINVAL;
2052 typedef R (*CONT)(Derived&);
2054 new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
2055 if (!ptr)
return ENOMEM;
2057 if (e != 0)
return e;
2058 e = ptr->GetFuture(next);
2059 if (e != 0)
return e;
2061 ref.value_->common.Lock();
2062 ref.value_->common.cont = ptr.release();
2063 bool isready = ref.IsReady_();
2064 ref.value_->common.Unlock();
2066 ref.value_->common.cont->DoContinuation();
2073 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
2074 struct FutureTuple {
2083 struct FutureTuple<None, None, None, None, None>;
2085 struct FutureTuple<R1, None, None, None, None>;
2087 template <
class R1,
class R2>
2088 struct FutureTuple<R1, R2, None, None, None> {
2093 template <
class R1,
class R2,
class R3>
2094 struct FutureTuple<R1, R2, R3, None, None> {
2100 template <
class R1,
class R2,
class R3,
class R4>
2101 struct FutureTuple<R1, R2, R3, R4, None> {
2108 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
2115 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
2119 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
2124 typedef void (*FuncType)(ArgType& ptr);
2127 static void Call(ArgType& ptr) {
2131 static void CallWhenAny(ArgType& ptr) {
2133 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2134 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady() ||
2135 ptr->tuple_->f5.IsReady()) {
2140 ptr->promise_.SetValue(ptr->tuple_.
release());
2142 static void CallWhenAll(ArgType& ptr) {
2143 ptr->tuple_->f1.Wait();
2144 ptr->tuple_->f2.Wait();
2145 ptr->tuple_->f3.Wait();
2146 ptr->tuple_->f4.Wait();
2147 ptr->tuple_->f5.Wait();
2148 ptr->promise_.SetValue(ptr->tuple_.
release());
2154 if (e != 0)
return e;
2155 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
2156 if (!tuple_)
return ENOMEM;
2157 e = promise_.GetFuture(f);
2158 if (e != 0)
return e;
2159 e = tuple_->f1.MakeSharedFrom(*f1);
2160 if (e != 0)
return e;
2161 e = tuple_->f2.MakeSharedFrom(*f2);
2162 if (e != 0)
return e;
2163 e = tuple_->f3.MakeSharedFrom(*f3);
2164 if (e != 0)
return e;
2165 e = tuple_->f4.MakeSharedFrom(*f4);
2166 if (e != 0)
return e;
2167 e = tuple_->f5.MakeSharedFrom(*f5);
2168 if (e != 0)
return e;
2180 template <
class R1,
class R2,
class R3,
class R4,
class R5>
2185 if (!f1 || !f2 || !f3 || !f4 || !f5)
return EINVAL;
2189 e = ptr->Init(f, f1, f2, f3, f4, f5);
2190 if (e != 0)
return e;
2193 if (e != 0)
return e;
2202 template <
class R1,
class R2>
2208 return DoWhen(f, f1, f2, CallWhenAll);
2211 return DoWhen(f, f1, f2, CallWhenAny);
2216 typedef void (*FuncType)(ArgType& ptr);
2218 static void Call(ArgType& ptr) {
2222 static void CallWhenAny(ArgType& ptr) {
2224 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady()) {
2229 ptr->promise_.SetValue(ptr->tuple_.
release());
2231 static void CallWhenAll(ArgType& ptr) {
2232 ptr->tuple_->f1.Wait();
2233 ptr->tuple_->f2.Wait();
2234 ptr->promise_.SetValue(ptr->tuple_.
release());
2239 if (e != 0)
return e;
2240 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2>());
2241 if (!tuple_)
return ENOMEM;
2242 e = promise_.GetFuture(f);
2243 if (e != 0)
return e;
2244 e = tuple_->f1.MakeSharedFrom(*f1);
2245 if (e != 0)
return e;
2246 e = tuple_->f2.MakeSharedFrom(*f2);
2247 if (e != 0)
return e;
2259 template <
class R1,
class R2>
2262 if (!f1 || !f2)
return EINVAL;
2266 e = ptr->Init(f, f1, f2);
2267 if (e != 0)
return e;
2270 if (e != 0)
return e;
2274 template <
class R1,
class R2,
class R3>
2280 return DoWhen(f, f1, f2, f3, CallWhenAll);
2283 return DoWhen(f, f1, f2, f3, CallWhenAny);
2288 typedef void (*FuncType)(ArgType& ptr);
2291 static void Call(ArgType& ptr) {
2295 static void CallWhenAny(ArgType& ptr) {
2297 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2298 ptr->tuple_->f3.IsReady()) {
2303 ptr->promise_.SetValue(ptr->tuple_.
release());
2305 static void CallWhenAll(ArgType& ptr) {
2306 ptr->tuple_->f1.Wait();
2307 ptr->tuple_->f2.Wait();
2308 ptr->tuple_->f3.Wait();
2309 ptr->promise_.SetValue(ptr->tuple_.
release());
2314 if (e != 0)
return e;
2315 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3>());
2316 if (!tuple_)
return ENOMEM;
2317 e = promise_.GetFuture(f);
2318 if (e != 0)
return e;
2319 e = tuple_->f1.MakeSharedFrom(*f1);
2320 if (e != 0)
return e;
2321 e = tuple_->f2.MakeSharedFrom(*f2);
2322 if (e != 0)
return e;
2323 e = tuple_->f3.MakeSharedFrom(*f3);
2324 if (e != 0)
return e;
2336 template <
class R1,
class R2,
class R3>
2339 if (!f1 || !f2 || !f3)
return EINVAL;
2343 e = ptr->Init(f, f1, f2, f3);
2344 if (e != 0)
return e;
2347 if (e != 0)
return e;
2351 template <
class R1,
class R2,
class R3,
class R4>
2358 return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2362 return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2367 typedef void (*FuncType)(ArgType& ptr);
2370 static void Call(ArgType& ptr) {
2374 static void CallWhenAny(ArgType& ptr) {
2376 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2377 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady()) {
2382 ptr->promise_.SetValue(ptr->tuple_.
release());
2384 static void CallWhenAll(ArgType& ptr) {
2385 ptr->tuple_->f1.Wait();
2386 ptr->tuple_->f2.Wait();
2387 ptr->tuple_->f3.Wait();
2388 ptr->tuple_->f4.Wait();
2389 ptr->promise_.SetValue(ptr->tuple_.
release());
2395 if (e != 0)
return e;
2396 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2397 if (!tuple_)
return ENOMEM;
2398 e = promise_.GetFuture(f);
2399 if (e != 0)
return e;
2400 e = tuple_->f1.MakeSharedFrom(*f1);
2401 if (e != 0)
return e;
2402 e = tuple_->f2.MakeSharedFrom(*f2);
2403 if (e != 0)
return e;
2404 e = tuple_->f3.MakeSharedFrom(*f3);
2405 if (e != 0)
return e;
2406 e = tuple_->f4.MakeSharedFrom(*f4);
2407 if (e != 0)
return e;
2419 template <
class R1,
class R2,
class R3,
class R4>
2422 if (!f1 || !f2 || !f3 || !f4)
return EINVAL;
2426 e = ptr->Init(f, f1, f2, f3, f4);
2427 if (e != 0)
return e;
2430 if (e != 0)
return e;
2437 NLIB_DEFINE_STD_SWAP_T_BEGIN3(
nn, nlib, threading)
2438 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::Future)
2439 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise)
2440 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask)
2441 NLIB_DEFINE_STD_SWAP_T_END3(
nn, nlib, threading)
2443 #endif // INCLUDE_NN_NLIB_THREADING_FUTURE_H_ errno_t Start(const ThreadSettings &settings, const FUNC &f, move_tag)
This function is nearly identical to the version without start options, except that it can specify th...
errno_t MakeReadyFuture(Future< R > *future, const R &value)
Creates a Future with preset values.
int64_t tick
These can be used for nlib_time and nlib_duration.
#define NLIB_OVERRIDE
Defines override if it is available for use. If not, holds an empty string.
errno_t Async(Future< R > *future, const FUNC &func, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, move_tag)
Async that moves arguments and function objects.
static errno_t Any(FutureType *f, Future< R1 > *f1, Future< R2 > *f2, Future< R3 > *f3, Future< R4 > *f4, Future< R5 > *f5)
When an error has been set to any of Future f1, f2, f3, f4, and f5, a value is set in f...
errno_t Sleep(const TimeSpan &span) noexcept
Makes the thread sleep for a specified period of time.
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Implements mutex, reentrant timeout mutex, and reentrant mutex.
errno_t Wait() noexcept
Waits for conditions that allow results to be acquired.
bool GetDetachState() const noexcept
Gets whether the thread is set to start in a detached state.
Future(Future &rhs, move_tag) noexcept
Corresponds to a move constructor.
void SetDetachState(bool detached) noexcept
Sets whether to start a thread in a detached state.
errno_t GetFuture(Future< R > *p) noexcept
Sets Future to get the result of execution.
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Defines that class that is corresponding to std::unique_ptr.
Promise & assign(Promise &rhs, move_tag) noexcept
Corresponds to a move assignment operator.
Class to create and start threads.
errno_t WaitUntil(const DateTime &datetime) noexcept
Waits for conditions that allow results to be acquired, until the defined time.
Class that calls the result of thread execution and outputs it in a thread safe manner. This class is similar to the std::promise class of C++11.
R Get()
Calls Get(R* ptr) after creating an object for the type that will be used internally as the value...
The class for representing the date and time.
bool IsValid() const noexcept
errno_t WaitFor(const TimeSpan &span) noexcept
Waits for conditions that allow results to be acquired, for a specified amount of time...
Defines a Future for which to set the value, under the condition that a value has been set for the Fu...
errno_t SetError(errno_t e) noexcept
Sets an error value.
Class to wrap nlib_thread_attr. nlib_thread_attr_init() and nlib_thread_attr_destroy() are run automa...
errno_t GetFuture(Future< R > *p) noexcept
Sets Future to get the result of execution.
An empty structure indicating that an argument to a function needs to be moved.
errno_t MakeSharedFrom(const Future &f) noexcept
Shares a Future so that it may be viewed.
static errno_t All(FutureType *f, Future< R1 > *f1, Future< R2 > *f2, Future< R3 > *f3, Future< R4 > *f4, Future< R5 > *f5)
When an error has been set to all Future f1, f2, f3, f4, and f5, sets a value to f.
#define NLIB_CATCH(x)
Defines catch(x) if exceptions are enabled. If not, defines if (true).
#define NLIB_TRY
Defines try if exceptions are enabled. If not, defines if (true).
errno_t Get(R *ptr)
Waits until a result is acquired, and then gets the result.
Defines the class for handling times and durations.
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
errno_t GetFutureError(FutureResult &result) noexcept
Function that enables systems to get error values when threads hold an error value.
Class that gets the output of a different thread executing in a thread safe manner. This class is similar to the std::shared_future class of C++11.
Future< R > FutureType
The type for Future<R>.
Wraps objects like CriticalSection. Locks with a constructor, and unlocks with a destructor.
errno_t StartRaw(ThreadFunc func, void *arg) noexcept
Starts running a function that has one void* type argument in a different thread. ...
Class that wraps a function to run in a different thread, and gets the return value in a thread safe ...
Promise() noexcept
Instantiates the object with default parameters (default constructor).
TimeValue ToTimeValue() const noexcept
Returns a TimeValue object.
bool IsReady() const noexcept
Returns whether a value has been set for Future (whether Promise set a value or an error)...
errno_t SetValue(const R &value)
Sets a value, and makes it possible to use Future to extract it.
PackagedTask< T > ThisType
The object type.
The class for representing the time.
errno_t Then(Future< RNEXT > *next, RNEXT(*cont)(Future< R > &)) noexcept
Registers the process to continue (continuation) to this future.
Future< ReturnType > FutureType
Type of the newly created Future.
Future() noexcept
Instantiates the object with default parameters (default constructor).
Future & assign(Future &rhs, move_tag) noexcept
Corresponds to a move assignment operator.
errno_t Init() noexcept
Initializes the object.
Promise(Promise &rhs, move_tag) noexcept
Corresponds to a move constructor.
UniquePtr< FutureTuple< R1, R2, R3, R4, R5 > > ReturnType
Type of value to set to the newly created Future.
T * release() noexcept
Release ownership of the pointer and returns the pointer.
errno_t Init(FUNC &func)
Performs initialization.