16 #ifndef INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 17 #define INCLUDE_NN_NLIB_THREADING_FUTURE_H_ 21 #include "nn/nlib/Swap.h" 26 #include "nn/nlib/threading/LimitedSharedPtr.h" 34 template<
class FutureResult>
51 virtual void DoContinuation() {}
57 template<
class FUTURE,
class R,
typename CONT>
58 class FutureContinuation;
60 template<
class Derived>
64 #ifdef __cpp_rvalue_references 65 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 66 FutureBase(FutureBase&& rhs) =
default;
67 FutureBase& operator=(FutureBase&& rhs) =
default;
71 FutureBase& assign(FutureBase&, move_tag)
NLIB_NOEXCEPT {
return *
this; }
76 const Derived& ref =
static_cast<const Derived&
>(*this);
81 Derived& ref =
static_cast<Derived&
>(*this);
82 return ref.value_.MakeSharedFrom(f.value_);
89 return static_cast<const Derived&
>(*this).value_->common.IsReady();
93 template<
class Derived>
95 const Derived& ref =
static_cast<const Derived&
>(*this);
97 ref.value_->common.Lock();
98 bool rval = IsReady_();
99 ref.value_->common.Unlock();
106 template<
class Derived>
108 Derived& ref =
static_cast<Derived&
>(*this);
109 NLIB_ASSERT(ref.value_);
110 if (!ref.value_)
return EINVAL;
111 ref.value_->common.Lock();
112 while (!IsReady_()) {
113 errno_t e = ref.value_->common.Wait();
115 ref.value_->common.Unlock();
116 NLIB_ASSERT_NOERR(e);
120 ref.value_->common.Unlock();
124 template<
class Derived>
126 Derived& ref =
static_cast<Derived&
>(*this);
127 NLIB_ASSERT(ref.value_);
128 if (!ref.value_)
return EINVAL;
130 errno_t e = DateTime::GetNow(&abstime);
132 if (e != 0)
return e;
133 ref.value_->common.Lock();
134 while (!IsReady_()) {
141 abstime.ToTimeValue().tick);
143 ref.value_->common.Unlock();
147 ref.value_->common.Unlock();
151 template<
class Derived>
153 Derived& ref =
static_cast<Derived&
>(*this);
154 NLIB_ASSERT(ref.value_);
155 if (!ref.value_)
return EINVAL;
156 ref.value_->common.Lock();
157 while (!IsReady_()) {
159 datetime.ToTimeValue().tick);
161 ref.value_->common.Unlock();
165 ref.value_->common.Unlock();
172 template<
class Derived>
176 #ifdef __cpp_rvalue_references 177 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 178 PromiseBase(PromiseBase&& ) =
default;
179 PromiseBase& operator=(PromiseBase&&) =
default;
185 const Derived& ref =
static_cast<const Derived&
>(*this);
193 struct NLIB_CAPABILITY("mutex") CommonStatus {
195 detail::FutureContinuationBase* cont;
199 CommonStatus()
NLIB_NOEXCEPT : status(0), cont(NULL), err(0) {
203 NLIB_ASSERT_NOERR(e);
205 NLIB_ASSERT_NOERR(e);
208 if (cont)
delete cont;
212 NLIB_ASSERT_NOERR(e);
214 NLIB_ASSERT_NOERR(e);
216 void Lock()
NLIB_NOEXCEPT NLIB_ACQUIRE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
220 NLIB_ASSERT_NOERR(e);
222 void Unlock()
NLIB_NOEXCEPT NLIB_RELEASE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
226 NLIB_ASSERT_NOERR(e);
233 if (status != 20120915L) {
243 NLIB_ASSERT_NOERR(e);
245 if (cont) cont->DoContinuation();
249 static_cast<Derived&
>(*this).value_->common.NotifyAndContinuation();
256 template<
class Derived>
261 Derived& ref =
static_cast<Derived&
>(*this);
262 if (ref.value_)
return EALREADY;
263 ref.value_.reset(
new (std::nothrow)
typename Derived::Status());
264 if (!ref.value_)
return ENOMEM;
268 template<
class Derived>
270 if (e == 0)
return 0;
271 Derived& ref =
static_cast<Derived&
>(*this);
274 if (ee != 0)
return ee;
277 ref.value_->common.Lock();
278 if (ref.value_->common.SetReady()) {
279 ref.value_->common.err = e;
280 ref.value_->common.Unlock();
282 ref.value_->common.Unlock();
286 this->NotifyAndContinuation();
290 template<
class Derived>
293 if (!p)
return EINVAL;
294 Derived& ref =
static_cast<Derived&
>(*this);
297 if (e != 0)
return e;
299 errno_t e = p->value_.MakeSharedFrom(ref.value_);
300 if (e != 0)
return e;
307 class Promise :
public detail::PromiseBase<Promise<R> > {
308 typedef detail::PromiseBase<Promise<R> > BaseType;
314 #ifdef __cpp_rvalue_references 315 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 316 Promise(Promise&& rhs) =
default;
317 Promise& operator=(Promise&& rhs) =
default;
319 Promise(Promise&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
321 value_ = std::move(rhs.value_);
328 value_.assign(rhs.value_,
move_tag());
331 errno_t SetValue(
const R& value);
340 typename BaseType::CommonStatus common;
343 LimitedSharedPtr<Status> value_;
348 friend class detail::PromiseBase;
355 if (e != 0)
return e;
359 if (value_->common.SetReady()) {
361 value_->data = value;
363 #ifdef __cpp_exceptions 364 NLIB_RETHROW_UNWIND {
365 this->SetError(ECANCELED);
368 NLIB_CATCH(...) {
return this->SetError(EINVAL); }
374 this->NotifyAndContinuation();
378 template<
class T,
class DEL>
379 class Promise<
UniquePtr<T, DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
380 typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
385 #ifdef __cpp_rvalue_references 386 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 387 Promise(Promise&& rhs) =
default;
388 Promise& operator=(Promise&& rhs) =
default;
390 Promise(Promise&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
392 value_ = std::move(rhs.value_);
397 Promise(Promise& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
399 value_.assign(rhs.value_, move_tag());
406 typename BaseType::CommonStatus common;
407 UniquePtr<T, DEL> data;
409 LimitedSharedPtr<Status> value_;
414 friend class detail::PromiseBase;
417 template<
class T,
class DEL>
421 if (e != 0)
return e;
424 value_->common.Lock();
425 if (value_->common.SetReady()) {
426 value_->data.reset(value);
427 value_->common.Unlock();
429 value_->common.Unlock();
433 this->NotifyAndContinuation();
437 template<
class T,
class DEL>
438 class Promise<UniquePtr<T[], DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
439 typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
442 typedef Future<UniquePtr<T[], DEL> > FutureType;
444 #ifdef __cpp_rvalue_references 445 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 446 Promise(Promise&& rhs) =
default;
447 Promise& operator=(Promise&& rhs) =
default;
449 Promise(Promise&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
451 value_ = std::move(rhs.value_);
456 Promise(Promise& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
458 value_.assign(rhs.value_, move_tag());
465 typename BaseType::CommonStatus common;
466 UniquePtr<T[], DEL> data;
468 LimitedSharedPtr<Status> value_;
473 friend class detail::PromiseBase;
476 template<
class T,
class DEL>
480 if (e != 0)
return e;
483 value_->common.Lock();
484 if (value_->common.SetReady()) {
485 value_->data.reset(value);
486 value_->common.Unlock();
488 value_->common.Unlock();
492 this->NotifyAndContinuation();
497 class Promise<void> :
public detail::PromiseBase<Promise<void> > {
498 typedef detail::PromiseBase<Promise<void> > BaseType;
501 typedef Future<void> FutureType;
503 #ifdef __cpp_rvalue_references 504 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 505 Promise(Promise&& rhs) =
default;
506 Promise& operator=(Promise&& rhs) =
default;
508 Promise(Promise&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
510 value_ = std::move(rhs.value_);
515 Promise(Promise& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
517 value_.assign(rhs.value_, move_tag());
524 BaseType::CommonStatus common;
526 LimitedSharedPtr<Status> value_;
531 friend class detail::PromiseBase;
535 class Promise<Future<R> > :
public detail::PromiseBase<Promise<Future<R> > > {
536 typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
539 typedef Future<Future<R> > FutureType;
541 #ifdef __cpp_rvalue_references 542 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 543 Promise(Promise&& rhs) =
default;
544 Promise& operator=(Promise&& rhs) =
default;
546 Promise(Promise&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
548 value_ = std::move(rhs.value_);
553 Promise(Promise& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
555 value_.assign(rhs.value_, move_tag());
562 typename BaseType::CommonStatus common;
565 LimitedSharedPtr<Status> value_;
570 friend class detail::PromiseBase;
577 if (e != 0)
return e;
580 value_->common.Lock();
581 if (value_->common.SetReady()) {
582 errno_t e = value_->data.MakeSharedFrom(value);
583 value_->common.Unlock();
588 value_->common.Unlock();
592 this->NotifyAndContinuation();
597 class Future :
public detail::FutureBase<Future<R> > {
598 typedef detail::FutureBase<Future<R> > BaseType;
602 #ifdef __cpp_rvalue_references 603 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 609 value_ = std::move(rhs.value_);
616 value_.assign(rhs.value_,
move_tag());
623 NLIB_ASSERT_NOERR(e);
627 if (!ptr)
return EINVAL;
629 errno_t e = value_->common.err;
634 #ifdef __cpp_exceptions 635 NLIB_RETHROW_UNWIND {
throw; }
646 return BaseType::WaitFor(span);
649 return BaseType::WaitUntil(datetime);
651 template<
class RNEXT>
653 return BaseType::Then(next, cont);
658 LimitedSharedPtr<typename Promise<R>::Status> value_;
663 friend class detail::FutureBase;
665 friend class detail::PromiseBase;
668 template<
class T,
class DEL>
669 class Future<
UniquePtr<T, DEL> > :
public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
670 typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
674 #ifdef __cpp_rvalue_references 675 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 676 Future(Future&& rhs) =
default;
677 Future& operator=(Future&& rhs) =
default;
679 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
681 value_ = std::move(rhs.value_);
686 Future(Future& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
688 value_.assign(rhs.value_, move_tag());
693 return value_->data.get();
696 if (!ptr)
return EINVAL;
698 errno_t e = value_->common.err;
699 if (e == 0) *ptr = value_->data.get();
704 return value_->data.release();
708 LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> value_;
711 friend class Promise;
713 friend class detail::FutureBase;
715 friend class detail::PromiseBase;
718 template<
class T,
class DEL>
719 class Future<UniquePtr<T[], DEL> > :
public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
720 typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
724 #ifdef __cpp_rvalue_references 725 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 726 Future(Future&& rhs) =
default;
727 Future& operator=(Future&& rhs) =
default;
729 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
731 value_ = std::move(rhs.value_);
736 Future(Future& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
738 value_.assign(rhs.value_, move_tag());
743 return value_->data.get();
746 if (!ptr)
return EINVAL;
748 errno_t e = value_->common.err;
749 if (e == 0) *ptr = value_->data.get();
754 return value_->common.data.release();
758 LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> value_;
761 friend class Promise;
763 friend class detail::FutureBase;
765 friend class detail::PromiseBase;
769 class Future<void> :
public detail::FutureBase<Future<void> > {
770 typedef detail::FutureBase<Future<void> > BaseType;
774 #ifdef __cpp_rvalue_references 775 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 776 Future(Future&& rhs) =
default;
777 Future& operator=(Future&& rhs) =
default;
779 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
781 value_ = std::move(rhs.value_);
786 Future(Future& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
788 value_.assign(rhs.value_, move_tag());
793 return value_->common.err;
797 LimitedSharedPtr<Promise<void>::Status> value_;
800 friend class Promise;
802 friend class detail::FutureBase;
804 friend class detail::PromiseBase;
808 class Future<Future<R> > :
public detail::FutureBase<Future<Future<R> > > {
809 typedef detail::FutureBase<Future<Future<R> > > BaseType;
813 #ifdef __cpp_rvalue_references 814 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 815 Future(Future&& rhs) =
default;
816 Future& operator=(Future&& rhs) =
default;
818 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
820 value_ = std::move(rhs.value_);
825 Future(Future& rhs, move_tag)
NLIB_NOEXCEPT : value_(rhs.value_, move_tag()) {}
827 value_.assign(rhs.value_, move_tag());
831 if (!inner)
return EINVAL;
833 errno_t e = value_->common.err;
834 if (e != 0)
return e;
835 return inner->MakeSharedFrom(value_->data);
839 LimitedSharedPtr<typename Promise<Future<R> >::Status> value_;
842 friend class Promise;
844 friend class detail::FutureBase;
846 friend class detail::PromiseBase;
852 class FuncHolderBase0 {
854 virtual ~FuncHolderBase0() {}
855 virtual R operator()() = 0;
858 template<
class R,
class T1>
859 class FuncHolderBase1 {
861 virtual ~FuncHolderBase1() {}
862 virtual R operator()(T1 NLIB_RREF arg1) = 0;
865 template<
class R,
class T1,
class T2>
866 class FuncHolderBase2 {
868 virtual ~FuncHolderBase2() {}
869 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0;
872 template<
class R,
class T1,
class T2,
class T3>
873 class FuncHolderBase3 {
875 virtual ~FuncHolderBase3() {}
876 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0;
879 template<
class R,
class T1,
class T2,
class T3,
class T4>
880 class FuncHolderBase4 {
882 virtual ~FuncHolderBase4() {}
884 operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) = 0;
887 template<
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
888 class FuncHolderBase5 {
890 virtual ~FuncHolderBase5() {}
891 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
892 T5 NLIB_RREF arg5) = 0;
895 template<
class FUNC,
bool USESWAP>
910 class FuncWrap_<FUNC, false> {
912 FuncWrap_(FUNC& func) : func_(func) {}
921 class FuncWrap :
public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
922 typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
925 FuncWrap(FUNC& func) : BaseType(func) {}
929 class FuncWrap<R()> {
932 explicit FuncWrap(FUNC func) : func_(func) {}
940 template<
class R,
class T1>
941 class FuncWrap<R(T1)> {
943 typedef R (*FUNC)(T1);
944 explicit FuncWrap(FUNC func) : func_(func) {}
952 template<
class R,
class T1,
class T2>
953 class FuncWrap<R(T1, T2)> {
955 typedef R (*FUNC)(T1, T2);
956 explicit FuncWrap(FUNC func) : func_(func) {}
964 template<
class R,
class T1,
class T2,
class T3>
965 class FuncWrap<R(T1, T2, T3)> {
967 typedef R (*FUNC)(T1, T2, T3);
968 explicit FuncWrap(FUNC func) : func_(func) {}
976 template<
class R,
class T1,
class T2,
class T3,
class T4>
977 class FuncWrap<R(T1, T2, T3, T4)> {
979 typedef R (*FUNC)(T1, T2, T3, T4);
980 explicit FuncWrap(FUNC func) : func_(func) {}
988 template<
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
989 class FuncWrap<R(T1, T2, T3, T4, T5)> {
991 typedef R (*FUNC)(T1, T2, T3, T4, T5);
992 explicit FuncWrap(FUNC func) : func_(func) {}
1000 template<
class FUNC,
class R>
1001 class FuncHolder0 :
public FuncHolderBase0<R> {
1003 FuncHolder0(FUNC& f) : func_(f) {}
1005 virtual R operator()()
NLIB_OVERRIDE {
return func_.get()(); }
1008 FuncWrap<FUNC> func_;
1011 template<
class FUNC,
class R,
class T1>
1012 class FuncHolder1 :
public FuncHolderBase1<R, T1> {
1014 FuncHolder1(FUNC& f) : func_(f) {}
1017 return func_.get()(NLIB_FWD(T1, arg1));
1021 FuncWrap<FUNC> func_;
1024 template<
class FUNC,
class R,
class T1,
class T2>
1025 class FuncHolder2 :
public FuncHolderBase2<R, T1, T2> {
1027 FuncHolder2(FUNC& f) : func_(f) {}
1029 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)
NLIB_OVERRIDE {
1030 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1034 FuncWrap<FUNC> func_;
1037 template<
class FUNC,
class R,
class T1,
class T2,
class T3>
1038 class FuncHolder3 :
public FuncHolderBase3<R, T1, T2, T3> {
1040 FuncHolder3(FUNC& f) : func_(f) {}
1042 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)
NLIB_OVERRIDE {
1043 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1047 FuncWrap<FUNC> func_;
1050 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1051 class FuncHolder4 :
public FuncHolderBase4<R, T1, T2, T3, T4> {
1053 FuncHolder4(FUNC& f) : func_(f) {}
1055 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1057 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1058 NLIB_FWD(T4, arg4));
1062 FuncWrap<FUNC> func_;
1065 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1066 class FuncHolder5 :
public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
1068 FuncHolder5(FUNC& f) : func_(f) {}
1070 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1072 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1073 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1077 FuncWrap<FUNC> func_;
1087 template<class FUNC>
1096 typedef R ReturnType;
1099 #ifdef __cpp_rvalue_references 1100 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1105 promise_(std::move(rhs.promise_)) {}
1107 func_ = std::move(rhs.func_);
1108 promise_ = std::move(rhs.promise_);
1114 promise_(rhs.promise_,
move_tag()) {}
1116 func_.reset(rhs.func_.release());
1117 promise_.assign(rhs.promise_,
move_tag());
1120 template<
class FUNC>
1123 if (e != 0)
return e;
1124 func_.reset(
new (std::nothrow) detail::FuncHolder0<FUNC, R>(func));
1125 return !func_ ? ENOMEM : 0;
1128 void operator()() { Exec<R>(); }
1131 template<
class DUMMY>
1132 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec() {
1134 R rval = (*func_)();
1137 promise_.SetValue(rval);
1139 promise_.SetError(e);
1142 #ifdef __cpp_exceptions 1143 NLIB_RETHROW_UNWIND {
1144 promise_.SetError(ECANCELED);
1147 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1150 template<
class DUMMY>
1151 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(){
NLIB_TRY{(*func_)();
1152 promise_.SetValue();
1154 #ifdef __cpp_exceptions 1155 NLIB_RETHROW_UNWIND {
1156 promise_.SetError(ECANCELED);
1160 promise_.SetError(EINVAL);
1171 template<
class R,
class T1>
1174 typedef R ReturnType;
1177 #ifdef __cpp_rvalue_references 1178 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1179 PackagedTask(PackagedTask&& rhs) =
default;
1180 PackagedTask& operator=(PackagedTask&& rhs) =
default;
1182 PackagedTask(PackagedTask&& rhs)
NLIB_NOEXCEPT : func_(std::move(rhs.func_)),
1183 promise_(std::move(rhs.promise_)) {}
1185 func_ = std::move(rhs.func_);
1186 promise_ = std::move(rhs.promise_);
1191 PackagedTask(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT : func_(rhs.func_.release()),
1192 promise_(rhs.promise_, move_tag()) {}
1193 PackagedTask& assign(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT {
1194 func_.reset(rhs.func_.release());
1195 promise_.assign(rhs.promise_, move_tag());
1198 template<
class FUNC>
1201 if (e != 0)
return e;
1202 func_.reset(
new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func));
1203 return !func_ ? ENOMEM : 0;
1206 void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1209 template<
class DUMMY>
1210 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(T1 NLIB_RREF arg1) {
1212 R rval = (*func_)(NLIB_FWD(T1, arg1));
1215 promise_.SetValue(rval);
1217 promise_.SetError(e);
1220 #ifdef __cpp_exceptions 1221 NLIB_RETHROW_UNWIND {
1222 promise_.SetError(ECANCELED);
1225 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1228 template<
class DUMMY>
1229 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type
1230 Exec(T1 NLIB_RREF arg1){
NLIB_TRY{(*func_)(NLIB_FWD(T1, arg1));
1231 promise_.SetValue();
1233 #ifdef __cpp_exceptions 1234 NLIB_RETHROW_UNWIND {
1235 promise_.SetError(ECANCELED);
1239 promise_.SetError(EINVAL);
1244 UniquePtr<detail::FuncHolderBase1<R, T1> > func_;
1245 Promise<R> promise_;
1250 template<
class R,
class T1,
class T2>
1251 class PackagedTask<R(T1, T2)> {
1253 typedef R ReturnType;
1254 typedef PackagedTask<ReturnType(T1, T2)> ThisType;
1256 #ifdef __cpp_rvalue_references 1257 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1258 PackagedTask(PackagedTask&& rhs) =
default;
1259 PackagedTask& operator=(PackagedTask&& rhs) =
default;
1261 PackagedTask(PackagedTask&& rhs)
NLIB_NOEXCEPT : func_(std::move(rhs.func_)),
1262 promise_(std::move(rhs.promise_)) {}
1264 func_ = std::move(rhs.func_);
1265 promise_ = std::move(rhs.promise_);
1270 PackagedTask(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT : func_(rhs.func_.release()),
1271 promise_(rhs.promise_, move_tag()) {}
1272 PackagedTask& assign(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT {
1273 func_.reset(rhs.func_.release());
1274 promise_.assign(rhs.promise_, move_tag());
1277 template<
class FUNC>
1280 if (e != 0)
return e;
1281 func_.reset(
new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func));
1282 return !func_ ? ENOMEM : 0;
1285 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1286 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1290 template<
class DUMMY>
1291 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type
1292 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1294 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1297 promise_.SetValue(rval);
1299 promise_.SetError(e);
1302 #ifdef __cpp_exceptions 1303 NLIB_RETHROW_UNWIND {
1304 promise_.SetError(ECANCELED);
1307 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1310 template<
class DUMMY>
1311 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type
1312 Exec(T1 NLIB_RREF arg1,
1313 T2 NLIB_RREF arg2){
NLIB_TRY{(*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1314 promise_.SetValue();
1316 #ifdef __cpp_exceptions 1317 NLIB_RETHROW_UNWIND {
1318 promise_.SetError(ECANCELED);
1322 promise_.SetError(EINVAL);
1327 UniquePtr<detail::FuncHolderBase2<R, T1, T2> > func_;
1328 Promise<ReturnType> promise_;
1333 template<
class R,
class T1,
class T2,
class T3>
1334 class PackagedTask<R(T1, T2, T3)> {
1336 typedef R ReturnType;
1337 typedef PackagedTask<ReturnType(T1, T2, T3)> ThisType;
1339 #ifdef __cpp_rvalue_references 1340 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1341 PackagedTask(PackagedTask&& rhs) =
default;
1342 PackagedTask& operator=(PackagedTask&& rhs) =
default;
1344 PackagedTask(PackagedTask&& rhs)
NLIB_NOEXCEPT : func_(std::move(rhs.func_)),
1345 promise_(std::move(rhs.promise_)) {}
1347 func_ = std::move(rhs.func_);
1348 promise_ = std::move(rhs.promise_);
1353 PackagedTask(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT : func_(rhs.func_.release()),
1354 promise_(rhs.promise_, move_tag()) {}
1355 PackagedTask& assign(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT {
1356 func_.reset(rhs.func_.release());
1357 promise_.assign(rhs.promise_, move_tag());
1360 template<
class FUNC>
1363 if (e != 0)
return e;
1364 func_.reset(
new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func));
1365 return !func_ ? ENOMEM : 0;
1368 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1369 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1373 template<
class DUMMY>
1374 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type
1375 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1377 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1380 promise_.SetValue(rval);
1382 promise_.SetError(e);
1385 #ifdef __cpp_exceptions 1386 NLIB_RETHROW_UNWIND {
1387 promise_.SetError(ECANCELED);
1390 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1393 template<
class DUMMY>
1394 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type
1395 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3){
1396 NLIB_TRY{(*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1397 promise_.SetValue();
1399 #ifdef __cpp_exceptions 1400 NLIB_RETHROW_UNWIND {
1401 promise_.SetError(ECANCELED);
1405 promise_.SetError(EINVAL);
1410 UniquePtr<detail::FuncHolderBase3<R, T1, T2, T3> > func_;
1411 Promise<ReturnType> promise_;
1416 template<
class R,
class T1,
class T2,
class T3,
class T4>
1417 class PackagedTask<R(T1, T2, T3, T4)> {
1419 typedef R ReturnType;
1420 typedef PackagedTask<ReturnType(T1, T2, T3, T4)> ThisType;
1422 #ifdef __cpp_rvalue_references 1423 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1424 PackagedTask(PackagedTask&& rhs) =
default;
1425 PackagedTask& operator=(PackagedTask&& rhs) =
default;
1427 PackagedTask(PackagedTask&& rhs)
NLIB_NOEXCEPT : func_(std::move(rhs.func_)),
1428 promise_(std::move(rhs.promise_)) {}
1430 func_ = std::move(rhs.func_);
1431 promise_ = std::move(rhs.promise_);
1436 PackagedTask(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT : func_(rhs.func_.release()),
1437 promise_(rhs.promise_, move_tag()) {}
1438 PackagedTask& assign(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT {
1439 func_.reset(rhs.func_.release());
1440 promise_.assign(rhs.promise_, move_tag());
1443 template<
class FUNC>
1446 if (e != 0)
return e;
1447 func_.reset(
new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func));
1448 return !func_ ? ENOMEM : 0;
1451 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1452 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1456 template<
class DUMMY>
1457 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type
1458 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1460 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1461 NLIB_FWD(T4, arg4));
1464 promise_.SetValue(rval);
1466 promise_.SetError(e);
1469 #ifdef __cpp_exceptions 1470 NLIB_RETHROW_UNWIND {
1471 promise_.SetError(ECANCELED);
1474 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1477 template<
class DUMMY>
1478 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type
1479 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4){
NLIB_TRY{
1480 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1481 promise_.SetValue();
1483 #ifdef __cpp_exceptions 1484 NLIB_RETHROW_UNWIND {
1485 promise_.SetError(ECANCELED);
1489 promise_.SetError(EINVAL);
1494 UniquePtr<detail::FuncHolderBase4<R, T1, T2, T3, T4> > func_;
1495 Promise<ReturnType> promise_;
1500 template<
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1501 class PackagedTask<R(T1, T2, T3, T4, T5)> {
1503 typedef R ReturnType;
1504 typedef PackagedTask<ReturnType(T1, T2, T3, T4, T5)> ThisType;
1506 #ifdef __cpp_rvalue_references 1507 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1508 PackagedTask(PackagedTask&& rhs) =
default;
1509 PackagedTask& operator=(PackagedTask&& rhs) =
default;
1511 PackagedTask(PackagedTask&& rhs)
NLIB_NOEXCEPT : func_(std::move(rhs.func_)),
1512 promise_(std::move(rhs.promise_)) {}
1514 func_ = std::move(rhs.func_);
1515 promise_ = std::move(rhs.promise_);
1520 PackagedTask(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT : func_(rhs.func_.release()),
1521 promise_(rhs.promise_, move_tag()) {}
1522 PackagedTask& assign(PackagedTask& rhs, move_tag)
NLIB_NOEXCEPT {
1523 func_.reset(rhs.func_.release());
1524 promise_.assign(rhs.promise_, move_tag());
1527 template<
class FUNC>
1530 if (e != 0)
return e;
1531 func_.reset(
new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func));
1532 return !func_ ? ENOMEM : 0;
1535 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1536 T5 NLIB_RREF arg5) {
1537 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1538 NLIB_FWD(T5, arg5));
1542 template<
class DUMMY>
1543 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type
1544 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1545 T5 NLIB_RREF arg5) {
1547 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1548 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1551 promise_.SetValue(rval);
1553 promise_.SetError(e);
1556 #ifdef __cpp_exceptions 1557 NLIB_RETHROW_UNWIND {
1558 promise_.SetError(ECANCELED);
1561 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1564 template<
class DUMMY>
1565 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type
1566 Exec(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1568 NLIB_TRY{(*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1569 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1570 promise_.SetValue();
1572 #ifdef __cpp_exceptions 1573 NLIB_RETHROW_UNWIND {
1574 promise_.SetError(ECANCELED);
1578 promise_.SetError(EINVAL);
1583 UniquePtr<detail::FuncHolderBase5<R, T1, T2, T3, T4, T5> > func_;
1584 Promise<ReturnType> promise_;
1591 template<
class T,
bool B>
1593 explicit XHolder(
const T& value_) : value() {
1595 swap(const_cast<T&>(value_), value);
1601 struct XHolder<T, false> {
1602 explicit XHolder(
const T& value_) : value(value_) {}
1607 struct XHolder<R(), false> {
1608 XHolder(R (*value_)()) : value(value_) {}
1612 template<
class R,
class T1>
1613 struct XHolder<R(T1), false> {
1614 XHolder(R (*value_)(T1)) : value(value_) {}
1618 template<
class R,
class T1,
class T2>
1619 struct XHolder<R(T1, T2), false> {
1620 XHolder(R (*value_)(T1, T2)) : value(value_) {}
1624 template<
class R,
class T1,
class T2,
class T3>
1625 struct XHolder<R(T1, T2, T3), false> {
1626 XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1627 R (*value)(T1, T2, T3);
1630 template<
class R,
class T1,
class T2,
class T3,
class T4>
1631 struct XHolder<R(T1, T2, T3, T4), false> {
1632 XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1633 R (*value)(T1, T2, T3, T4);
1636 template<
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1637 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1638 XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1639 R (*value)(T1, T2, T3, T4, T5);
1642 #define NLIB_ASYNC_HOLDER(T, B) \ 1643 XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value> 1644 #ifdef __cpp_rvalue_references 1645 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1646 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && !IsPointer<FUNC>::value> 1648 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1649 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && !IsPointer<FUNC>::value> 1652 template<
class FUNC,
class R,
class BF>
1653 errno_t Async_(Future<R>* future,
const FUNC& func,
const ThreadSettings& settings, BF) {
1654 if (!future || !settings.GetDetachState())
return EINVAL;
1655 PackagedTask<R()> task;
1656 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1657 errno_t e = task.Init(func_.value);
1658 if (e != 0)
return e;
1659 e = task.GetFuture(future);
1660 if (e != 0)
return e;
1662 e = th.Start(settings, task, move_tag());
1666 template<
class FUNC,
class R,
class BF,
class T1>
1668 Async_(Future<R>* future,
const FUNC& func,
const T1& arg1,
const ThreadSettings& settings, BF) {
1669 if (!future || !settings.GetDetachState())
return EINVAL;
1670 PackagedTask<R(T1)> task;
1671 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1672 errno_t e = task.Init(func_.value);
1673 if (e != 0)
return e;
1674 e = task.GetFuture(future);
1675 if (e != 0)
return e;
1677 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1678 e = th.Start(settings, task, arg1_.value, move_tag());
1682 template<
class FUNC,
class R,
class BF,
class T1,
class T2>
1683 errno_t Async_(Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
1684 const ThreadSettings& settings, BF) {
1685 if (!future || !settings.GetDetachState())
return EINVAL;
1686 PackagedTask<R(T1, T2)> task;
1687 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1688 errno_t e = task.Init(func_.value);
1689 if (e != 0)
return e;
1690 e = task.GetFuture(future);
1691 if (e != 0)
return e;
1693 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1694 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1695 e = th.Start(settings, task, arg1_.value, arg2_.value, move_tag());
1699 template<
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3>
1700 errno_t Async_(Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1701 const ThreadSettings& settings, BF) {
1702 if (!future || !settings.GetDetachState())
return EINVAL;
1703 PackagedTask<R(T1, T2, T3)> task;
1704 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1705 errno_t e = task.Init(func_.value);
1706 if (e != 0)
return e;
1707 e = task.GetFuture(future);
1708 if (e != 0)
return e;
1710 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1711 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1712 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1713 e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, move_tag());
1717 template<
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4>
1718 errno_t Async_(Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1719 const T4& arg4,
const ThreadSettings& settings, BF) {
1720 if (!future || !settings.GetDetachState())
return EINVAL;
1721 PackagedTask<R(T1, T2, T3, T4)> task;
1722 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1723 errno_t e = task.Init(func_.value);
1724 if (e != 0)
return e;
1725 e = task.GetFuture(future);
1726 if (e != 0)
return e;
1728 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1729 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1730 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1731 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1732 e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, move_tag());
1736 template<
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4,
class T5>
1737 errno_t Async_(Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1738 const T4& arg4,
const T5& arg5,
const ThreadSettings& settings, BF) {
1739 if (!future || !settings.GetDetachState())
return EINVAL;
1740 PackagedTask<R(T1, T2, T3, T4, T5)> task;
1741 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1742 errno_t e = task.Init(func_.value);
1743 if (e != 0)
return e;
1744 e = task.GetFuture(future);
1745 if (e != 0)
return e;
1747 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1748 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1749 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1750 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1751 NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1752 e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1757 #undef NLIB_ASYNC_HOLDER 1758 #undef NLIB_ASYNC_HOLDER_F 1762 template<
class FUNC,
class R>
1764 return detail::Async_(future, func, settings, FalseType());
1767 template<
class FUNC,
class R>
1770 return detail::Async_(future, func, settings, TrueType());
1773 template<
class FUNC,
class R>
1777 return Async(future, func, settings);
1780 template<
class FUNC,
class R>
1787 template<
class FUNC,
class R,
class T1>
1790 return detail::Async_(future, func, arg1, settings, FalseType());
1793 template<
class FUNC,
class R,
class T1>
1796 return detail::Async_(future, func, arg1, settings, TrueType());
1799 template<
class FUNC,
class R,
class T1>
1803 return Async(future, func, arg1, settings);
1806 template<
class FUNC,
class R,
class T1>
1813 template<
class FUNC,
class R,
class T1,
class T2>
1816 return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1819 template<
class FUNC,
class R,
class T1,
class T2>
1822 return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1825 template<
class FUNC,
class R,
class T1,
class T2>
1829 return Async(future, func, arg1, arg2, settings);
1832 template<
class FUNC,
class R,
class T1,
class T2>
1837 return Async(future, func, arg1, arg2, settings,
move_tag());
1840 template<
class FUNC,
class R,
class T1,
class T2,
class T3>
1843 return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1846 template<
class FUNC,
class R,
class T1,
class T2,
class T3>
1849 return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1852 template<
class FUNC,
class R,
class T1,
class T2,
class T3>
1854 Async(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3) {
1857 return Async(future, func, arg1, arg2, arg3, settings);
1860 template<
class FUNC,
class R,
class T1,
class T2,
class T3>
1865 return Async(future, func, arg1, arg2, arg3, settings,
move_tag());
1868 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1870 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings) {
1871 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1874 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1877 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1880 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1882 const T3& arg3,
const T4& arg4) {
1885 return Async(future, func, arg1, arg2, arg3, arg4, settings);
1888 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1890 const T3& arg3,
const T4& arg4,
move_tag) {
1893 return Async(future, func, arg1, arg2, arg3, arg4, settings,
move_tag());
1896 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1898 Async(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1899 const T4& arg4,
const T5& arg5,
const ThreadSettings& settings) {
1900 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1903 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1905 Async(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1907 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1910 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1912 const T3& arg3,
const T4& arg4,
const T5& arg5) {
1915 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1918 template<
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1920 const T3& arg3,
const T4& arg4,
const T5& arg5,
move_tag) {
1923 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings,
move_tag());
1928 if (!future)
return EINVAL;
1931 if (e != 0)
return e;
1932 e = promise.SetValue(value);
1933 if (e != 0)
return e;
1934 e = promise.GetFuture(future);
1935 if (e != 0)
return e;
1940 template<
class FUTURE,
class R,
typename CONT>
1941 class FutureContinuation :
public FutureContinuationBase {
1943 FutureContinuation(FUTURE& f, CONT cont)
NLIB_NOEXCEPT : status_(0), parent_(f), func_(cont) {}
1956 template<class FUTURE, class R, typename CONT>
1957 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
1958 int32_t expected = 0;
1962 R rval = func_(parent_);
1965 (void)next_.SetValue(rval);
1967 (void)next_.SetError(e);
1970 #ifdef __cpp_exceptions 1971 NLIB_RETHROW_UNWIND {
1972 next_.SetError(ECANCELED);
1975 NLIB_CATCH(...) { (void)next_.SetError(EINVAL); }
1980 template<
class Derived>
1983 Derived& ref =
static_cast<Derived&
>(*this);
1984 if (!ref.value_)
return EINVAL;
1986 typedef R (*CONT)(Derived&);
1987 UniquePtr<FutureContinuation<Derived, R, CONT> > ptr(
1988 new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
1989 if (!ptr)
return ENOMEM;
1991 if (e != 0)
return e;
1992 e = ptr->GetFuture(next);
1993 if (e != 0)
return e;
1995 ref.value_->common.Lock();
1996 ref.value_->common.cont = ptr.release();
1997 bool isready = ref.IsReady_();
1998 ref.value_->common.Unlock();
2000 ref.value_->common.cont->DoContinuation();
2007 template<
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
2008 struct FutureTuple {
2017 struct FutureTuple<None, None, None, None, None>;
2019 struct FutureTuple<R1, None, None, None, None>;
2021 template<
class R1,
class R2>
2022 struct FutureTuple<R1, R2, None, None, None> {
2027 template<
class R1,
class R2,
class R3>
2028 struct FutureTuple<R1, R2, R3, None, None> {
2034 template<
class R1,
class R2,
class R3,
class R4>
2035 struct FutureTuple<R1, R2, R3, R4, None> {
2042 template<
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
2049 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
2053 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
2058 typedef void (*FuncType)(ArgType& ptr);
2061 static void Call(ArgType& ptr) {
2065 static void CallWhenAny(ArgType& ptr) {
2067 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2068 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady() ||
2069 ptr->tuple_->f5.IsReady()) {
2074 ptr->promise_.SetValue(ptr->tuple_.release());
2076 static void CallWhenAll(ArgType& ptr) {
2077 ptr->tuple_->f1.Wait();
2078 ptr->tuple_->f2.Wait();
2079 ptr->tuple_->f3.Wait();
2080 ptr->tuple_->f4.Wait();
2081 ptr->tuple_->f5.Wait();
2082 ptr->promise_.SetValue(ptr->tuple_.release());
2084 explicit WhenFutureComplete(FuncType f) : func_(f) {}
2085 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2086 Future<R4>* f4, Future<R5>* f5) {
2088 if (e != 0)
return e;
2089 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
2090 if (!tuple_)
return ENOMEM;
2091 e = promise_.GetFuture(f);
2092 if (e != 0)
return e;
2093 e = tuple_->f1.MakeSharedFrom(*f1);
2094 if (e != 0)
return e;
2095 e = tuple_->f2.MakeSharedFrom(*f2);
2096 if (e != 0)
return e;
2097 e = tuple_->f3.MakeSharedFrom(*f3);
2098 if (e != 0)
return e;
2099 e = tuple_->f4.MakeSharedFrom(*f4);
2100 if (e != 0)
return e;
2101 e = tuple_->f5.MakeSharedFrom(*f5);
2102 if (e != 0)
return e;
2109 Promise<ReturnType> promise_;
2111 friend class Thread;
2114 template<
class R1,
class R2,
class R3,
class R4,
class R5>
2116 WhenFutureComplete<R1, R2, R3, R4, R5>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
2117 Future<R3>* f3, Future<R4>* f4, Future<R5>* f5,
2119 if (!f1 || !f2 || !f3 || !f4 || !f5)
return EINVAL;
2120 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
2123 e = ptr->Init(f, f1, f2, f3, f4, f5);
2124 if (e != 0)
return e;
2126 e = th.StartRaw(ptr);
2127 if (e != 0)
return e;
2132 class WhenFutureComplete<None, None, None, None, None>;
2134 class WhenFutureComplete<R1, None, None, None, None>;
2136 template<
class R1,
class R2>
2137 class WhenFutureComplete<R1, R2, None, None, None> {
2139 typedef UniquePtr<FutureTuple<R1, R2> > ReturnType;
2140 typedef Future<ReturnType> FutureType;
2141 static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2) {
2142 return DoWhen(f, f1, f2, CallWhenAll);
2144 static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2) {
2145 return DoWhen(f, f1, f2, CallWhenAny);
2149 typedef UniquePtr<WhenFutureComplete> ArgType;
2150 typedef void (*FuncType)(ArgType& ptr);
2151 static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, FuncType func);
2152 static void Call(ArgType& ptr) {
2156 static void CallWhenAny(ArgType& ptr) {
2158 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady()) {
2163 ptr->promise_.SetValue(ptr->tuple_.release());
2165 static void CallWhenAll(ArgType& ptr) {
2166 ptr->tuple_->f1.Wait();
2167 ptr->tuple_->f2.Wait();
2168 ptr->promise_.SetValue(ptr->tuple_.release());
2170 explicit WhenFutureComplete(FuncType f) : func_(f) {}
2171 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2) {
2173 if (e != 0)
return e;
2174 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2>());
2175 if (!tuple_)
return ENOMEM;
2176 e = promise_.GetFuture(f);
2177 if (e != 0)
return e;
2178 e = tuple_->f1.MakeSharedFrom(*f1);
2179 if (e != 0)
return e;
2180 e = tuple_->f2.MakeSharedFrom(*f2);
2181 if (e != 0)
return e;
2188 Promise<ReturnType> promise_;
2190 friend class Thread;
2193 template<
class R1,
class R2>
2194 errno_t inline WhenFutureComplete<R1, R2>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
2196 if (!f1 || !f2)
return EINVAL;
2197 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
2200 e = ptr->Init(f, f1, f2);
2201 if (e != 0)
return e;
2203 e = th.StartRaw(ptr);
2204 if (e != 0)
return e;
2208 template<
class R1,
class R2,
class R3>
2209 class WhenFutureComplete<R1, R2, R3, None, None> {
2211 typedef UniquePtr<FutureTuple<R1, R2, R3> > ReturnType;
2212 typedef Future<ReturnType> FutureType;
2213 static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
2214 return DoWhen(f, f1, f2, f3, CallWhenAll);
2216 static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
2217 return DoWhen(f, f1, f2, f3, CallWhenAny);
2221 typedef UniquePtr<WhenFutureComplete> ArgType;
2222 typedef void (*FuncType)(ArgType& ptr);
2224 DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3, FuncType func);
2225 static void Call(ArgType& ptr) {
2229 static void CallWhenAny(ArgType& ptr) {
2231 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2232 ptr->tuple_->f3.IsReady()) {
2237 ptr->promise_.SetValue(ptr->tuple_.release());
2239 static void CallWhenAll(ArgType& ptr) {
2240 ptr->tuple_->f1.Wait();
2241 ptr->tuple_->f2.Wait();
2242 ptr->tuple_->f3.Wait();
2243 ptr->promise_.SetValue(ptr->tuple_.release());
2245 explicit WhenFutureComplete(FuncType f) : func_(f) {}
2246 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
2248 if (e != 0)
return e;
2249 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3>());
2250 if (!tuple_)
return ENOMEM;
2251 e = promise_.GetFuture(f);
2252 if (e != 0)
return e;
2253 e = tuple_->f1.MakeSharedFrom(*f1);
2254 if (e != 0)
return e;
2255 e = tuple_->f2.MakeSharedFrom(*f2);
2256 if (e != 0)
return e;
2257 e = tuple_->f3.MakeSharedFrom(*f3);
2258 if (e != 0)
return e;
2265 Promise<ReturnType> promise_;
2267 friend class Thread;
2270 template<
class R1,
class R2,
class R3>
2271 inline errno_t WhenFutureComplete<R1, R2, R3>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
2272 Future<R3>* f3, FuncType func) {
2273 if (!f1 || !f2 || !f3)
return EINVAL;
2274 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
2277 e = ptr->Init(f, f1, f2, f3);
2278 if (e != 0)
return e;
2280 e = th.StartRaw(ptr);
2281 if (e != 0)
return e;
2285 template<
class R1,
class R2,
class R3,
class R4>
2286 class WhenFutureComplete<R1, R2, R3, R4, None> {
2288 typedef UniquePtr<FutureTuple<R1, R2, R3, R4> > ReturnType;
2289 typedef Future<ReturnType> FutureType;
2291 All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3, Future<R4>* f4) {
2292 return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2295 Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3, Future<R4>* f4) {
2296 return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2300 typedef UniquePtr<WhenFutureComplete> ArgType;
2301 typedef void (*FuncType)(ArgType& ptr);
2302 static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2303 Future<R4>* f4, FuncType func);
2304 static void Call(ArgType& ptr) {
2308 static void CallWhenAny(ArgType& ptr) {
2310 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2311 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady()) {
2316 ptr->promise_.SetValue(ptr->tuple_.release());
2318 static void CallWhenAll(ArgType& ptr) {
2319 ptr->tuple_->f1.Wait();
2320 ptr->tuple_->f2.Wait();
2321 ptr->tuple_->f3.Wait();
2322 ptr->tuple_->f4.Wait();
2323 ptr->promise_.SetValue(ptr->tuple_.release());
2325 explicit WhenFutureComplete(FuncType f) : func_(f) {}
2327 Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3, Future<R4>* f4) {
2329 if (e != 0)
return e;
2330 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2331 if (!tuple_)
return ENOMEM;
2332 e = promise_.GetFuture(f);
2333 if (e != 0)
return e;
2334 e = tuple_->f1.MakeSharedFrom(*f1);
2335 if (e != 0)
return e;
2336 e = tuple_->f2.MakeSharedFrom(*f2);
2337 if (e != 0)
return e;
2338 e = tuple_->f3.MakeSharedFrom(*f3);
2339 if (e != 0)
return e;
2340 e = tuple_->f4.MakeSharedFrom(*f4);
2341 if (e != 0)
return e;
2348 Promise<ReturnType> promise_;
2350 friend class Thread;
2353 template<
class R1,
class R2,
class R3,
class R4>
2355 WhenFutureComplete<R1, R2, R3, R4>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
2356 Future<R3>* f3, Future<R4>* f4, FuncType func) {
2357 if (!f1 || !f2 || !f3 || !f4)
return EINVAL;
2358 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
2361 e = ptr->Init(f, f1, f2, f3, f4);
2362 if (e != 0)
return e;
2364 e = th.StartRaw(ptr);
2365 if (e != 0)
return e;
2372 NLIB_DEFINE_STD_SWAP_T_BEGIN3(
nn, nlib, threading)
2373 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::Future)
2374 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise)
2375 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask)
2376 NLIB_DEFINE_STD_SWAP_T_END3(
nn, nlib, threading)
2378 #endif // INCLUDE_NN_NLIB_THREADING_FUTURE_H_ errno_t MakeReadyFuture(Future< R > *future, const R &value)
予め値が設定されたFutureを作成します。
#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
結果が取得できる状態になるまで待ちます。
Future(Future &rhs, move_tag) noexcept
ムーブコンストラクタに相当します。
void SetDetachState(bool detached) noexcept
デタッチした状態でスレッドを起動するかどうかを設定します。
errno_t GetFuture(Future< R > *p) noexcept
実行結果を取得するためのFutureを設定します。
C++11環境(エイリアステンプレートが可能な環境)においてはstd::unique_ptrにエイリアステンプレートされま...
std::unique_ptrに相当するクラスが定義されています。
Promise & assign(Promise &rhs, move_tag) noexcept
ムーブ代入演算子に相当します。
errno_t WaitUntil(const DateTime &datetime) noexcept
指定された時刻までの間、結果が取得できる状態になるまで待ちます。
スレッド実行の結果を呼び出しスレッドに対してスレッドセーフに出力するためのクラスです。C++11のstd::pro...
R Get()
内部で値となる型のオブジェクトを構築してから、Get(R* ptr)を呼び出します。
bool IsValid() const noexcept
FutureがPromiseと関連付けられているかどうかを返します。
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 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等をラップしてコンストラクタでロック、デストラクタでアンロックします。 ...
関数をラップし、別スレッドで実行し戻り値をスレッドセーフに取得できるようにするクラスです。C++11のstd:...
Promise() noexcept
デフォルトコンストラクタです。
bool IsReady() const noexcept
Future に値が設定されている(Promiseが値かエラーを設定した)かどうかを返します。
PackagedTask< T > ThisType
このオブジェクトの型です。
errno_t Then(Future< RNEXT > *next, RNEXT(*cont)(Future< R > &)) noexcept
このフューチャーに対して引き続き行う処理(continuation)を登録します。
Future< ReturnType > FutureType
新たに作成されるFutureの型です。
Future() noexcept
デフォルトコンストラクタです。
Future & assign(Future &rhs, move_tag) noexcept
ムーブ代入演算子に相当します。
errno_t Init() noexcept
オブジェクトの初期化を行います。
Promise(Promise &rhs, move_tag) noexcept
ムーブコンストラクタに相当します。
UniquePtr< FutureTuple< R1, R2, R3, R4, R5 > > ReturnType
新たに作成されるFutureに設定される値の型です。