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)
スレッドの起動オプションを指定できること以外はそうでないバージョンと同じです。
errno_t MakeReadyFuture(Future< R > *future, const R &value)
予め値が設定されたFutureを作成します。
int64_t tick
nlib_time, nlib_durationとして利用することができます。
#define NLIB_OVERRIDE
利用可能であればoverrideが定義されます。そうでない場合は空文字列です。
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です。
static errno_t Any(FutureType *f, Future< R1 > *f1, Future< R2 > *f2, Future< R3 > *f3, Future< R4 > *f4, Future< R5 > *f5)
Future f1, f2, f3, f4, f5 の何れかに値かエラーが設定された場合に、f に値が設定されます。 ...
errno_t Sleep(const TimeSpan &span) noexcept
スリープします。
C++11の標準ヘッダとなるtype_traitsの代用定義です。 コンパイラや標準ライブラリによってサポートされてい...
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
ミューテックス, 再入可能ミューテックス, 再入とタイムアウトが可能なミューテックスを実装しています。 ...
errno_t Wait() noexcept
結果が取得できる状態になるまで待ちます。
bool GetDetachState() const noexcept
デタッチ状態でスレッドを起動する設定かどうかを返します。
void swap(Promise &rhs) noexcept
オブジェクトをスワップします。
void SetDetachState(bool detached) noexcept
デタッチした状態でスレッドを起動するかどうかを設定します。
errno_t GetFuture(Future< R > *p) noexcept
実行結果を取得するためのFutureを設定します。
UniquePtrはポインタの所有権を保持し、UniquePtrがスコープから出るときにデストラクタでポインタをDELで指...
std::unique_ptrに相当するクラスが定義されています。
NLIB_CHECK_RESULT errno_t WaitUntil(const DateTime &datetime) noexcept
指定された時刻までの間、結果が取得できる状態になるまで待ちます。
スレッド実行の結果を呼び出しスレッドに対してスレッドセーフに出力するためのクラスです。C++11のstd::pro...
bool IsValid() const noexcept
FutureがPromiseと関連付けられているかどうかを返します。
NLIB_CHECK_RESULT errno_t WaitFor(const TimeSpan &span) noexcept
指定された期間の間、結果が取得できる状態になるまで待ちます。
Futureに値が設定されたことを条件として値が設定されるFutureを定義します。
errno_t SetError(errno_t e) noexcept
エラー値を設定します。
nlib_thread_attrをラップするクラスです。必要に応じて自動的にnlib_thread_attr_init()とnlib_thread_attr...
errno_t GetFuture(Future< R > *p) noexcept
実行結果を取得するためのFutureを設定します。
空の構造体で、関数の引数をムーブすべきことを示すために利用されます。
errno_t MakeSharedFrom(const Future &f) noexcept
同じFutureを参照できるよう共有します。
static errno_t All(FutureType *f, Future< R1 > *f1, Future< R2 > *f2, Future< R3 > *f3, Future< R4 > *f4, Future< R5 > *f5)
Future f1, f2, f3, f4, f5 の全てに値かエラーが設定された場合に、f に値が設定されます。 ...
#define NLIB_CATCH(x)
例外が有効なときはcatch(x), そうでなければif (true)が定義されます。
#define NLIB_TRY
例外が有効なときはtry, そうでなければif (true)が定義されます。
errno_t Get(R *ptr)
結果が取得できるまで待ってから、結果を取得します。
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
errno_t GetFutureError(FutureResult &result) noexcept
スレッドがエラー値を持つとき、それをシステムが取得できるようにするための関数です。 ...
別のスレッド実行の出力をスレッドセーフに取得するためのクラスです。C++11のstd::shared_futureに似ていま...
Future< R > FutureType
Future<R>です。
CriticalSection等をラップしてコンストラクタでロック、デストラクタでアンロックします。 ...
errno_t StartRaw(ThreadFunc func, void *arg) noexcept
void*型の引数を1つもつ関数を別スレッドで実行開始します。
関数をラップし、別スレッドで実行し戻り値をスレッドセーフに取得できるようにするクラスです。C++11のstd:...
Promise() noexcept
デフォルトコンストラクタです。
TimeValue ToTimeValue() const noexcept
TimeValueオブジェクトを返します。
bool IsReady() const noexcept
Future に値が設定されている(Promiseが値かエラーを設定した)かどうかを返します。
errno_t SetValue(const R &value)
値を設定して、Futureから取り出せる状態にします。
PackagedTask< T > ThisType
このオブジェクトの型です。
errno_t Then(Future< RNEXT > *next, RNEXT(*cont)(Future< R > &)) noexcept
このフューチャーに対して引き続き行う処理(continuation)を登録します。
Future< ReturnType > FutureType
新たに作成されるFutureの型です。
Future() noexcept
デフォルトコンストラクタです。
errno_t Init() noexcept
オブジェクトの初期化を行います。
UniquePtr< FutureTuple< R1, R2, R3, R4, R5 > > ReturnType
新たに作成されるFutureに設定される値の型です。
T * release() noexcept
ポインタの所有権を手放し、ポインタを返します。
errno_t Init(FUNC &func)
初期化を行います。