3 #ifndef INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 4 #define INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 6 #include "nn/nlib/Swap.h" 11 #include "nn/nlib/threading/LimitedSharedPtr.h" 19 template <
class FutureResult>
36 virtual void DoContinuation() {}
42 template <
class FUTURE,
class R,
typename CONT>
43 class FutureContinuation;
45 template <
class Derived>
49 #ifdef NLIB_CXX11_RVALUE_REFERENCES 50 FutureBase(FutureBase&& rhs)
NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
55 bool IsValid() const NLIB_NOEXCEPT {
56 const Derived& ref =
static_cast<const Derived&
>(*this);
61 Derived& ref =
static_cast<Derived&
>(*this);
62 return ref.value_.MakeSharedFrom(f.value_);
66 void swap(Derived& rhs) NLIB_NOEXCEPT {
67 static_cast<Derived&
>(*this).value_.swap(rhs.value_);
71 bool IsReady_() const NLIB_NOEXCEPT {
72 return static_cast<const Derived&
>(*this).value_->common.IsReady();
76 template <
class Derived>
77 bool FutureBase<Derived>::IsReady() const NLIB_NOEXCEPT {
78 const Derived& ref =
static_cast<const Derived&
>(*this);
80 ref.value_->common.Lock();
81 bool rval = IsReady_();
82 ref.value_->common.Unlock();
89 template <
class Derived>
90 errno_t FutureBase<Derived>::Wait() NLIB_NOEXCEPT {
91 Derived& ref =
static_cast<Derived&
>(*this);
92 NLIB_ASSERT(ref.value_);
93 if (!ref.value_)
return EINVAL;
94 ref.value_->common.Lock();
96 errno_t e = ref.value_->common.Wait();
98 ref.value_->common.Unlock();
103 ref.value_->common.Unlock();
107 template <
class Derived>
108 errno_t FutureBase<Derived>::WaitFor(
const TimeSpan& span) NLIB_NOEXCEPT {
109 Derived& ref =
static_cast<Derived&
>(*this);
110 NLIB_ASSERT(ref.value_);
111 if (!ref.value_)
return EINVAL;
113 errno_t e = DateTime::GetNow(&abstime);
115 if (e != 0)
return e;
116 ref.value_->common.Lock();
117 while (!IsReady_()) {
124 &ref.value_->common.lock,
127 ref.value_->common.Unlock();
131 ref.value_->common.Unlock();
135 template <
class Derived>
136 errno_t FutureBase<Derived>::WaitUntil(
const DateTime& datetime) NLIB_NOEXCEPT {
137 Derived& ref =
static_cast<Derived&
>(*this);
138 NLIB_ASSERT(ref.value_);
139 if (!ref.value_)
return EINVAL;
140 ref.value_->common.Lock();
141 while (!IsReady_()) {
143 &ref.value_->common.lock,
144 datetime.ToTimeValue().tick);
146 ref.value_->common.Unlock();
150 ref.value_->common.Unlock();
157 template <
class Derived>
160 PromiseBase() NLIB_NOEXCEPT {}
161 #ifdef NLIB_CXX11_RVALUE_REFERENCES 162 PromiseBase(PromiseBase&& rhs) NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
166 bool IsValid() const NLIB_NOEXCEPT {
167 const Derived& ref =
static_cast<const Derived&
>(*this);
173 void swap(Derived& rhs) NLIB_NOEXCEPT {
175 Derived& ref =
static_cast<Derived&
>(*this);
176 swap(ref.value_, rhs.value_);
180 struct NLIB_CAPABILITY("mutex") CommonStatus {
182 detail::FutureContinuationBase* cont;
186 CommonStatus() NLIB_NOEXCEPT
187 : status(0), cont(NULL), err(0) {
191 NLIB_ASSERT_NOERR(e);
193 NLIB_ASSERT_NOERR(e);
195 ~CommonStatus() NLIB_NOEXCEPT {
196 if (cont)
delete cont;
200 NLIB_ASSERT_NOERR(e);
202 NLIB_ASSERT_NOERR(e);
204 void Lock() NLIB_NOEXCEPT NLIB_ACQUIRE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
208 NLIB_ASSERT_NOERR(e);
210 void Unlock() NLIB_NOEXCEPT NLIB_RELEASE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
214 NLIB_ASSERT_NOERR(e);
216 errno_t Wait() NLIB_NOEXCEPT NLIB_REQUIRES(*this) NLIB_NO_THREAD_SAFETY_ANALYSIS {
219 bool IsReady() NLIB_NOEXCEPT {
220 return status == 20120915L;
222 bool SetReady() NLIB_NOEXCEPT {
223 if (status != 20120915L) {
230 void NotifyAndContinuation() NLIB_NOEXCEPT {
233 NLIB_ASSERT_NOERR(e);
235 if (cont) cont->DoContinuation();
238 void NotifyAndContinuation() NLIB_NOEXCEPT {
239 static_cast<Derived&
>(*this).value_->common.NotifyAndContinuation();
246 template <
class Derived>
247 errno_t PromiseBase<Derived>::Init() NLIB_NOEXCEPT {
251 Derived& ref =
static_cast<Derived&
>(*this);
252 if (ref.value_)
return EALREADY;
253 ref.value_.reset(
new (std::nothrow)
typename Derived::Status());
254 if (!ref.value_)
return ENOMEM;
258 template <
class Derived>
260 if (e == 0)
return 0;
261 Derived& ref =
static_cast<Derived&
>(*this);
264 if (ee != 0)
return ee;
267 ref.value_->common.Lock();
268 if (ref.value_->common.SetReady()) {
269 ref.value_->common.err = e;
270 ref.value_->common.Unlock();
272 ref.value_->common.Unlock();
276 this->NotifyAndContinuation();
280 template <
class Derived>
282 errno_t PromiseBase<Derived>::GetFuture(F* p) NLIB_NOEXCEPT {
283 if (!p)
return EINVAL;
284 Derived& ref =
static_cast<Derived&
>(*this);
287 if (e != 0)
return e;
289 errno_t e = p->value_.MakeSharedFrom(ref.value_);
290 if (e != 0)
return e;
297 class Promise :
public detail::PromiseBase<Promise<R> > {
298 typedef detail::PromiseBase<Promise<R> > BaseType;
304 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
305 errno_t SetValue(
const R& value);
311 return BaseType::GetFuture(p);
317 typename BaseType::CommonStatus common;
320 LimitedSharedPtr<Status> value_;
325 friend class detail::PromiseBase;
332 if (e != 0)
return e;
336 if (value_->common.SetReady()) {
338 value_->data = value;
340 #ifdef NLIB_EXCEPTION_ENABLED 341 NLIB_RETHROW_UNWIND {
342 this->SetError(ECANCELED);
346 return this->SetError(EINVAL);
353 this->NotifyAndContinuation();
357 template <
class T,
class DEL>
358 class Promise<UniquePtr<T, DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
359 typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
363 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
368 typename BaseType::CommonStatus common;
371 LimitedSharedPtr<Status> value_;
376 friend class detail::PromiseBase;
379 template <
class T,
class DEL>
383 if (e != 0)
return e;
386 value_->common.Lock();
387 if (value_->common.SetReady()) {
388 value_->data.reset(value);
389 value_->common.Unlock();
391 value_->common.Unlock();
395 this->NotifyAndContinuation();
399 template <
class T,
class DEL>
400 class Promise<UniquePtr<T[], DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
401 typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
405 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
410 typename BaseType::CommonStatus common;
413 LimitedSharedPtr<Status> value_;
418 friend class detail::PromiseBase;
421 template <
class T,
class DEL>
425 if (e != 0)
return e;
428 value_->common.Lock();
429 if (value_->common.SetReady()) {
430 value_->data.reset(value);
431 value_->common.Unlock();
433 value_->common.Unlock();
437 this->NotifyAndContinuation();
442 class Promise<void> :
public detail::PromiseBase<Promise<void> > {
443 typedef detail::PromiseBase<Promise<void> > BaseType;
447 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
452 BaseType::CommonStatus common;
454 LimitedSharedPtr<Status> value_;
459 friend class detail::PromiseBase;
463 class Promise<Future<R> > :
public detail::PromiseBase<Promise<Future<R> > > {
464 typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
468 NLIB_MOVE_MEMBER_HELPER_1(
Promise, value_)
473 typename BaseType::CommonStatus common;
476 LimitedSharedPtr<Status> value_;
481 friend class detail::PromiseBase;
488 if (e != 0)
return e;
491 value_->common.Lock();
492 if (value_->common.SetReady()) {
493 errno_t e = value_->data.MakeSharedFrom(value);
494 value_->common.Unlock();
499 value_->common.Unlock();
503 this->NotifyAndContinuation();
508 class Future :
public detail::FutureBase<Future<R> > {
509 typedef detail::FutureBase<Future<R> > BaseType;
513 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
518 NLIB_ASSERT_NOERR(e);
522 if (!ptr)
return EINVAL;
524 errno_t e = value_->common.err;
529 #ifdef NLIB_EXCEPTION_ENABLED 530 NLIB_RETHROW_UNWIND {
539 bool IsValid() const NLIB_NOEXCEPT {
return BaseType::IsValid(); }
540 bool IsReady() const NLIB_NOEXCEPT {
return BaseType::IsReady(); }
543 return BaseType::WaitFor(span);
546 return BaseType::WaitUntil(datetime);
548 template <
class RNEXT>
550 return BaseType::Then(next, cont);
555 LimitedSharedPtr<typename Promise<R>::Status> value_;
560 friend class detail::FutureBase;
562 friend class detail::PromiseBase;
565 template <
class T,
class DEL>
566 class Future<UniquePtr<T, DEL> > :
public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
567 typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
570 Future() NLIB_NOEXCEPT {}
571 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
572 T* Get() NLIB_NOEXCEPT {
574 return value_->data.get();
576 errno_t Get(T** ptr) NLIB_NOEXCEPT {
577 if (!ptr)
return EINVAL;
579 errno_t e = value_->common.err;
580 if (e == 0) *ptr = value_->data.get();
583 T* Release() NLIB_NOEXCEPT {
585 return value_->data.release();
589 LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> value_;
594 friend class detail::FutureBase;
596 friend class detail::PromiseBase;
599 template <
class T,
class DEL>
600 class Future<UniquePtr<T[], DEL> > :
public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
601 typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
604 Future() NLIB_NOEXCEPT {}
605 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
606 T* Get() NLIB_NOEXCEPT {
608 return value_->data.get();
610 errno_t Get(T** ptr) NLIB_NOEXCEPT {
611 if (!ptr)
return EINVAL;
613 errno_t e = value_->common.err;
614 if (e == 0) *ptr = value_->data.get();
617 T* Release() NLIB_NOEXCEPT {
619 return value_->common.data.release();
623 LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> value_;
628 friend class detail::FutureBase;
630 friend class detail::PromiseBase;
634 class Future<void> :
public detail::FutureBase<Future<void> > {
635 typedef detail::FutureBase<Future<void> > BaseType;
638 Future() NLIB_NOEXCEPT {}
639 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
642 return value_->common.err;
646 LimitedSharedPtr<Promise<void>::Status> value_;
651 friend class detail::FutureBase;
653 friend class detail::PromiseBase;
657 class Future<Future<R> > :
public detail::FutureBase<Future<Future<R> > > {
658 typedef detail::FutureBase<Future<Future<R> > > BaseType;
661 Future() NLIB_NOEXCEPT {}
662 NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
664 if (!inner)
return EINVAL;
666 errno_t e = value_->common.err;
667 if (e != 0)
return e;
672 LimitedSharedPtr<typename Promise<Future<R> >::Status> value_;
677 friend class detail::FutureBase;
679 friend class detail::PromiseBase;
685 class FuncHolderBase0 {
687 virtual ~FuncHolderBase0() {}
688 virtual R operator()() = 0;
691 template <
class R,
class T1>
692 class FuncHolderBase1 {
694 virtual ~FuncHolderBase1() {}
695 virtual R operator()(T1 NLIB_RREF arg1) = 0;
698 template <
class R,
class T1,
class T2>
699 class FuncHolderBase2 {
701 virtual ~FuncHolderBase2() {}
702 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0;
705 template <
class R,
class T1,
class T2,
class T3>
706 class FuncHolderBase3 {
708 virtual ~FuncHolderBase3() {}
709 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0;
712 template <
class R,
class T1,
class T2,
class T3,
class T4>
713 class FuncHolderBase4 {
715 virtual ~FuncHolderBase4() {}
716 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
717 T4 NLIB_RREF arg4) = 0;
720 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
721 class FuncHolderBase5 {
723 virtual ~FuncHolderBase5() {}
724 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
725 T5 NLIB_RREF arg5) = 0;
728 template <
class FUNC,
bool USESWAP>
731 FuncWrap_(FUNC& func) NLIB_NOEXCEPT : func_() {
735 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
742 template <
class FUNC>
743 class FuncWrap_<FUNC, false> {
745 FuncWrap_(FUNC& func) : func_(func) {}
746 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
753 template <
class FUNC>
754 class FuncWrap :
public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
755 typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
758 FuncWrap(FUNC& func) : BaseType(func) {}
762 class FuncWrap<R()> {
765 explicit FuncWrap(FUNC func) : func_(func) {}
766 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
773 template <
class R,
class T1>
774 class FuncWrap<R(T1)> {
776 typedef R (*FUNC)(T1);
777 explicit FuncWrap(FUNC func) : func_(func) {}
778 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
785 template <
class R,
class T1,
class T2>
786 class FuncWrap<R(T1, T2)> {
788 typedef R (*FUNC)(T1, T2);
789 explicit FuncWrap(FUNC func) : func_(func) {}
790 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
797 template <
class R,
class T1,
class T2,
class T3>
798 class FuncWrap<R(T1, T2, T3)> {
800 typedef R (*FUNC)(T1, T2, T3);
801 explicit FuncWrap(FUNC func) : func_(func) {}
802 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
809 template <
class R,
class T1,
class T2,
class T3,
class T4>
810 class FuncWrap<R(T1, T2, T3, T4)> {
812 typedef R (*FUNC)(T1, T2, T3, T4);
813 explicit FuncWrap(FUNC func) : func_(func) {}
814 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
821 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
822 class FuncWrap<R(T1, T2, T3, T4, T5)> {
824 typedef R (*FUNC)(T1, T2, T3, T4, T5);
825 explicit FuncWrap(FUNC func) : func_(func) {}
826 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
833 template <
class FUNC,
class R>
834 class FuncHolder0 :
public FuncHolderBase0<R> {
836 FuncHolder0(FUNC& f) : func_(f) {}
839 return func_.get()();
843 FuncWrap<FUNC> func_;
846 template <
class FUNC,
class R,
class T1>
847 class FuncHolder1 :
public FuncHolderBase1<R, T1> {
849 FuncHolder1(FUNC& f) : func_(f) {}
852 return func_.get()(NLIB_FWD(T1, arg1));
856 FuncWrap<FUNC> func_;
859 template <
class FUNC,
class R,
class T1,
class T2>
860 class FuncHolder2 :
public FuncHolderBase2<R, T1, T2> {
862 FuncHolder2(FUNC& f) : func_(f) {}
864 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)
NLIB_OVERRIDE {
865 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
869 FuncWrap<FUNC> func_;
872 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
873 class FuncHolder3 :
public FuncHolderBase3<R, T1, T2, T3> {
875 FuncHolder3(FUNC& f) : func_(f) {}
877 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)
NLIB_OVERRIDE {
878 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
882 FuncWrap<FUNC> func_;
885 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
886 class FuncHolder4 :
public FuncHolderBase4<R, T1, T2, T3, T4> {
888 FuncHolder4(FUNC& f) : func_(f) {}
890 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
892 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
897 FuncWrap<FUNC> func_;
900 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
901 class FuncHolder5 :
public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
903 FuncHolder5(FUNC& f) : func_(f) {}
905 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
907 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
908 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
912 FuncWrap<FUNC> func_;
922 template <class FUNC>
925 errno_t GetFuture(Future<R>* p) NLIB_NOEXCEPT;
932 typedef R ReturnType;
935 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
936 template <
class FUNC>
939 if (e != 0)
return e;
940 func_.reset(
new (std::nothrow) detail::FuncHolder0<FUNC, R>(func));
941 return !func_ ? ENOMEM : 0;
946 swap(func_, rhs.func_);
947 swap(promise_, rhs.promise_);
954 template <
class DUMMY>
955 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec() {
960 promise_.SetValue(rval);
962 promise_.SetError(e);
965 #ifdef NLIB_EXCEPTION_ENABLED 966 NLIB_RETHROW_UNWIND {
967 promise_.SetError(ECANCELED);
970 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
973 template <
class DUMMY>
974 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec() {
979 #ifdef NLIB_EXCEPTION_ENABLED 980 NLIB_RETHROW_UNWIND {
981 promise_.SetError(ECANCELED);
984 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
993 template <
class R,
class T1>
996 typedef R ReturnType;
999 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1000 template <
class FUNC>
1003 if (e != 0)
return e;
1004 func_.reset(
new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func));
1005 return !func_ ? ENOMEM : 0;
1010 swap(func_, rhs.func_);
1011 swap(promise_, rhs.promise_);
1013 void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1016 template <
class DUMMY>
1017 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(T1 NLIB_RREF arg1) {
1019 R rval = (*func_)(NLIB_FWD(T1, arg1));
1022 promise_.SetValue(rval);
1024 promise_.SetError(e);
1027 #ifdef NLIB_EXCEPTION_ENABLED 1028 NLIB_RETHROW_UNWIND {
1029 promise_.SetError(ECANCELED);
1032 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1035 template <
class DUMMY>
1036 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(T1 NLIB_RREF arg1) {
1038 (*func_)(NLIB_FWD(T1, arg1));
1039 promise_.SetValue();
1041 #ifdef NLIB_EXCEPTION_ENABLED 1042 NLIB_RETHROW_UNWIND {
1043 promise_.SetError(ECANCELED);
1046 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1055 template <
class R,
class T1,
class T2>
1058 typedef R ReturnType;
1061 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1062 template <
class FUNC>
1065 if (e != 0)
return e;
1066 func_.reset(
new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func));
1067 return !func_ ? ENOMEM : 0;
1072 swap(func_, rhs.func_);
1073 swap(promise_, rhs.promise_);
1075 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1076 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1080 template <
class DUMMY>
1081 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1082 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1084 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1087 promise_.SetValue(rval);
1089 promise_.SetError(e);
1092 #ifdef NLIB_EXCEPTION_ENABLED 1093 NLIB_RETHROW_UNWIND {
1094 promise_.SetError(ECANCELED);
1097 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1100 template <
class DUMMY>
1101 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1102 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1104 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1105 promise_.SetValue();
1107 #ifdef NLIB_EXCEPTION_ENABLED 1108 NLIB_RETHROW_UNWIND {
1109 promise_.SetError(ECANCELED);
1112 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1121 template <
class R,
class T1,
class T2,
class T3>
1124 typedef R ReturnType;
1127 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1128 template <
class FUNC>
1131 if (e != 0)
return e;
1132 func_.reset(
new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func));
1133 return !func_ ? ENOMEM : 0;
1138 swap(func_, rhs.func_);
1139 swap(promise_, rhs.promise_);
1141 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1142 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1146 template <
class DUMMY>
1147 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1148 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1150 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1153 promise_.SetValue(rval);
1155 promise_.SetError(e);
1158 #ifdef NLIB_EXCEPTION_ENABLED 1159 NLIB_RETHROW_UNWIND {
1160 promise_.SetError(ECANCELED);
1163 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1166 template <
class DUMMY>
1167 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1168 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1170 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1171 promise_.SetValue();
1173 #ifdef NLIB_EXCEPTION_ENABLED 1174 NLIB_RETHROW_UNWIND {
1175 promise_.SetError(ECANCELED);
1178 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1187 template <
class R,
class T1,
class T2,
class T3,
class T4>
1190 typedef R ReturnType;
1193 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1194 template <
class FUNC>
1197 if (e != 0)
return e;
1198 func_.reset(
new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func));
1199 return !func_ ? ENOMEM : 0;
1204 swap(func_, rhs.func_);
1205 swap(promise_, rhs.promise_);
1207 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1208 T4 NLIB_RREF arg4) {
1209 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1213 template <
class DUMMY>
1214 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1215 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1217 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1218 NLIB_FWD(T4, arg4));
1221 promise_.SetValue(rval);
1223 promise_.SetError(e);
1226 #ifdef NLIB_EXCEPTION_ENABLED 1227 NLIB_RETHROW_UNWIND {
1228 promise_.SetError(ECANCELED);
1231 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1234 template <
class DUMMY>
1235 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1236 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1238 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1239 NLIB_FWD(T4, arg4));
1240 promise_.SetValue();
1242 #ifdef NLIB_EXCEPTION_ENABLED 1243 NLIB_RETHROW_UNWIND {
1244 promise_.SetError(ECANCELED);
1247 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1256 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1259 typedef R ReturnType;
1262 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, func_, promise_)
1263 template <
class FUNC>
1266 if (e != 0)
return e;
1267 func_.reset(
new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func));
1268 return !func_ ? ENOMEM : 0;
1273 swap(func_, rhs.func_);
1274 swap(promise_, rhs.promise_);
1276 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1277 T5 NLIB_RREF arg5) {
1278 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1279 NLIB_FWD(T5, arg5));
1283 template <
class DUMMY>
1284 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1285 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1286 T5 NLIB_RREF arg5) {
1288 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1289 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1292 promise_.SetValue(rval);
1294 promise_.SetError(e);
1297 #ifdef NLIB_EXCEPTION_ENABLED 1298 NLIB_RETHROW_UNWIND {
1299 promise_.SetError(ECANCELED);
1302 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1305 template <
class DUMMY>
1306 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1307 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1308 T5 NLIB_RREF arg5) {
1310 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1311 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1312 promise_.SetValue();
1314 #ifdef NLIB_EXCEPTION_ENABLED 1315 NLIB_RETHROW_UNWIND {
1316 promise_.SetError(ECANCELED);
1319 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1330 template <
class T,
bool B>
1332 explicit XHolder(
const T& value_) : value() {
1334 swap(const_cast<T&>(value_), value);
1340 struct XHolder<T, false> {
1341 explicit XHolder(
const T& value_) : value(value_) {}
1346 struct XHolder<R(), false> {
1347 XHolder(R (*value_)()) : value(value_) {}
1351 template <
class R,
class T1>
1352 struct XHolder<R(T1), false> {
1353 XHolder(R (*value_)(T1)) : value(value_) {}
1357 template <
class R,
class T1,
class T2>
1358 struct XHolder<R(T1, T2), false> {
1359 XHolder(R (*value_)(T1, T2)) : value(value_) {}
1363 template <
class R,
class T1,
class T2,
class T3>
1364 struct XHolder<R(T1, T2, T3), false> {
1365 XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1366 R (*value)(T1, T2, T3);
1369 template <
class R,
class T1,
class T2,
class T3,
class T4>
1370 struct XHolder<R(T1, T2, T3, T4), false> {
1371 XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1372 R (*value)(T1, T2, T3, T4);
1375 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1376 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1377 XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1378 R (*value)(T1, T2, T3, T4, T5);
1381 #define NLIB_ASYNC_HOLDER(T, B) \ 1382 XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value> 1383 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1384 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && !IsPointer<FUNC>::value> 1386 template <
class FUNC,
class R,
class BF>
1390 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1392 if (e != 0)
return e;
1394 if (e != 0)
return e;
1400 template <
class FUNC,
class R,
class BF,
class T1>
1405 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1407 if (e != 0)
return e;
1409 if (e != 0)
return e;
1411 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1416 template <
class FUNC,
class R,
class BF,
class T1,
class T2>
1417 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
1421 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1423 if (e != 0)
return e;
1425 if (e != 0)
return e;
1427 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1428 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1429 e = th.
Start(settings, task, arg1_.value, arg2_.value,
move_tag());
1433 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3>
1434 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1438 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1440 if (e != 0)
return e;
1442 if (e != 0)
return e;
1444 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1445 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1446 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1447 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value,
move_tag());
1451 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4>
1452 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1456 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1458 if (e != 0)
return e;
1460 if (e != 0)
return e;
1462 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1463 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1464 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1465 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1466 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value,
move_tag());
1470 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4,
class T5>
1471 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1472 const T4& arg4,
const T5& arg5,
const ThreadSettings& settings, BF) {
1475 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1477 if (e != 0)
return e;
1479 if (e != 0)
return e;
1481 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1482 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1483 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1484 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1485 NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1486 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1491 #undef NLIB_ASYNC_HOLDER 1492 #undef NLIB_ASYNC_HOLDER_F 1496 template <
class FUNC,
class R>
1498 return detail::Async_(future, func, settings, FalseType());
1501 template <
class FUNC,
class R>
1504 return detail::Async_(future, func, settings, TrueType());
1507 template <
class FUNC,
class R>
1511 return Async(future, func, settings);
1514 template <
class FUNC,
class R>
1521 template <
class FUNC,
class R,
class T1>
1524 return detail::Async_(future, func, arg1, settings, FalseType());
1527 template <
class FUNC,
class R,
class T1>
1530 return detail::Async_(future, func, arg1, settings, TrueType());
1533 template <
class FUNC,
class R,
class T1>
1537 return Async(future, func, arg1, settings);
1540 template <
class FUNC,
class R,
class T1>
1547 template <
class FUNC,
class R,
class T1,
class T2>
1550 return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1553 template <
class FUNC,
class R,
class T1,
class T2>
1556 return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1559 template <
class FUNC,
class R,
class T1,
class T2>
1563 return Async(future, func, arg1, arg2, settings);
1566 template <
class FUNC,
class R,
class T1,
class T2>
1571 return Async(future, func, arg1, arg2, settings,
move_tag());
1574 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1577 return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1580 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1583 return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1586 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1591 return Async(future, func, arg1, arg2, arg3, settings);
1594 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1599 return Async(future, func, arg1, arg2, arg3, settings,
move_tag());
1602 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1604 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings) {
1605 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1608 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1611 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1614 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1616 const T3& arg3,
const T4& arg4) {
1619 return Async(future, func, arg1, arg2, arg3, arg4, settings);
1622 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1624 const T3& arg3,
const T4& arg4,
move_tag) {
1627 return Async(future, func, arg1, arg2, arg3, arg4, settings,
move_tag());
1630 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1632 const T3& arg3,
const T4& arg4,
const T5& arg5,
1634 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1637 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1639 const T3& arg3,
const T4& arg4,
const T5& arg5,
const ThreadSettings& settings,
1641 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1644 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1646 const T3& arg3,
const T4& arg4,
const T5& arg5) {
1649 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1652 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1654 const T3& arg3,
const T4& arg4,
const T5& arg5,
move_tag) {
1657 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings,
move_tag());
1662 if (!future)
return EINVAL;
1665 if (e != 0)
return e;
1667 if (e != 0)
return e;
1669 if (e != 0)
return e;
1674 template <
class FUTURE,
class R,
typename CONT>
1675 class FutureContinuation :
public FutureContinuationBase {
1677 FutureContinuation(FUTURE& f, CONT cont) NLIB_NOEXCEPT
1681 errno_t Init() NLIB_NOEXCEPT {
return next_.Init(); }
1682 errno_t GetFuture(
Future<R>* future) NLIB_NOEXCEPT {
return next_.GetFuture(future); }
1683 virtual ~FutureContinuation() NLIB_NOEXCEPT
NLIB_OVERRIDE {}
1693 template <
class FUTURE,
class R,
typename CONT>
1694 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
1695 int32_t expected = 0;
1699 R rval = func_(parent_);
1702 (void)next_.SetValue(rval);
1704 (void)next_.SetError(e);
1707 #ifdef NLIB_EXCEPTION_ENABLED 1708 NLIB_RETHROW_UNWIND {
1709 next_.SetError(ECANCELED);
1712 NLIB_CATCH(...) { (void)next_.SetError(EINVAL); }
1717 template <
class Derived>
1719 errno_t FutureBase<Derived>::Then(
Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT {
1720 Derived& ref =
static_cast<Derived&
>(*this);
1721 if (!ref.value_)
return EINVAL;
1723 typedef R (*CONT)(Derived&);
1725 new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
1726 if (!ptr)
return ENOMEM;
1728 if (e != 0)
return e;
1729 e = ptr->GetFuture(next);
1730 if (e != 0)
return e;
1732 ref.value_->common.Lock();
1733 ref.value_->common.cont = ptr.release();
1734 bool isready = ref.IsReady_();
1735 ref.value_->common.Unlock();
1737 ref.value_->common.cont->DoContinuation();
1744 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
1745 struct FutureTuple {
1754 struct FutureTuple<None, None, None, None, None>;
1756 struct FutureTuple<R1, None, None, None, None>;
1758 template <
class R1,
class R2>
1759 struct FutureTuple<R1, R2, None, None, None> {
1764 template <
class R1,
class R2,
class R3>
1765 struct FutureTuple<R1, R2, R3, None, None> {
1771 template <
class R1,
class R2,
class R3,
class R4>
1772 struct FutureTuple<R1, R2, R3, R4, None> {
1779 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
1786 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
1790 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
1795 typedef void (*FuncType)(ArgType& ptr);
1798 static void Call(ArgType& ptr) {
1802 static void CallWhenAny(ArgType& ptr) {
1804 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
1805 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady() ||
1806 ptr->tuple_->f5.IsReady()) {
1811 ptr->promise_.SetValue(ptr->tuple_.
release());
1813 static void CallWhenAll(ArgType& ptr) {
1814 ptr->tuple_->f1.Wait();
1815 ptr->tuple_->f2.Wait();
1816 ptr->tuple_->f3.Wait();
1817 ptr->tuple_->f4.Wait();
1818 ptr->tuple_->f5.Wait();
1819 ptr->promise_.SetValue(ptr->tuple_.
release());
1825 if (e != 0)
return e;
1826 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
1827 if (!tuple_)
return ENOMEM;
1828 e = promise_.GetFuture(f);
1829 if (e != 0)
return e;
1830 e = tuple_->f1.MakeSharedFrom(*f1);
1831 if (e != 0)
return e;
1832 e = tuple_->f2.MakeSharedFrom(*f2);
1833 if (e != 0)
return e;
1834 e = tuple_->f3.MakeSharedFrom(*f3);
1835 if (e != 0)
return e;
1836 e = tuple_->f4.MakeSharedFrom(*f4);
1837 if (e != 0)
return e;
1838 e = tuple_->f5.MakeSharedFrom(*f5);
1839 if (e != 0)
return e;
1851 template <
class R1,
class R2,
class R3,
class R4,
class R5>
1856 if (!f1 || !f2 || !f3 || !f4 || !f5)
return EINVAL;
1860 e = ptr->Init(f, f1, f2, f3, f4, f5);
1861 if (e != 0)
return e;
1864 if (e != 0)
return e;
1873 template <
class R1,
class R2>
1879 return DoWhen(f, f1, f2, CallWhenAll);
1882 return DoWhen(f, f1, f2, CallWhenAny);
1887 typedef void (*FuncType)(ArgType& ptr);
1889 static void Call(ArgType& ptr) {
1893 static void CallWhenAny(ArgType& ptr) {
1895 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady()) {
1900 ptr->promise_.SetValue(ptr->tuple_.
release());
1902 static void CallWhenAll(ArgType& ptr) {
1903 ptr->tuple_->f1.Wait();
1904 ptr->tuple_->f2.Wait();
1905 ptr->promise_.SetValue(ptr->tuple_.
release());
1910 if (e != 0)
return e;
1911 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2>());
1912 if (!tuple_)
return ENOMEM;
1913 e = promise_.GetFuture(f);
1914 if (e != 0)
return e;
1915 e = tuple_->f1.MakeSharedFrom(*f1);
1916 if (e != 0)
return e;
1917 e = tuple_->f2.MakeSharedFrom(*f2);
1918 if (e != 0)
return e;
1930 template <
class R1,
class R2>
1933 if (!f1 || !f2)
return EINVAL;
1937 e = ptr->Init(f, f1, f2);
1938 if (e != 0)
return e;
1941 if (e != 0)
return e;
1945 template <
class R1,
class R2,
class R3>
1951 return DoWhen(f, f1, f2, f3, CallWhenAll);
1954 return DoWhen(f, f1, f2, f3, CallWhenAny);
1959 typedef void (*FuncType)(ArgType& ptr);
1962 static void Call(ArgType& ptr) {
1966 static void CallWhenAny(ArgType& ptr) {
1968 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
1969 ptr->tuple_->f3.IsReady()) {
1974 ptr->promise_.SetValue(ptr->tuple_.
release());
1976 static void CallWhenAll(ArgType& ptr) {
1977 ptr->tuple_->f1.Wait();
1978 ptr->tuple_->f2.Wait();
1979 ptr->tuple_->f3.Wait();
1980 ptr->promise_.SetValue(ptr->tuple_.
release());
1985 if (e != 0)
return e;
1986 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3>());
1987 if (!tuple_)
return ENOMEM;
1988 e = promise_.GetFuture(f);
1989 if (e != 0)
return e;
1990 e = tuple_->f1.MakeSharedFrom(*f1);
1991 if (e != 0)
return e;
1992 e = tuple_->f2.MakeSharedFrom(*f2);
1993 if (e != 0)
return e;
1994 e = tuple_->f3.MakeSharedFrom(*f3);
1995 if (e != 0)
return e;
2007 template <
class R1,
class R2,
class R3>
2010 if (!f1 || !f2 || !f3)
return EINVAL;
2014 e = ptr->Init(f, f1, f2, f3);
2015 if (e != 0)
return e;
2018 if (e != 0)
return e;
2022 template <
class R1,
class R2,
class R3,
class R4>
2029 return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2033 return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2038 typedef void (*FuncType)(ArgType& ptr);
2041 static void Call(ArgType& ptr) {
2045 static void CallWhenAny(ArgType& ptr) {
2047 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2048 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady()) {
2053 ptr->promise_.SetValue(ptr->tuple_.
release());
2055 static void CallWhenAll(ArgType& ptr) {
2056 ptr->tuple_->f1.Wait();
2057 ptr->tuple_->f2.Wait();
2058 ptr->tuple_->f3.Wait();
2059 ptr->tuple_->f4.Wait();
2060 ptr->promise_.SetValue(ptr->tuple_.
release());
2066 if (e != 0)
return e;
2067 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2068 if (!tuple_)
return ENOMEM;
2069 e = promise_.GetFuture(f);
2070 if (e != 0)
return e;
2071 e = tuple_->f1.MakeSharedFrom(*f1);
2072 if (e != 0)
return e;
2073 e = tuple_->f2.MakeSharedFrom(*f2);
2074 if (e != 0)
return e;
2075 e = tuple_->f3.MakeSharedFrom(*f3);
2076 if (e != 0)
return e;
2077 e = tuple_->f4.MakeSharedFrom(*f4);
2078 if (e != 0)
return e;
2090 template <
class R1,
class R2,
class R3,
class R4>
2093 if (!f1 || !f2 || !f3 || !f4)
return EINVAL;
2097 e = ptr->Init(f, f1, f2, f3, f4);
2098 if (e != 0)
return e;
2101 if (e != 0)
return e;
2108 #ifndef NLIB_STD_SWAP_WORKAROUND 2109 NLIB_NAMESPACE_BEGIN
2112 NLIB_DEFINE_STD_SWAP_T_BEGIN1(threading)
2113 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise)
2114 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask)
2115 NLIB_DEFINE_STD_SWAP_T_END1(threading)
2117 #ifndef NLIB_STD_SWAP_WORKAROUND 2121 #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.