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)
スレッドの起動オプションを指定できること以外はそうでないバージョンと同じです。
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)
初期化を行います。