16 #ifndef INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 17 #define INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 19 #include "nn/nlib/Swap.h" 24 #include "nn/nlib/threading/LimitedSharedPtr.h" 32 template <
class FutureResult>
49 virtual void DoContinuation() {}
55 template <
class FUTURE,
class R,
typename CONT>
56 class FutureContinuation;
58 template <
class Derived>
62 #ifdef NLIB_CXX11_RVALUE_REFERENCES 63 FutureBase(FutureBase&& rhs)
NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
68 bool IsValid() const NLIB_NOEXCEPT {
69 const Derived& ref =
static_cast<const Derived&
>(*this);
74 Derived& ref =
static_cast<Derived&
>(*this);
75 return ref.value_.MakeSharedFrom(f.value_);
79 void swap(Derived& rhs) NLIB_NOEXCEPT {
80 static_cast<Derived&
>(*this).value_.swap(rhs.value_);
84 bool IsReady_() const NLIB_NOEXCEPT {
85 return static_cast<const Derived&
>(*this).value_->common.IsReady();
89 template <
class Derived>
90 bool FutureBase<Derived>::IsReady() const NLIB_NOEXCEPT {
91 const Derived& ref =
static_cast<const Derived&
>(*this);
93 ref.value_->common.Lock();
94 bool rval = IsReady_();
95 ref.value_->common.Unlock();
102 template <
class Derived>
103 errno_t FutureBase<Derived>::Wait() NLIB_NOEXCEPT {
104 Derived& ref =
static_cast<Derived&
>(*this);
105 NLIB_ASSERT(ref.value_);
106 if (!ref.value_)
return EINVAL;
107 ref.value_->common.Lock();
108 while (!IsReady_()) {
109 errno_t e = ref.value_->common.Wait();
111 ref.value_->common.Unlock();
112 NLIB_ASSERT_NOERR(e);
116 ref.value_->common.Unlock();
120 template <
class Derived>
121 errno_t FutureBase<Derived>::WaitFor(
const TimeSpan& span) NLIB_NOEXCEPT {
122 Derived& ref =
static_cast<Derived&
>(*this);
123 NLIB_ASSERT(ref.value_);
124 if (!ref.value_)
return EINVAL;
126 errno_t e = DateTime::GetNow(&abstime);
128 if (e != 0)
return e;
129 ref.value_->common.Lock();
130 while (!IsReady_()) {
137 &ref.value_->common.lock,
140 ref.value_->common.Unlock();
144 ref.value_->common.Unlock();
148 template <
class Derived>
149 errno_t FutureBase<Derived>::WaitUntil(
const DateTime& datetime) NLIB_NOEXCEPT {
150 Derived& ref =
static_cast<Derived&
>(*this);
151 NLIB_ASSERT(ref.value_);
152 if (!ref.value_)
return EINVAL;
153 ref.value_->common.Lock();
154 while (!IsReady_()) {
156 &ref.value_->common.lock,
157 datetime.ToTimeValue().tick);
159 ref.value_->common.Unlock();
163 ref.value_->common.Unlock();
170 template <
class Derived>
173 PromiseBase() NLIB_NOEXCEPT {}
174 #ifdef NLIB_CXX11_RVALUE_REFERENCES 175 PromiseBase(PromiseBase&& rhs) NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
179 bool IsValid() const NLIB_NOEXCEPT {
180 const Derived& ref =
static_cast<const Derived&
>(*this);
186 void swap(Derived& rhs) NLIB_NOEXCEPT {
188 Derived& ref =
static_cast<Derived&
>(*this);
189 swap(ref.value_, rhs.value_);
193 struct NLIB_CAPABILITY("mutex") CommonStatus {
195 detail::FutureContinuationBase* cont;
199 CommonStatus() NLIB_NOEXCEPT
200 : status(0), cont(NULL), err(0) {
204 NLIB_ASSERT_NOERR(e);
206 NLIB_ASSERT_NOERR(e);
208 ~CommonStatus() NLIB_NOEXCEPT {
209 if (cont)
delete cont;
213 NLIB_ASSERT_NOERR(e);
215 NLIB_ASSERT_NOERR(e);
217 void Lock() NLIB_NOEXCEPT NLIB_ACQUIRE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
221 NLIB_ASSERT_NOERR(e);
223 void Unlock() NLIB_NOEXCEPT NLIB_RELEASE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
227 NLIB_ASSERT_NOERR(e);
229 errno_t Wait() NLIB_NOEXCEPT NLIB_REQUIRES(*this) NLIB_NO_THREAD_SAFETY_ANALYSIS {
232 bool IsReady() NLIB_NOEXCEPT {
233 return status == 20120915L;
235 bool SetReady() NLIB_NOEXCEPT {
236 if (status != 20120915L) {
243 void NotifyAndContinuation() NLIB_NOEXCEPT {
246 NLIB_ASSERT_NOERR(e);
248 if (cont) cont->DoContinuation();
251 void NotifyAndContinuation() NLIB_NOEXCEPT {
252 static_cast<Derived&
>(*this).value_->common.NotifyAndContinuation();
259 template <
class Derived>
260 errno_t PromiseBase<Derived>::Init() NLIB_NOEXCEPT {
264 Derived& ref =
static_cast<Derived&
>(*this);
265 if (ref.value_)
return EALREADY;
266 ref.value_.reset(
new (std::nothrow)
typename Derived::Status());
267 if (!ref.value_)
return ENOMEM;
271 template <
class Derived>
273 if (e == 0)
return 0;
274 Derived& ref =
static_cast<Derived&
>(*this);
277 if (ee != 0)
return ee;
280 ref.value_->common.Lock();
281 if (ref.value_->common.SetReady()) {
282 ref.value_->common.err = e;
283 ref.value_->common.Unlock();
285 ref.value_->common.Unlock();
289 this->NotifyAndContinuation();
293 template <
class Derived>
295 errno_t PromiseBase<Derived>::GetFuture(F* p) NLIB_NOEXCEPT {
296 if (!p)
return EINVAL;
297 Derived& ref =
static_cast<Derived&
>(*this);
300 if (e != 0)
return e;
302 errno_t e = p->value_.MakeSharedFrom(ref.value_);
303 if (e != 0)
return e;
310 class Promise :
public detail::PromiseBase<Promise<R> > {
311 typedef detail::PromiseBase<Promise<R> > BaseType;
317 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
318 errno_t SetValue(
const R& value);
324 return BaseType::GetFuture(p);
330 typename BaseType::CommonStatus common;
333 LimitedSharedPtr<Status> value_;
338 friend class detail::PromiseBase;
345 if (e != 0)
return e;
349 if (value_->common.SetReady()) {
351 value_->data = value;
353 #ifdef NLIB_EXCEPTION_ENABLED 354 NLIB_RETHROW_UNWIND {
355 this->SetError(ECANCELED);
359 return this->SetError(EINVAL);
366 this->NotifyAndContinuation();
370 template <
class T,
class DEL>
371 class Promise<UniquePtr<T, DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
372 typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
376 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
381 typename BaseType::CommonStatus common;
384 LimitedSharedPtr<Status> value_;
389 friend class detail::PromiseBase;
392 template <
class T,
class DEL>
396 if (e != 0)
return e;
399 value_->common.Lock();
400 if (value_->common.SetReady()) {
401 value_->data.reset(value);
402 value_->common.Unlock();
404 value_->common.Unlock();
408 this->NotifyAndContinuation();
412 template <
class T,
class DEL>
413 class Promise<UniquePtr<T[], DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
414 typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
418 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
423 typename BaseType::CommonStatus common;
426 LimitedSharedPtr<Status> value_;
431 friend class detail::PromiseBase;
434 template <
class T,
class DEL>
438 if (e != 0)
return e;
441 value_->common.Lock();
442 if (value_->common.SetReady()) {
443 value_->data.reset(value);
444 value_->common.Unlock();
446 value_->common.Unlock();
450 this->NotifyAndContinuation();
455 class Promise<void> :
public detail::PromiseBase<Promise<void> > {
456 typedef detail::PromiseBase<Promise<void> > BaseType;
460 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
465 BaseType::CommonStatus common;
467 LimitedSharedPtr<Status> value_;
472 friend class detail::PromiseBase;
476 class Promise<Future<R> > :
public detail::PromiseBase<Promise<Future<R> > > {
477 typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
481 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
486 typename BaseType::CommonStatus common;
489 LimitedSharedPtr<Status> value_;
494 friend class detail::PromiseBase;
501 if (e != 0)
return e;
504 value_->common.Lock();
505 if (value_->common.SetReady()) {
506 errno_t e = value_->data.MakeSharedFrom(value);
507 value_->common.Unlock();
512 value_->common.Unlock();
516 this->NotifyAndContinuation();
521 class Future :
public detail::FutureBase<Future<R> > {
522 typedef detail::FutureBase<Future<R> > BaseType;
526 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
531 NLIB_ASSERT_NOERR(e);
535 if (!ptr)
return EINVAL;
537 errno_t e = value_->common.err;
542 #ifdef NLIB_EXCEPTION_ENABLED 543 NLIB_RETHROW_UNWIND {
552 bool IsValid() const NLIB_NOEXCEPT {
return BaseType::IsValid(); }
553 bool IsReady() const NLIB_NOEXCEPT {
return BaseType::IsReady(); }
556 return BaseType::WaitFor(span);
559 return BaseType::WaitUntil(datetime);
561 template <
class RNEXT>
563 return BaseType::Then(next, cont);
568 LimitedSharedPtr<typename Promise<R>::Status> value_;
573 friend class detail::FutureBase;
575 friend class detail::PromiseBase;
578 template <
class T,
class DEL>
579 class Future<UniquePtr<T, DEL> > :
public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
580 typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
583 Future() NLIB_NOEXCEPT {}
584 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
585 T* Get() NLIB_NOEXCEPT {
587 return value_->data.get();
589 errno_t Get(T** ptr) NLIB_NOEXCEPT {
590 if (!ptr)
return EINVAL;
592 errno_t e = value_->common.err;
593 if (e == 0) *ptr = value_->data.get();
596 T* Release() NLIB_NOEXCEPT {
598 return value_->data.release();
602 LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> value_;
607 friend class detail::FutureBase;
609 friend class detail::PromiseBase;
612 template <
class T,
class DEL>
613 class Future<UniquePtr<T[], DEL> > :
public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
614 typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
617 Future() NLIB_NOEXCEPT {}
618 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
619 T* Get() NLIB_NOEXCEPT {
621 return value_->data.get();
623 errno_t Get(T** ptr) NLIB_NOEXCEPT {
624 if (!ptr)
return EINVAL;
626 errno_t e = value_->common.err;
627 if (e == 0) *ptr = value_->data.get();
630 T* Release() NLIB_NOEXCEPT {
632 return value_->common.data.release();
636 LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> value_;
641 friend class detail::FutureBase;
643 friend class detail::PromiseBase;
647 class Future<void> :
public detail::FutureBase<Future<void> > {
648 typedef detail::FutureBase<Future<void> > BaseType;
651 Future() NLIB_NOEXCEPT {}
652 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
655 return value_->common.err;
659 LimitedSharedPtr<Promise<void>::Status> value_;
664 friend class detail::FutureBase;
666 friend class detail::PromiseBase;
670 class Future<Future<R> > :
public detail::FutureBase<Future<Future<R> > > {
671 typedef detail::FutureBase<Future<Future<R> > > BaseType;
674 Future() NLIB_NOEXCEPT {}
675 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
677 if (!inner)
return EINVAL;
679 errno_t e = value_->common.err;
680 if (e != 0)
return e;
685 LimitedSharedPtr<typename Promise<Future<R> >::Status> value_;
690 friend class detail::FutureBase;
692 friend class detail::PromiseBase;
698 class FuncHolderBase0 {
700 virtual ~FuncHolderBase0() {}
701 virtual R operator()() = 0;
704 template <
class R,
class T1>
705 class FuncHolderBase1 {
707 virtual ~FuncHolderBase1() {}
708 virtual R operator()(T1 NLIB_RREF arg1) = 0;
711 template <
class R,
class T1,
class T2>
712 class FuncHolderBase2 {
714 virtual ~FuncHolderBase2() {}
715 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0;
718 template <
class R,
class T1,
class T2,
class T3>
719 class FuncHolderBase3 {
721 virtual ~FuncHolderBase3() {}
722 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0;
725 template <
class R,
class T1,
class T2,
class T3,
class T4>
726 class FuncHolderBase4 {
728 virtual ~FuncHolderBase4() {}
729 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
730 T4 NLIB_RREF arg4) = 0;
733 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
734 class FuncHolderBase5 {
736 virtual ~FuncHolderBase5() {}
737 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
738 T5 NLIB_RREF arg5) = 0;
741 template <
class FUNC,
bool USESWAP>
748 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
755 template <
class FUNC>
756 class FuncWrap_<FUNC, false> {
758 FuncWrap_(FUNC& func) : func_(func) {}
759 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
766 template <
class FUNC>
767 class FuncWrap :
public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
768 typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
771 FuncWrap(FUNC& func) : BaseType(func) {}
775 class FuncWrap<R()> {
778 explicit FuncWrap(FUNC func) : func_(func) {}
779 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
786 template <
class R,
class T1>
787 class FuncWrap<R(T1)> {
789 typedef R (*FUNC)(T1);
790 explicit FuncWrap(FUNC func) : func_(func) {}
791 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
798 template <
class R,
class T1,
class T2>
799 class FuncWrap<R(T1, T2)> {
801 typedef R (*FUNC)(T1, T2);
802 explicit FuncWrap(FUNC func) : func_(func) {}
803 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
810 template <
class R,
class T1,
class T2,
class T3>
811 class FuncWrap<R(T1, T2, T3)> {
813 typedef R (*FUNC)(T1, T2, T3);
814 explicit FuncWrap(FUNC func) : func_(func) {}
815 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
822 template <
class R,
class T1,
class T2,
class T3,
class T4>
823 class FuncWrap<R(T1, T2, T3, T4)> {
825 typedef R (*FUNC)(T1, T2, T3, T4);
826 explicit FuncWrap(FUNC func) : func_(func) {}
827 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
834 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
835 class FuncWrap<R(T1, T2, T3, T4, T5)> {
837 typedef R (*FUNC)(T1, T2, T3, T4, T5);
838 explicit FuncWrap(FUNC func) : func_(func) {}
839 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
846 template <
class FUNC,
class R>
847 class FuncHolder0 :
public FuncHolderBase0<R> {
849 FuncHolder0(FUNC& f) : func_(f) {}
852 return func_.get()();
856 FuncWrap<FUNC> func_;
859 template <
class FUNC,
class R,
class T1>
860 class FuncHolder1 :
public FuncHolderBase1<R, T1> {
862 FuncHolder1(FUNC& f) : func_(f) {}
865 return func_.get()(NLIB_FWD(T1, arg1));
869 FuncWrap<FUNC> func_;
872 template <
class FUNC,
class R,
class T1,
class T2>
873 class FuncHolder2 :
public FuncHolderBase2<R, T1, T2> {
875 FuncHolder2(FUNC& f) : func_(f) {}
877 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)
NLIB_OVERRIDE {
878 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
882 FuncWrap<FUNC> func_;
885 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
886 class FuncHolder3 :
public FuncHolderBase3<R, T1, T2, T3> {
888 FuncHolder3(FUNC& f) : func_(f) {}
890 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)
NLIB_OVERRIDE {
891 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
895 FuncWrap<FUNC> func_;
898 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
899 class FuncHolder4 :
public FuncHolderBase4<R, T1, T2, T3, T4> {
901 FuncHolder4(FUNC& f) : func_(f) {}
903 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
905 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
910 FuncWrap<FUNC> func_;
913 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
914 class FuncHolder5 :
public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
916 FuncHolder5(FUNC& f) : func_(f) {}
918 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
920 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
921 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
925 FuncWrap<FUNC> func_;
935 template <class FUNC>
938 errno_t GetFuture(Future<R>* p) NLIB_NOEXCEPT;
945 typedef R ReturnType;
948 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
949 template <
class FUNC>
952 if (e != 0)
return e;
953 func_.reset(
new (std::nothrow) detail::FuncHolder0<FUNC, R>(func));
954 return !func_ ? ENOMEM : 0;
959 swap(func_, rhs.func_);
960 swap(promise_, rhs.promise_);
967 template <
class DUMMY>
968 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec() {
973 promise_.SetValue(rval);
975 promise_.SetError(e);
978 #ifdef NLIB_EXCEPTION_ENABLED 979 NLIB_RETHROW_UNWIND {
980 promise_.SetError(ECANCELED);
983 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
986 template <
class DUMMY>
987 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec() {
992 #ifdef NLIB_EXCEPTION_ENABLED 993 NLIB_RETHROW_UNWIND {
994 promise_.SetError(ECANCELED);
997 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1006 template <
class R,
class T1>
1009 typedef R ReturnType;
1012 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1013 template <
class FUNC>
1016 if (e != 0)
return e;
1017 func_.reset(
new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func));
1018 return !func_ ? ENOMEM : 0;
1023 swap(func_, rhs.func_);
1024 swap(promise_, rhs.promise_);
1026 void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1029 template <
class DUMMY>
1030 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(T1 NLIB_RREF arg1) {
1032 R rval = (*func_)(NLIB_FWD(T1, arg1));
1035 promise_.SetValue(rval);
1037 promise_.SetError(e);
1040 #ifdef NLIB_EXCEPTION_ENABLED 1041 NLIB_RETHROW_UNWIND {
1042 promise_.SetError(ECANCELED);
1045 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1048 template <
class DUMMY>
1049 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(T1 NLIB_RREF arg1) {
1051 (*func_)(NLIB_FWD(T1, arg1));
1052 promise_.SetValue();
1054 #ifdef NLIB_EXCEPTION_ENABLED 1055 NLIB_RETHROW_UNWIND {
1056 promise_.SetError(ECANCELED);
1059 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1068 template <
class R,
class T1,
class T2>
1071 typedef R ReturnType;
1074 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1075 template <
class FUNC>
1078 if (e != 0)
return e;
1079 func_.reset(
new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func));
1080 return !func_ ? ENOMEM : 0;
1085 swap(func_, rhs.func_);
1086 swap(promise_, rhs.promise_);
1088 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1089 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1093 template <
class DUMMY>
1094 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1095 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1097 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1100 promise_.SetValue(rval);
1102 promise_.SetError(e);
1105 #ifdef NLIB_EXCEPTION_ENABLED 1106 NLIB_RETHROW_UNWIND {
1107 promise_.SetError(ECANCELED);
1110 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1113 template <
class DUMMY>
1114 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1115 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1117 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1118 promise_.SetValue();
1120 #ifdef NLIB_EXCEPTION_ENABLED 1121 NLIB_RETHROW_UNWIND {
1122 promise_.SetError(ECANCELED);
1125 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1134 template <
class R,
class T1,
class T2,
class T3>
1137 typedef R ReturnType;
1140 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1141 template <
class FUNC>
1144 if (e != 0)
return e;
1145 func_.reset(
new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func));
1146 return !func_ ? ENOMEM : 0;
1151 swap(func_, rhs.func_);
1152 swap(promise_, rhs.promise_);
1154 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1155 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1159 template <
class DUMMY>
1160 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1161 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1163 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1166 promise_.SetValue(rval);
1168 promise_.SetError(e);
1171 #ifdef NLIB_EXCEPTION_ENABLED 1172 NLIB_RETHROW_UNWIND {
1173 promise_.SetError(ECANCELED);
1176 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1179 template <
class DUMMY>
1180 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1181 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1183 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1184 promise_.SetValue();
1186 #ifdef NLIB_EXCEPTION_ENABLED 1187 NLIB_RETHROW_UNWIND {
1188 promise_.SetError(ECANCELED);
1191 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1200 template <
class R,
class T1,
class T2,
class T3,
class T4>
1203 typedef R ReturnType;
1206 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1207 template <
class FUNC>
1210 if (e != 0)
return e;
1211 func_.reset(
new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func));
1212 return !func_ ? ENOMEM : 0;
1217 swap(func_, rhs.func_);
1218 swap(promise_, rhs.promise_);
1220 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1221 T4 NLIB_RREF arg4) {
1222 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1226 template <
class DUMMY>
1227 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1228 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1230 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1231 NLIB_FWD(T4, arg4));
1234 promise_.SetValue(rval);
1236 promise_.SetError(e);
1239 #ifdef NLIB_EXCEPTION_ENABLED 1240 NLIB_RETHROW_UNWIND {
1241 promise_.SetError(ECANCELED);
1244 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1247 template <
class DUMMY>
1248 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1249 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1251 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1252 NLIB_FWD(T4, arg4));
1253 promise_.SetValue();
1255 #ifdef NLIB_EXCEPTION_ENABLED 1256 NLIB_RETHROW_UNWIND {
1257 promise_.SetError(ECANCELED);
1260 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1269 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1272 typedef R ReturnType;
1275 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1276 template <
class FUNC>
1279 if (e != 0)
return e;
1280 func_.reset(
new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func));
1281 return !func_ ? ENOMEM : 0;
1286 swap(func_, rhs.func_);
1287 swap(promise_, rhs.promise_);
1289 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1290 T5 NLIB_RREF arg5) {
1291 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1292 NLIB_FWD(T5, arg5));
1296 template <
class DUMMY>
1297 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1298 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1299 T5 NLIB_RREF arg5) {
1301 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1302 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1305 promise_.SetValue(rval);
1307 promise_.SetError(e);
1310 #ifdef NLIB_EXCEPTION_ENABLED 1311 NLIB_RETHROW_UNWIND {
1312 promise_.SetError(ECANCELED);
1315 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1318 template <
class DUMMY>
1319 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1320 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1321 T5 NLIB_RREF arg5) {
1323 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1324 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1325 promise_.SetValue();
1327 #ifdef NLIB_EXCEPTION_ENABLED 1328 NLIB_RETHROW_UNWIND {
1329 promise_.SetError(ECANCELED);
1332 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1343 template <
class T,
bool B>
1345 explicit XHolder(
const T& value_) : value() {
1347 swap(const_cast<T&>(value_), value);
1353 struct XHolder<T, false> {
1354 explicit XHolder(
const T& value_) : value(value_) {}
1359 struct XHolder<R(), false> {
1360 XHolder(R (*value_)()) : value(value_) {}
1364 template <
class R,
class T1>
1365 struct XHolder<R(T1), false> {
1366 XHolder(R (*value_)(T1)) : value(value_) {}
1370 template <
class R,
class T1,
class T2>
1371 struct XHolder<R(T1, T2), false> {
1372 XHolder(R (*value_)(T1, T2)) : value(value_) {}
1376 template <
class R,
class T1,
class T2,
class T3>
1377 struct XHolder<R(T1, T2, T3), false> {
1378 XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1379 R (*value)(T1, T2, T3);
1382 template <
class R,
class T1,
class T2,
class T3,
class T4>
1383 struct XHolder<R(T1, T2, T3, T4), false> {
1384 XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1385 R (*value)(T1, T2, T3, T4);
1388 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1389 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1390 XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1391 R (*value)(T1, T2, T3, T4, T5);
1394 #define NLIB_ASYNC_HOLDER(T, B) \ 1395 XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value> 1396 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1397 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && !IsPointer<FUNC>::value> 1399 template <
class FUNC,
class R,
class BF>
1403 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1405 if (e != 0)
return e;
1407 if (e != 0)
return e;
1413 template <
class FUNC,
class R,
class BF,
class T1>
1418 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1420 if (e != 0)
return e;
1422 if (e != 0)
return e;
1424 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1429 template <
class FUNC,
class R,
class BF,
class T1,
class T2>
1430 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
1434 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1436 if (e != 0)
return e;
1438 if (e != 0)
return e;
1440 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1441 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1442 e = th.
Start(settings, task, arg1_.value, arg2_.value,
move_tag());
1446 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3>
1447 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1451 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1453 if (e != 0)
return e;
1455 if (e != 0)
return e;
1457 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1458 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1459 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1460 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value,
move_tag());
1464 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4>
1465 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1469 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1471 if (e != 0)
return e;
1473 if (e != 0)
return e;
1475 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1476 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1477 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1478 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1479 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value,
move_tag());
1483 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4,
class T5>
1484 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1485 const T4& arg4,
const T5& arg5,
const ThreadSettings& settings, BF) {
1488 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1490 if (e != 0)
return e;
1492 if (e != 0)
return e;
1494 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1495 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1496 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1497 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1498 NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1499 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1504 #undef NLIB_ASYNC_HOLDER 1505 #undef NLIB_ASYNC_HOLDER_F 1509 template <
class FUNC,
class R>
1511 return detail::Async_(future, func, settings, FalseType());
1514 template <
class FUNC,
class R>
1517 return detail::Async_(future, func, settings, TrueType());
1520 template <
class FUNC,
class R>
1524 return Async(future, func, settings);
1527 template <
class FUNC,
class R>
1534 template <
class FUNC,
class R,
class T1>
1537 return detail::Async_(future, func, arg1, settings, FalseType());
1540 template <
class FUNC,
class R,
class T1>
1543 return detail::Async_(future, func, arg1, settings, TrueType());
1546 template <
class FUNC,
class R,
class T1>
1550 return Async(future, func, arg1, settings);
1553 template <
class FUNC,
class R,
class T1>
1560 template <
class FUNC,
class R,
class T1,
class T2>
1563 return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1566 template <
class FUNC,
class R,
class T1,
class T2>
1569 return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1572 template <
class FUNC,
class R,
class T1,
class T2>
1576 return Async(future, func, arg1, arg2, settings);
1579 template <
class FUNC,
class R,
class T1,
class T2>
1584 return Async(future, func, arg1, arg2, settings,
move_tag());
1587 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1590 return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1593 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1596 return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1599 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1604 return Async(future, func, arg1, arg2, arg3, settings);
1607 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1612 return Async(future, func, arg1, arg2, arg3, settings,
move_tag());
1615 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1617 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings) {
1618 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1621 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1624 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1627 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1629 const T3& arg3,
const T4& arg4) {
1632 return Async(future, func, arg1, arg2, arg3, arg4, settings);
1635 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1637 const T3& arg3,
const T4& arg4,
move_tag) {
1640 return Async(future, func, arg1, arg2, arg3, arg4, settings,
move_tag());
1643 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1645 const T3& arg3,
const T4& arg4,
const T5& arg5,
1647 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1650 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1652 const T3& arg3,
const T4& arg4,
const T5& arg5,
const ThreadSettings& settings,
1654 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1657 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1659 const T3& arg3,
const T4& arg4,
const T5& arg5) {
1662 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1665 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1667 const T3& arg3,
const T4& arg4,
const T5& arg5,
move_tag) {
1670 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings,
move_tag());
1675 if (!future)
return EINVAL;
1678 if (e != 0)
return e;
1680 if (e != 0)
return e;
1682 if (e != 0)
return e;
1687 template <
class FUTURE,
class R,
typename CONT>
1688 class FutureContinuation :
public FutureContinuationBase {
1690 FutureContinuation(FUTURE& f, CONT cont) NLIB_NOEXCEPT
1694 errno_t Init() NLIB_NOEXCEPT {
return next_.Init(); }
1695 errno_t GetFuture(
Future<R>* future) NLIB_NOEXCEPT {
return next_.GetFuture(future); }
1696 virtual ~FutureContinuation() NLIB_NOEXCEPT
NLIB_OVERRIDE {}
1706 template <
class FUTURE,
class R,
typename CONT>
1707 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
1708 int32_t expected = 0;
1712 R rval = func_(parent_);
1715 (void)next_.SetValue(rval);
1717 (void)next_.SetError(e);
1720 #ifdef NLIB_EXCEPTION_ENABLED 1721 NLIB_RETHROW_UNWIND {
1722 next_.SetError(ECANCELED);
1725 NLIB_CATCH(...) { (void)next_.SetError(EINVAL); }
1730 template <
class Derived>
1732 errno_t FutureBase<Derived>::Then(
Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT {
1733 Derived& ref =
static_cast<Derived&
>(*this);
1734 if (!ref.value_)
return EINVAL;
1736 typedef R (*CONT)(Derived&);
1738 new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
1739 if (!ptr)
return ENOMEM;
1741 if (e != 0)
return e;
1742 e = ptr->GetFuture(next);
1743 if (e != 0)
return e;
1745 ref.value_->common.Lock();
1746 ref.value_->common.cont = ptr.release();
1747 bool isready = ref.IsReady_();
1748 ref.value_->common.Unlock();
1750 ref.value_->common.cont->DoContinuation();
1757 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
1758 struct FutureTuple {
1767 struct FutureTuple<None, None, None, None, None>;
1769 struct FutureTuple<R1, None, None, None, None>;
1771 template <
class R1,
class R2>
1772 struct FutureTuple<R1, R2, None, None, None> {
1777 template <
class R1,
class R2,
class R3>
1778 struct FutureTuple<R1, R2, R3, None, None> {
1784 template <
class R1,
class R2,
class R3,
class R4>
1785 struct FutureTuple<R1, R2, R3, R4, None> {
1792 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
1799 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
1803 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
1808 typedef void (*FuncType)(ArgType& ptr);
1811 static void Call(ArgType& ptr) {
1815 static void CallWhenAny(ArgType& ptr) {
1817 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
1818 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady() ||
1819 ptr->tuple_->f5.IsReady()) {
1824 ptr->promise_.SetValue(ptr->tuple_.
release());
1826 static void CallWhenAll(ArgType& ptr) {
1827 ptr->tuple_->f1.Wait();
1828 ptr->tuple_->f2.Wait();
1829 ptr->tuple_->f3.Wait();
1830 ptr->tuple_->f4.Wait();
1831 ptr->tuple_->f5.Wait();
1832 ptr->promise_.SetValue(ptr->tuple_.
release());
1838 if (e != 0)
return e;
1839 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
1840 if (!tuple_)
return ENOMEM;
1841 e = promise_.GetFuture(f);
1842 if (e != 0)
return e;
1843 e = tuple_->f1.MakeSharedFrom(*f1);
1844 if (e != 0)
return e;
1845 e = tuple_->f2.MakeSharedFrom(*f2);
1846 if (e != 0)
return e;
1847 e = tuple_->f3.MakeSharedFrom(*f3);
1848 if (e != 0)
return e;
1849 e = tuple_->f4.MakeSharedFrom(*f4);
1850 if (e != 0)
return e;
1851 e = tuple_->f5.MakeSharedFrom(*f5);
1852 if (e != 0)
return e;
1864 template <
class R1,
class R2,
class R3,
class R4,
class R5>
1869 if (!f1 || !f2 || !f3 || !f4 || !f5)
return EINVAL;
1873 e = ptr->Init(f, f1, f2, f3, f4, f5);
1874 if (e != 0)
return e;
1877 if (e != 0)
return e;
1886 template <
class R1,
class R2>
1892 return DoWhen(f, f1, f2, CallWhenAll);
1895 return DoWhen(f, f1, f2, CallWhenAny);
1900 typedef void (*FuncType)(ArgType& ptr);
1902 static void Call(ArgType& ptr) {
1906 static void CallWhenAny(ArgType& ptr) {
1908 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady()) {
1913 ptr->promise_.SetValue(ptr->tuple_.
release());
1915 static void CallWhenAll(ArgType& ptr) {
1916 ptr->tuple_->f1.Wait();
1917 ptr->tuple_->f2.Wait();
1918 ptr->promise_.SetValue(ptr->tuple_.
release());
1923 if (e != 0)
return e;
1924 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2>());
1925 if (!tuple_)
return ENOMEM;
1926 e = promise_.GetFuture(f);
1927 if (e != 0)
return e;
1928 e = tuple_->f1.MakeSharedFrom(*f1);
1929 if (e != 0)
return e;
1930 e = tuple_->f2.MakeSharedFrom(*f2);
1931 if (e != 0)
return e;
1943 template <
class R1,
class R2>
1946 if (!f1 || !f2)
return EINVAL;
1950 e = ptr->Init(f, f1, f2);
1951 if (e != 0)
return e;
1954 if (e != 0)
return e;
1958 template <
class R1,
class R2,
class R3>
1964 return DoWhen(f, f1, f2, f3, CallWhenAll);
1967 return DoWhen(f, f1, f2, f3, CallWhenAny);
1972 typedef void (*FuncType)(ArgType& ptr);
1975 static void Call(ArgType& ptr) {
1979 static void CallWhenAny(ArgType& ptr) {
1981 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
1982 ptr->tuple_->f3.IsReady()) {
1987 ptr->promise_.SetValue(ptr->tuple_.
release());
1989 static void CallWhenAll(ArgType& ptr) {
1990 ptr->tuple_->f1.Wait();
1991 ptr->tuple_->f2.Wait();
1992 ptr->tuple_->f3.Wait();
1993 ptr->promise_.SetValue(ptr->tuple_.
release());
1998 if (e != 0)
return e;
1999 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3>());
2000 if (!tuple_)
return ENOMEM;
2001 e = promise_.GetFuture(f);
2002 if (e != 0)
return e;
2003 e = tuple_->f1.MakeSharedFrom(*f1);
2004 if (e != 0)
return e;
2005 e = tuple_->f2.MakeSharedFrom(*f2);
2006 if (e != 0)
return e;
2007 e = tuple_->f3.MakeSharedFrom(*f3);
2008 if (e != 0)
return e;
2020 template <
class R1,
class R2,
class R3>
2023 if (!f1 || !f2 || !f3)
return EINVAL;
2027 e = ptr->Init(f, f1, f2, f3);
2028 if (e != 0)
return e;
2031 if (e != 0)
return e;
2035 template <
class R1,
class R2,
class R3,
class R4>
2042 return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2046 return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2051 typedef void (*FuncType)(ArgType& ptr);
2054 static void Call(ArgType& ptr) {
2058 static void CallWhenAny(ArgType& ptr) {
2060 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2061 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady()) {
2066 ptr->promise_.SetValue(ptr->tuple_.
release());
2068 static void CallWhenAll(ArgType& ptr) {
2069 ptr->tuple_->f1.Wait();
2070 ptr->tuple_->f2.Wait();
2071 ptr->tuple_->f3.Wait();
2072 ptr->tuple_->f4.Wait();
2073 ptr->promise_.SetValue(ptr->tuple_.
release());
2079 if (e != 0)
return e;
2080 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2081 if (!tuple_)
return ENOMEM;
2082 e = promise_.GetFuture(f);
2083 if (e != 0)
return e;
2084 e = tuple_->f1.MakeSharedFrom(*f1);
2085 if (e != 0)
return e;
2086 e = tuple_->f2.MakeSharedFrom(*f2);
2087 if (e != 0)
return e;
2088 e = tuple_->f3.MakeSharedFrom(*f3);
2089 if (e != 0)
return e;
2090 e = tuple_->f4.MakeSharedFrom(*f4);
2091 if (e != 0)
return e;
2103 template <
class R1,
class R2,
class R3,
class R4>
2106 if (!f1 || !f2 || !f3 || !f4)
return EINVAL;
2110 e = ptr->Init(f, f1, f2, f3, f4);
2111 if (e != 0)
return e;
2114 if (e != 0)
return e;
2121 #ifndef NLIB_STD_SWAP_WORKAROUND 2122 NLIB_NAMESPACE_BEGIN
2125 NLIB_DEFINE_STD_SWAP_T_BEGIN1(threading)
2126 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise)
2127 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask)
2128 NLIB_DEFINE_STD_SWAP_T_END1(threading)
2130 #ifndef NLIB_STD_SWAP_WORKAROUND 2134 #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.
void swap(Promise &rhs) noexcept
Swaps an object.
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.
Class to create and start threads.
NLIB_CHECK_RESULT 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.
The class for representing the date and time.
bool IsValid() const noexcept
NLIB_CHECK_RESULT 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).
errno_t Init() noexcept
Initializes the object.
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.