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;
73 static_cast<Derived&
>(*this).value_.swap(rhs.value_);
78 bool IsValid() const NLIB_NOEXCEPT {
79 const Derived& ref =
static_cast<const Derived&
>(*this);
84 Derived& ref =
static_cast<Derived&
>(*this);
85 return ref.value_.MakeSharedFrom(f.value_);
91 bool IsReady_() const NLIB_NOEXCEPT {
92 return static_cast<const Derived&
>(*this).value_->common.IsReady();
96 template <
class Derived>
97 bool FutureBase<Derived>::IsReady() const NLIB_NOEXCEPT {
98 const Derived& ref =
static_cast<const Derived&
>(*this);
100 ref.value_->common.Lock();
101 bool rval = IsReady_();
102 ref.value_->common.Unlock();
109 template <
class Derived>
110 errno_t FutureBase<Derived>::Wait() NLIB_NOEXCEPT {
111 Derived& ref =
static_cast<Derived&
>(*this);
112 NLIB_ASSERT(ref.value_);
113 if (!ref.value_)
return EINVAL;
114 ref.value_->common.Lock();
115 while (!IsReady_()) {
116 errno_t e = ref.value_->common.Wait();
118 ref.value_->common.Unlock();
119 NLIB_ASSERT_NOERR(e);
123 ref.value_->common.Unlock();
127 template <
class Derived>
128 errno_t FutureBase<Derived>::WaitFor(
const TimeSpan& span) NLIB_NOEXCEPT {
129 Derived& ref =
static_cast<Derived&
>(*this);
130 NLIB_ASSERT(ref.value_);
131 if (!ref.value_)
return EINVAL;
133 errno_t e = DateTime::GetNow(&abstime);
135 if (e != 0)
return e;
136 ref.value_->common.Lock();
137 while (!IsReady_()) {
144 &ref.value_->common.lock,
147 ref.value_->common.Unlock();
151 ref.value_->common.Unlock();
155 template <
class Derived>
156 errno_t FutureBase<Derived>::WaitUntil(
const DateTime& datetime) NLIB_NOEXCEPT {
157 Derived& ref =
static_cast<Derived&
>(*this);
158 NLIB_ASSERT(ref.value_);
159 if (!ref.value_)
return EINVAL;
160 ref.value_->common.Lock();
161 while (!IsReady_()) {
163 &ref.value_->common.lock,
164 datetime.ToTimeValue().tick);
166 ref.value_->common.Unlock();
170 ref.value_->common.Unlock();
177 template <
class Derived>
180 PromiseBase() NLIB_NOEXCEPT {}
181 #ifdef __cpp_rvalue_references 182 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 183 PromiseBase(PromiseBase&& rhs) =
default;
184 PromiseBase& operator=(PromiseBase&&) =
default;
189 Derived& ref =
static_cast<Derived&
>(*this);
190 swap(ref.value_, rhs.value_);
194 bool IsValid() const NLIB_NOEXCEPT {
195 const Derived& ref =
static_cast<const Derived&
>(*this);
203 struct NLIB_CAPABILITY("mutex") CommonStatus {
205 detail::FutureContinuationBase* cont;
209 CommonStatus() NLIB_NOEXCEPT
210 : status(0), cont(NULL), err(0) {
214 NLIB_ASSERT_NOERR(e);
216 NLIB_ASSERT_NOERR(e);
218 ~CommonStatus() NLIB_NOEXCEPT {
219 if (cont)
delete cont;
223 NLIB_ASSERT_NOERR(e);
225 NLIB_ASSERT_NOERR(e);
227 void Lock() NLIB_NOEXCEPT NLIB_ACQUIRE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
231 NLIB_ASSERT_NOERR(e);
233 void Unlock() NLIB_NOEXCEPT NLIB_RELEASE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
237 NLIB_ASSERT_NOERR(e);
239 errno_t Wait() NLIB_NOEXCEPT NLIB_REQUIRES(*this) NLIB_NO_THREAD_SAFETY_ANALYSIS {
242 bool IsReady() NLIB_NOEXCEPT {
243 return status == 20120915L;
245 bool SetReady() NLIB_NOEXCEPT {
246 if (status != 20120915L) {
253 void NotifyAndContinuation() NLIB_NOEXCEPT {
256 NLIB_ASSERT_NOERR(e);
258 if (cont) cont->DoContinuation();
261 void NotifyAndContinuation() NLIB_NOEXCEPT {
262 static_cast<Derived&
>(*this).value_->common.NotifyAndContinuation();
269 template <
class Derived>
270 errno_t PromiseBase<Derived>::Init() NLIB_NOEXCEPT {
274 Derived& ref =
static_cast<Derived&
>(*this);
275 if (ref.value_)
return EALREADY;
276 ref.value_.reset(
new (std::nothrow)
typename Derived::Status());
277 if (!ref.value_)
return ENOMEM;
281 template <
class Derived>
283 if (e == 0)
return 0;
284 Derived& ref =
static_cast<Derived&
>(*this);
287 if (ee != 0)
return ee;
290 ref.value_->common.Lock();
291 if (ref.value_->common.SetReady()) {
292 ref.value_->common.err = e;
293 ref.value_->common.Unlock();
295 ref.value_->common.Unlock();
299 this->NotifyAndContinuation();
303 template <
class Derived>
305 errno_t PromiseBase<Derived>::GetFuture(F* p) NLIB_NOEXCEPT {
306 if (!p)
return EINVAL;
307 Derived& ref =
static_cast<Derived&
>(*this);
310 if (e != 0)
return e;
312 errno_t e = p->value_.MakeSharedFrom(ref.value_);
313 if (e != 0)
return e;
320 class Promise :
public detail::PromiseBase<Promise<R> > {
321 typedef detail::PromiseBase<Promise<R> > BaseType;
327 #ifdef __cpp_rvalue_references 328 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 334 value_ = std::move(rhs.value_);
344 errno_t SetValue(
const R& value);
353 return BaseType::GetFuture(p);
358 typename BaseType::CommonStatus common;
361 LimitedSharedPtr<Status> value_;
366 friend class detail::PromiseBase;
373 if (e != 0)
return e;
377 if (value_->common.SetReady()) {
379 value_->data = value;
381 #ifdef __cpp_exceptions 382 NLIB_RETHROW_UNWIND {
383 this->SetError(ECANCELED);
387 return this->SetError(EINVAL);
394 this->NotifyAndContinuation();
398 template <
class T,
class DEL>
399 class Promise<UniquePtr<T, DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
400 typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
405 #ifdef __cpp_rvalue_references 406 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 412 value_ = std::move(rhs.value_);
426 typename BaseType::CommonStatus common;
429 LimitedSharedPtr<Status> value_;
434 friend class detail::PromiseBase;
437 template <
class T,
class DEL>
441 if (e != 0)
return e;
444 value_->common.Lock();
445 if (value_->common.SetReady()) {
446 value_->data.reset(value);
447 value_->common.Unlock();
449 value_->common.Unlock();
453 this->NotifyAndContinuation();
457 template <
class T,
class DEL>
458 class Promise<UniquePtr<T[], DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
459 typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
464 #ifdef __cpp_rvalue_references 465 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 471 value_ = std::move(rhs.value_);
485 typename BaseType::CommonStatus common;
488 LimitedSharedPtr<Status> value_;
493 friend class detail::PromiseBase;
496 template <
class T,
class DEL>
500 if (e != 0)
return e;
503 value_->common.Lock();
504 if (value_->common.SetReady()) {
505 value_->data.reset(value);
506 value_->common.Unlock();
508 value_->common.Unlock();
512 this->NotifyAndContinuation();
517 class Promise<void> :
public detail::PromiseBase<Promise<void> > {
518 typedef detail::PromiseBase<Promise<void> > BaseType;
523 #ifdef __cpp_rvalue_references 524 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 530 value_ = std::move(rhs.value_);
544 BaseType::CommonStatus common;
546 LimitedSharedPtr<Status> value_;
551 friend class detail::PromiseBase;
555 class Promise<Future<R> > :
public detail::PromiseBase<Promise<Future<R> > > {
556 typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
561 #ifdef __cpp_rvalue_references 562 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 568 value_ = std::move(rhs.value_);
585 typename BaseType::CommonStatus common;
588 LimitedSharedPtr<Status> value_;
593 friend class detail::PromiseBase;
600 if (e != 0)
return e;
603 value_->common.Lock();
604 if (value_->common.SetReady()) {
605 errno_t e = value_->data.MakeSharedFrom(value);
606 value_->common.Unlock();
611 value_->common.Unlock();
615 this->NotifyAndContinuation();
620 class Future :
public detail::FutureBase<Future<R> > {
621 typedef detail::FutureBase<Future<R> > BaseType;
625 #ifdef __cpp_rvalue_references 626 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 627 Future(Future&& rhs) =
default;
628 Future& operator=(Future&& rhs) =
default;
630 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
631 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
632 value_ = std::move(rhs.value_);
646 NLIB_ASSERT_NOERR(e);
650 if (!ptr)
return EINVAL;
652 errno_t e = value_->common.err;
657 #ifdef __cpp_exceptions 658 NLIB_RETHROW_UNWIND {
667 bool IsValid() const NLIB_NOEXCEPT {
return BaseType::IsValid(); }
668 bool IsReady() const NLIB_NOEXCEPT {
return BaseType::IsReady(); }
671 return BaseType::WaitFor(span);
674 return BaseType::WaitUntil(datetime);
676 template <
class RNEXT>
678 return BaseType::Then(next, cont);
683 LimitedSharedPtr<typename Promise<R>::Status> value_;
688 friend class detail::FutureBase;
690 friend class detail::PromiseBase;
693 template <
class T,
class DEL>
694 class Future<UniquePtr<T, DEL> > :
public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
695 typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
698 Future() NLIB_NOEXCEPT {}
699 #ifdef __cpp_rvalue_references 700 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 701 Future(Future&& rhs) =
default;
702 Future& operator=(Future&& rhs) =
default;
704 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
705 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
706 value_ = std::move(rhs.value_);
712 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
716 T* Get() NLIB_NOEXCEPT {
718 return value_->data.get();
720 errno_t Get(T** ptr) NLIB_NOEXCEPT {
721 if (!ptr)
return EINVAL;
723 errno_t e = value_->common.err;
724 if (e == 0) *ptr = value_->data.get();
727 T* Release() NLIB_NOEXCEPT {
729 return value_->data.release();
733 LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> value_;
738 friend class detail::FutureBase;
740 friend class detail::PromiseBase;
743 template <
class T,
class DEL>
744 class Future<UniquePtr<T[], DEL> > :
public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
745 typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
748 Future() NLIB_NOEXCEPT {}
749 #ifdef __cpp_rvalue_references 750 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 751 Future(Future&& rhs) =
default;
752 Future& operator=(Future&& rhs) =
default;
754 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
755 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
756 value_ = std::move(rhs.value_);
762 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
766 T* Get() NLIB_NOEXCEPT {
768 return value_->data.get();
770 errno_t Get(T** ptr) NLIB_NOEXCEPT {
771 if (!ptr)
return EINVAL;
773 errno_t e = value_->common.err;
774 if (e == 0) *ptr = value_->data.get();
777 T* Release() NLIB_NOEXCEPT {
779 return value_->common.data.release();
783 LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> value_;
788 friend class detail::FutureBase;
790 friend class detail::PromiseBase;
794 class Future<void> :
public detail::FutureBase<Future<void> > {
795 typedef detail::FutureBase<Future<void> > BaseType;
798 Future() NLIB_NOEXCEPT {}
799 #ifdef __cpp_rvalue_references 800 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 801 Future(Future&& rhs) =
default;
802 Future& operator=(Future&& rhs) =
default;
804 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
805 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
806 value_ = std::move(rhs.value_);
812 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
818 return value_->common.err;
822 LimitedSharedPtr<Promise<void>::Status> value_;
827 friend class detail::FutureBase;
829 friend class detail::PromiseBase;
833 class Future<Future<R> > :
public detail::FutureBase<Future<Future<R> > > {
834 typedef detail::FutureBase<Future<Future<R> > > BaseType;
837 Future() NLIB_NOEXCEPT {}
838 #ifdef __cpp_rvalue_references 839 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 840 Future(Future&& rhs) =
default;
841 Future& operator=(Future&& rhs) =
default;
843 Future(Future&& rhs)
NLIB_NOEXCEPT : value_(std::move(rhs.value_)) {}
844 Future& operator=(Future&& rhs) NLIB_NOEXCEPT {
845 value_ = std::move(rhs.value_);
851 Future& assign(Future& rhs,
move_tag) NLIB_NOEXCEPT {
856 if (!inner)
return EINVAL;
858 errno_t e = value_->common.err;
859 if (e != 0)
return e;
864 LimitedSharedPtr<typename Promise<Future<R> >::Status> value_;
869 friend class detail::FutureBase;
871 friend class detail::PromiseBase;
877 class FuncHolderBase0 {
879 virtual ~FuncHolderBase0() {}
880 virtual R operator()() = 0;
883 template <
class R,
class T1>
884 class FuncHolderBase1 {
886 virtual ~FuncHolderBase1() {}
887 virtual R operator()(T1 NLIB_RREF arg1) = 0;
890 template <
class R,
class T1,
class T2>
891 class FuncHolderBase2 {
893 virtual ~FuncHolderBase2() {}
894 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0;
897 template <
class R,
class T1,
class T2,
class T3>
898 class FuncHolderBase3 {
900 virtual ~FuncHolderBase3() {}
901 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0;
904 template <
class R,
class T1,
class T2,
class T3,
class T4>
905 class FuncHolderBase4 {
907 virtual ~FuncHolderBase4() {}
908 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
909 T4 NLIB_RREF arg4) = 0;
912 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
913 class FuncHolderBase5 {
915 virtual ~FuncHolderBase5() {}
916 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
917 T5 NLIB_RREF arg5) = 0;
920 template <
class FUNC,
bool USESWAP>
927 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
934 template <
class FUNC>
935 class FuncWrap_<FUNC, false> {
937 FuncWrap_(FUNC& func) : func_(func) {}
938 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
945 template <
class FUNC>
946 class FuncWrap :
public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
947 typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
950 FuncWrap(FUNC& func) : BaseType(func) {}
954 class FuncWrap<R()> {
957 explicit FuncWrap(FUNC func) : func_(func) {}
958 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
965 template <
class R,
class T1>
966 class FuncWrap<R(T1)> {
968 typedef R (*FUNC)(T1);
969 explicit FuncWrap(FUNC func) : func_(func) {}
970 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
977 template <
class R,
class T1,
class T2>
978 class FuncWrap<R(T1, T2)> {
980 typedef R (*FUNC)(T1, T2);
981 explicit FuncWrap(FUNC func) : func_(func) {}
982 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
989 template <
class R,
class T1,
class T2,
class T3>
990 class FuncWrap<R(T1, T2, T3)> {
992 typedef R (*FUNC)(T1, T2, T3);
993 explicit FuncWrap(FUNC func) : func_(func) {}
994 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
1001 template <
class R,
class T1,
class T2,
class T3,
class T4>
1002 class FuncWrap<R(T1, T2, T3, T4)> {
1004 typedef R (*FUNC)(T1, T2, T3, T4);
1005 explicit FuncWrap(FUNC func) : func_(func) {}
1006 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
1013 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1014 class FuncWrap<R(T1, T2, T3, T4, T5)> {
1016 typedef R (*FUNC)(T1, T2, T3, T4, T5);
1017 explicit FuncWrap(FUNC func) : func_(func) {}
1018 FUNC&
get() NLIB_NOEXCEPT {
return func_; }
1025 template <
class FUNC,
class R>
1026 class FuncHolder0 :
public FuncHolderBase0<R> {
1028 FuncHolder0(FUNC& f) : func_(f) {}
1031 return func_.get()();
1035 FuncWrap<FUNC> func_;
1038 template <
class FUNC,
class R,
class T1>
1039 class FuncHolder1 :
public FuncHolderBase1<R, T1> {
1041 FuncHolder1(FUNC& f) : func_(f) {}
1044 return func_.get()(NLIB_FWD(T1, arg1));
1048 FuncWrap<FUNC> func_;
1051 template <
class FUNC,
class R,
class T1,
class T2>
1052 class FuncHolder2 :
public FuncHolderBase2<R, T1, T2> {
1054 FuncHolder2(FUNC& f) : func_(f) {}
1056 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)
NLIB_OVERRIDE {
1057 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1061 FuncWrap<FUNC> func_;
1064 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1065 class FuncHolder3 :
public FuncHolderBase3<R, T1, T2, T3> {
1067 FuncHolder3(FUNC& f) : func_(f) {}
1069 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)
NLIB_OVERRIDE {
1070 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1074 FuncWrap<FUNC> func_;
1077 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1078 class FuncHolder4 :
public FuncHolderBase4<R, T1, T2, T3, T4> {
1080 FuncHolder4(FUNC& f) : func_(f) {}
1082 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1084 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1085 NLIB_FWD(T4, arg4));
1089 FuncWrap<FUNC> func_;
1092 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1093 class FuncHolder5 :
public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
1095 FuncHolder5(FUNC& f) : func_(f) {}
1097 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1099 return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1100 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1104 FuncWrap<FUNC> func_;
1114 template <class FUNC>
1117 errno_t GetFuture(Future<R>* p) NLIB_NOEXCEPT;
1124 typedef R ReturnType;
1127 #ifdef __cpp_rvalue_references 1128 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1133 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {}
1135 func_ = std::move(rhs.func_);
1136 promise_ = std::move(rhs.promise_);
1142 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {}
1144 func_.reset(rhs.func_.release());
1145 promise_.assign(rhs.promise_,
move_tag());
1150 swap(func_, rhs.func_);
1151 swap(promise_, rhs.promise_);
1153 template <
class FUNC>
1156 if (e != 0)
return e;
1157 func_.reset(
new (std::nothrow) detail::FuncHolder0<FUNC, R>(func));
1158 return !func_ ? ENOMEM : 0;
1166 template <
class DUMMY>
1167 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec() {
1169 R rval = (*func_)();
1172 promise_.SetValue(rval);
1174 promise_.SetError(e);
1177 #ifdef __cpp_exceptions 1178 NLIB_RETHROW_UNWIND {
1179 promise_.SetError(ECANCELED);
1182 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1185 template <
class DUMMY>
1186 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec() {
1189 promise_.SetValue();
1191 #ifdef __cpp_exceptions 1192 NLIB_RETHROW_UNWIND {
1193 promise_.SetError(ECANCELED);
1196 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1205 template <
class R,
class T1>
1208 typedef R ReturnType;
1211 #ifdef __cpp_rvalue_references 1212 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1217 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1220 func_ = std::move(rhs.func_);
1221 promise_ = std::move(rhs.promise_);
1227 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1230 func_.reset(rhs.func_.release());
1231 promise_.assign(rhs.promise_,
move_tag());
1236 swap(func_, rhs.func_);
1237 swap(promise_, rhs.promise_);
1239 template <
class FUNC>
1242 if (e != 0)
return e;
1243 func_.reset(
new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func));
1244 return !func_ ? ENOMEM : 0;
1247 void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1250 template <
class DUMMY>
1251 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(T1 NLIB_RREF arg1) {
1253 R rval = (*func_)(NLIB_FWD(T1, arg1));
1256 promise_.SetValue(rval);
1258 promise_.SetError(e);
1261 #ifdef __cpp_exceptions 1262 NLIB_RETHROW_UNWIND {
1263 promise_.SetError(ECANCELED);
1266 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1269 template <
class DUMMY>
1270 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(T1 NLIB_RREF arg1) {
1272 (*func_)(NLIB_FWD(T1, arg1));
1273 promise_.SetValue();
1275 #ifdef __cpp_exceptions 1276 NLIB_RETHROW_UNWIND {
1277 promise_.SetError(ECANCELED);
1280 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1289 template <
class R,
class T1,
class T2>
1292 typedef R ReturnType;
1295 #ifdef __cpp_rvalue_references 1296 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1301 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1304 func_ = std::move(rhs.func_);
1305 promise_ = std::move(rhs.promise_);
1311 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1314 func_.reset(rhs.func_.release());
1315 promise_.assign(rhs.promise_,
move_tag());
1320 swap(func_, rhs.func_);
1321 swap(promise_, rhs.promise_);
1323 template <
class FUNC>
1326 if (e != 0)
return e;
1327 func_.reset(
new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func));
1328 return !func_ ? ENOMEM : 0;
1331 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1332 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1336 template <
class DUMMY>
1337 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1338 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1340 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1343 promise_.SetValue(rval);
1345 promise_.SetError(e);
1348 #ifdef __cpp_exceptions 1349 NLIB_RETHROW_UNWIND {
1350 promise_.SetError(ECANCELED);
1353 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1356 template <
class DUMMY>
1357 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1358 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1360 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1361 promise_.SetValue();
1363 #ifdef __cpp_exceptions 1364 NLIB_RETHROW_UNWIND {
1365 promise_.SetError(ECANCELED);
1368 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1377 template <
class R,
class T1,
class T2,
class T3>
1380 typedef R ReturnType;
1383 #ifdef __cpp_rvalue_references 1384 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1389 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1392 func_ = std::move(rhs.func_);
1393 promise_ = std::move(rhs.promise_);
1399 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1402 func_.reset(rhs.func_.release());
1403 promise_.assign(rhs.promise_,
move_tag());
1408 swap(func_, rhs.func_);
1409 swap(promise_, rhs.promise_);
1411 template <
class FUNC>
1414 if (e != 0)
return e;
1415 func_.reset(
new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func));
1416 return !func_ ? ENOMEM : 0;
1419 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1420 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1424 template <
class DUMMY>
1425 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1426 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1428 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1431 promise_.SetValue(rval);
1433 promise_.SetError(e);
1436 #ifdef __cpp_exceptions 1437 NLIB_RETHROW_UNWIND {
1438 promise_.SetError(ECANCELED);
1441 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1444 template <
class DUMMY>
1445 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1446 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1448 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1449 promise_.SetValue();
1451 #ifdef __cpp_exceptions 1452 NLIB_RETHROW_UNWIND {
1453 promise_.SetError(ECANCELED);
1456 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1465 template <
class R,
class T1,
class T2,
class T3,
class T4>
1468 typedef R ReturnType;
1471 #ifdef __cpp_rvalue_references 1472 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1477 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1480 func_ = std::move(rhs.func_);
1481 promise_ = std::move(rhs.promise_);
1487 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1490 func_.reset(rhs.func_.release());
1491 promise_.assign(rhs.promise_,
move_tag());
1496 swap(func_, rhs.func_);
1497 swap(promise_, rhs.promise_);
1499 template <
class FUNC>
1502 if (e != 0)
return e;
1503 func_.reset(
new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func));
1504 return !func_ ? ENOMEM : 0;
1507 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1508 T4 NLIB_RREF arg4) {
1509 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1513 template <
class DUMMY>
1514 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1515 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1517 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1518 NLIB_FWD(T4, arg4));
1521 promise_.SetValue(rval);
1523 promise_.SetError(e);
1526 #ifdef __cpp_exceptions 1527 NLIB_RETHROW_UNWIND {
1528 promise_.SetError(ECANCELED);
1531 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1534 template <
class DUMMY>
1535 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1536 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1538 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1539 NLIB_FWD(T4, arg4));
1540 promise_.SetValue();
1542 #ifdef __cpp_exceptions 1543 NLIB_RETHROW_UNWIND {
1544 promise_.SetError(ECANCELED);
1547 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1556 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1559 typedef R ReturnType;
1562 #ifdef __cpp_rvalue_references 1563 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS 1568 : func_(std::move(rhs.func_)), promise_(std::move(rhs.promise_)) {
1571 func_ = std::move(rhs.func_);
1572 promise_ = std::move(rhs.promise_);
1578 : func_(rhs.func_.release()), promise_(rhs.promise_,
move_tag()) {
1581 func_.reset(rhs.func_.release());
1582 promise_.assign(rhs.promise_,
move_tag());
1587 swap(func_, rhs.func_);
1588 swap(promise_, rhs.promise_);
1590 template <
class FUNC>
1593 if (e != 0)
return e;
1594 func_.reset(
new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func));
1595 return !func_ ? ENOMEM : 0;
1598 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1599 T5 NLIB_RREF arg5) {
1600 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1601 NLIB_FWD(T5, arg5));
1605 template <
class DUMMY>
1606 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1607 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1608 T5 NLIB_RREF arg5) {
1610 R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1611 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1614 promise_.SetValue(rval);
1616 promise_.SetError(e);
1619 #ifdef __cpp_exceptions 1620 NLIB_RETHROW_UNWIND {
1621 promise_.SetError(ECANCELED);
1624 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1627 template <
class DUMMY>
1628 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1629 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1630 T5 NLIB_RREF arg5) {
1632 (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1633 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1634 promise_.SetValue();
1636 #ifdef __cpp_exceptions 1637 NLIB_RETHROW_UNWIND {
1638 promise_.SetError(ECANCELED);
1641 NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1652 template <
class T,
bool B>
1654 explicit XHolder(
const T& value_) : value() {
1656 swap(const_cast<T&>(value_), value);
1662 struct XHolder<T, false> {
1663 explicit XHolder(
const T& value_) : value(value_) {}
1668 struct XHolder<R(), false> {
1669 XHolder(R (*value_)()) : value(value_) {}
1673 template <
class R,
class T1>
1674 struct XHolder<R(T1), false> {
1675 XHolder(R (*value_)(T1)) : value(value_) {}
1679 template <
class R,
class T1,
class T2>
1680 struct XHolder<R(T1, T2), false> {
1681 XHolder(R (*value_)(T1, T2)) : value(value_) {}
1685 template <
class R,
class T1,
class T2,
class T3>
1686 struct XHolder<R(T1, T2, T3), false> {
1687 XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1688 R (*value)(T1, T2, T3);
1691 template <
class R,
class T1,
class T2,
class T3,
class T4>
1692 struct XHolder<R(T1, T2, T3, T4), false> {
1693 XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1694 R (*value)(T1, T2, T3, T4);
1697 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1698 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1699 XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1700 R (*value)(T1, T2, T3, T4, T5);
1703 #define NLIB_ASYNC_HOLDER(T, B) \ 1704 XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value> 1705 #ifdef __cpp_rvalue_references 1706 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1707 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && \ 1708 !IsPointer<FUNC>::value> 1710 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \ 1711 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && \ 1712 !IsPointer<FUNC>::value> 1715 template <
class FUNC,
class R,
class BF>
1719 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1721 if (e != 0)
return e;
1723 if (e != 0)
return e;
1729 template <
class FUNC,
class R,
class BF,
class T1>
1734 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1736 if (e != 0)
return e;
1738 if (e != 0)
return e;
1740 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1745 template <
class FUNC,
class R,
class BF,
class T1,
class T2>
1746 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
1750 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1752 if (e != 0)
return e;
1754 if (e != 0)
return e;
1756 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1757 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1758 e = th.
Start(settings, task, arg1_.value, arg2_.value,
move_tag());
1762 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3>
1763 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1767 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1769 if (e != 0)
return e;
1771 if (e != 0)
return e;
1773 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1774 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1775 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1776 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value,
move_tag());
1780 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4>
1781 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1785 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1787 if (e != 0)
return e;
1789 if (e != 0)
return e;
1791 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1792 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1793 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1794 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1795 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value,
move_tag());
1799 template <
class FUNC,
class R,
class BF,
class T1,
class T2,
class T3,
class T4,
class T5>
1800 errno_t Async_(
Future<R>* future,
const FUNC& func,
const T1& arg1,
const T2& arg2,
const T3& arg3,
1801 const T4& arg4,
const T5& arg5,
const ThreadSettings& settings, BF) {
1804 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1806 if (e != 0)
return e;
1808 if (e != 0)
return e;
1810 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1811 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1812 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1813 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1814 NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1815 e = th.
Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1820 #undef NLIB_ASYNC_HOLDER 1821 #undef NLIB_ASYNC_HOLDER_F 1825 template <
class FUNC,
class R>
1827 return detail::Async_(future, func, settings, FalseType());
1830 template <
class FUNC,
class R>
1833 return detail::Async_(future, func, settings, TrueType());
1836 template <
class FUNC,
class R>
1840 return Async(future, func, settings);
1843 template <
class FUNC,
class R>
1850 template <
class FUNC,
class R,
class T1>
1853 return detail::Async_(future, func, arg1, settings, FalseType());
1856 template <
class FUNC,
class R,
class T1>
1859 return detail::Async_(future, func, arg1, settings, TrueType());
1862 template <
class FUNC,
class R,
class T1>
1866 return Async(future, func, arg1, settings);
1869 template <
class FUNC,
class R,
class T1>
1876 template <
class FUNC,
class R,
class T1,
class T2>
1879 return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1882 template <
class FUNC,
class R,
class T1,
class T2>
1885 return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1888 template <
class FUNC,
class R,
class T1,
class T2>
1892 return Async(future, func, arg1, arg2, settings);
1895 template <
class FUNC,
class R,
class T1,
class T2>
1900 return Async(future, func, arg1, arg2, settings,
move_tag());
1903 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1906 return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1909 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1912 return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1915 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1920 return Async(future, func, arg1, arg2, arg3, settings);
1923 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1928 return Async(future, func, arg1, arg2, arg3, settings,
move_tag());
1931 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1933 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings) {
1934 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1937 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1940 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1943 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1945 const T3& arg3,
const T4& arg4) {
1948 return Async(future, func, arg1, arg2, arg3, arg4, settings);
1951 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1953 const T3& arg3,
const T4& arg4,
move_tag) {
1956 return Async(future, func, arg1, arg2, arg3, arg4, settings,
move_tag());
1959 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1961 const T3& arg3,
const T4& arg4,
const T5& arg5,
1963 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1966 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1968 const T3& arg3,
const T4& arg4,
const T5& arg5,
const ThreadSettings& settings,
1970 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1973 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1975 const T3& arg3,
const T4& arg4,
const T5& arg5) {
1978 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1981 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1983 const T3& arg3,
const T4& arg4,
const T5& arg5,
move_tag) {
1986 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings,
move_tag());
1991 if (!future)
return EINVAL;
1994 if (e != 0)
return e;
1996 if (e != 0)
return e;
1998 if (e != 0)
return e;
2003 template <
class FUTURE,
class R,
typename CONT>
2004 class FutureContinuation :
public FutureContinuationBase {
2006 FutureContinuation(FUTURE& f, CONT cont) NLIB_NOEXCEPT
2010 errno_t Init() NLIB_NOEXCEPT {
return next_.Init(); }
2011 errno_t GetFuture(
Future<R>* future) NLIB_NOEXCEPT {
return next_.GetFuture(future); }
2012 virtual ~FutureContinuation() NLIB_NOEXCEPT
NLIB_OVERRIDE {}
2022 template <
class FUTURE,
class R,
typename CONT>
2023 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
2024 int32_t expected = 0;
2028 R rval = func_(parent_);
2031 (void)next_.SetValue(rval);
2033 (void)next_.SetError(e);
2036 #ifdef __cpp_exceptions 2037 NLIB_RETHROW_UNWIND {
2038 next_.SetError(ECANCELED);
2041 NLIB_CATCH(...) { (void)next_.SetError(EINVAL); }
2046 template <
class Derived>
2048 errno_t FutureBase<Derived>::Then(
Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT {
2049 Derived& ref =
static_cast<Derived&
>(*this);
2050 if (!ref.value_)
return EINVAL;
2052 typedef R (*CONT)(Derived&);
2054 new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
2055 if (!ptr)
return ENOMEM;
2057 if (e != 0)
return e;
2058 e = ptr->GetFuture(next);
2059 if (e != 0)
return e;
2061 ref.value_->common.Lock();
2062 ref.value_->common.cont = ptr.release();
2063 bool isready = ref.IsReady_();
2064 ref.value_->common.Unlock();
2066 ref.value_->common.cont->DoContinuation();
2073 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
2074 struct FutureTuple {
2083 struct FutureTuple<None, None, None, None, None>;
2085 struct FutureTuple<R1, None, None, None, None>;
2087 template <
class R1,
class R2>
2088 struct FutureTuple<R1, R2, None, None, None> {
2093 template <
class R1,
class R2,
class R3>
2094 struct FutureTuple<R1, R2, R3, None, None> {
2100 template <
class R1,
class R2,
class R3,
class R4>
2101 struct FutureTuple<R1, R2, R3, R4, None> {
2108 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
2115 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
2119 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
2124 typedef void (*FuncType)(ArgType& ptr);
2127 static void Call(ArgType& ptr) {
2131 static void CallWhenAny(ArgType& ptr) {
2133 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2134 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady() ||
2135 ptr->tuple_->f5.IsReady()) {
2140 ptr->promise_.SetValue(ptr->tuple_.
release());
2142 static void CallWhenAll(ArgType& ptr) {
2143 ptr->tuple_->f1.Wait();
2144 ptr->tuple_->f2.Wait();
2145 ptr->tuple_->f3.Wait();
2146 ptr->tuple_->f4.Wait();
2147 ptr->tuple_->f5.Wait();
2148 ptr->promise_.SetValue(ptr->tuple_.
release());
2154 if (e != 0)
return e;
2155 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
2156 if (!tuple_)
return ENOMEM;
2157 e = promise_.GetFuture(f);
2158 if (e != 0)
return e;
2159 e = tuple_->f1.MakeSharedFrom(*f1);
2160 if (e != 0)
return e;
2161 e = tuple_->f2.MakeSharedFrom(*f2);
2162 if (e != 0)
return e;
2163 e = tuple_->f3.MakeSharedFrom(*f3);
2164 if (e != 0)
return e;
2165 e = tuple_->f4.MakeSharedFrom(*f4);
2166 if (e != 0)
return e;
2167 e = tuple_->f5.MakeSharedFrom(*f5);
2168 if (e != 0)
return e;
2180 template <
class R1,
class R2,
class R3,
class R4,
class R5>
2185 if (!f1 || !f2 || !f3 || !f4 || !f5)
return EINVAL;
2189 e = ptr->Init(f, f1, f2, f3, f4, f5);
2190 if (e != 0)
return e;
2193 if (e != 0)
return e;
2202 template <
class R1,
class R2>
2208 return DoWhen(f, f1, f2, CallWhenAll);
2211 return DoWhen(f, f1, f2, CallWhenAny);
2216 typedef void (*FuncType)(ArgType& ptr);
2218 static void Call(ArgType& ptr) {
2222 static void CallWhenAny(ArgType& ptr) {
2224 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady()) {
2229 ptr->promise_.SetValue(ptr->tuple_.
release());
2231 static void CallWhenAll(ArgType& ptr) {
2232 ptr->tuple_->f1.Wait();
2233 ptr->tuple_->f2.Wait();
2234 ptr->promise_.SetValue(ptr->tuple_.
release());
2239 if (e != 0)
return e;
2240 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2>());
2241 if (!tuple_)
return ENOMEM;
2242 e = promise_.GetFuture(f);
2243 if (e != 0)
return e;
2244 e = tuple_->f1.MakeSharedFrom(*f1);
2245 if (e != 0)
return e;
2246 e = tuple_->f2.MakeSharedFrom(*f2);
2247 if (e != 0)
return e;
2259 template <
class R1,
class R2>
2262 if (!f1 || !f2)
return EINVAL;
2266 e = ptr->Init(f, f1, f2);
2267 if (e != 0)
return e;
2270 if (e != 0)
return e;
2274 template <
class R1,
class R2,
class R3>
2280 return DoWhen(f, f1, f2, f3, CallWhenAll);
2283 return DoWhen(f, f1, f2, f3, CallWhenAny);
2288 typedef void (*FuncType)(ArgType& ptr);
2291 static void Call(ArgType& ptr) {
2295 static void CallWhenAny(ArgType& ptr) {
2297 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2298 ptr->tuple_->f3.IsReady()) {
2303 ptr->promise_.SetValue(ptr->tuple_.
release());
2305 static void CallWhenAll(ArgType& ptr) {
2306 ptr->tuple_->f1.Wait();
2307 ptr->tuple_->f2.Wait();
2308 ptr->tuple_->f3.Wait();
2309 ptr->promise_.SetValue(ptr->tuple_.
release());
2314 if (e != 0)
return e;
2315 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3>());
2316 if (!tuple_)
return ENOMEM;
2317 e = promise_.GetFuture(f);
2318 if (e != 0)
return e;
2319 e = tuple_->f1.MakeSharedFrom(*f1);
2320 if (e != 0)
return e;
2321 e = tuple_->f2.MakeSharedFrom(*f2);
2322 if (e != 0)
return e;
2323 e = tuple_->f3.MakeSharedFrom(*f3);
2324 if (e != 0)
return e;
2336 template <
class R1,
class R2,
class R3>
2339 if (!f1 || !f2 || !f3)
return EINVAL;
2343 e = ptr->Init(f, f1, f2, f3);
2344 if (e != 0)
return e;
2347 if (e != 0)
return e;
2351 template <
class R1,
class R2,
class R3,
class R4>
2358 return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2362 return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2367 typedef void (*FuncType)(ArgType& ptr);
2370 static void Call(ArgType& ptr) {
2374 static void CallWhenAny(ArgType& ptr) {
2376 if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2377 ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady()) {
2382 ptr->promise_.SetValue(ptr->tuple_.
release());
2384 static void CallWhenAll(ArgType& ptr) {
2385 ptr->tuple_->f1.Wait();
2386 ptr->tuple_->f2.Wait();
2387 ptr->tuple_->f3.Wait();
2388 ptr->tuple_->f4.Wait();
2389 ptr->promise_.SetValue(ptr->tuple_.
release());
2395 if (e != 0)
return e;
2396 tuple_.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2397 if (!tuple_)
return ENOMEM;
2398 e = promise_.GetFuture(f);
2399 if (e != 0)
return e;
2400 e = tuple_->f1.MakeSharedFrom(*f1);
2401 if (e != 0)
return e;
2402 e = tuple_->f2.MakeSharedFrom(*f2);
2403 if (e != 0)
return e;
2404 e = tuple_->f3.MakeSharedFrom(*f3);
2405 if (e != 0)
return e;
2406 e = tuple_->f4.MakeSharedFrom(*f4);
2407 if (e != 0)
return e;
2419 template <
class R1,
class R2,
class R3,
class R4>
2422 if (!f1 || !f2 || !f3 || !f4)
return EINVAL;
2426 e = ptr->Init(f, f1, f2, f3, f4);
2427 if (e != 0)
return e;
2430 if (e != 0)
return e;
2437 NLIB_DEFINE_STD_SWAP_T_BEGIN3(
nn, nlib, threading)
2438 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::Future)
2439 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise)
2440 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask)
2441 NLIB_DEFINE_STD_SWAP_T_END3(
nn, nlib, threading)
2443 #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
デタッチ状態でスレッドを起動する設定かどうかを返します。
Future(Future &rhs, move_tag) noexcept
ムーブコンストラクタに相当します。
void SetDetachState(bool detached) noexcept
デタッチした状態でスレッドを起動するかどうかを設定します。
errno_t GetFuture(Future< R > *p) noexcept
実行結果を取得するためのFutureを設定します。
UniquePtrはポインタの所有権を保持し、UniquePtrがスコープから出るときにデストラクタでポインタをDELで指...
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 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
デフォルトコンストラクタです。
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に設定される値の型です。
T * release() noexcept
ポインタの所有権を手放し、ポインタを返します。
errno_t Init(FUNC &func)
初期化を行います。