3 #ifndef INCLUDE_NN_NLIB_THREADING_FUTURE_H_
4 #define INCLUDE_NN_NLIB_THREADING_FUTURE_H_
6 #include "nn/nlib/Swap.h"
11 #include "nn/nlib/threading/LimitedSharedPtr.h"
19 template <
class FutureResult>
36 virtual void DoContinuation() {}
42 template <
class FUTURE,
class R,
typename CONT>
43 class FutureContinuation;
45 template <
class Derived>
49 #ifdef NLIB_CXX11_RVALUE_REFERENCES
50 FutureBase(FutureBase&& rhs)
NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
54 errno_t WaitUntil(const DateTime& datetime) NLIB_NOEXCEPT;
55 bool IsValid() const NLIB_NOEXCEPT {
56 const Derived& ref =
static_cast<const Derived&
>(*this);
61 Derived& ref =
static_cast<Derived&
>(*this);
62 return ref.m_Value.MakeSharedFrom(f.m_Value);
65 errno_t Then(Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT;
66 void swap(Derived& rhs) NLIB_NOEXCEPT {
67 static_cast<Derived&
>(*this).m_Value.swap(rhs.m_Value);
71 bool IsReady_() const NLIB_NOEXCEPT {
72 return static_cast<const Derived&
>(*this).m_Value->common.IsReady();
76 template <
class Derived>
77 bool FutureBase<Derived>::IsReady() const NLIB_NOEXCEPT {
78 const Derived& ref =
static_cast<const Derived&
>(*this);
80 ref.m_Value->common.Lock();
81 bool rval = IsReady_();
82 ref.m_Value->common.Unlock();
89 template <
class Derived>
90 errno_t FutureBase<Derived>::Wait() NLIB_NOEXCEPT {
91 Derived& ref =
static_cast<Derived&
>(*this);
92 NLIB_ASSERT(ref.m_Value);
93 if (!ref.m_Value)
return EINVAL;
94 ref.m_Value->common.Lock();
97 &ref.m_Value->common.lock);
99 ref.m_Value->common.Unlock();
100 NLIB_ASSERT_NOERR(e);
104 ref.m_Value->common.Unlock();
108 template <
class Derived>
109 errno_t FutureBase<Derived>::WaitFor(
const TimeSpan& span) NLIB_NOEXCEPT {
110 Derived& ref =
static_cast<Derived&
>(*this);
111 NLIB_ASSERT(ref.m_Value);
112 if (!ref.m_Value)
return EINVAL;
114 errno_t e = DateTime::GetNow(&abstime);
116 if (e != 0)
return e;
117 ref.m_Value->common.Lock();
118 while (!IsReady_()) {
125 &ref.m_Value->common.lock,
126 abstime.ToTimeValue().tick);
128 ref.m_Value->common.Unlock();
132 ref.m_Value->common.Unlock();
136 template <
class Derived>
137 errno_t FutureBase<Derived>::WaitUntil(
const DateTime& datetime) NLIB_NOEXCEPT {
138 Derived& ref =
static_cast<Derived&
>(*this);
139 NLIB_ASSERT(ref.m_Value);
140 if (!ref.m_Value)
return EINVAL;
141 ref.m_Value->common.Lock();
142 while (!IsReady_()) {
144 &ref.m_Value->common.lock,
145 datetime.ToTimeValue().tick);
147 ref.m_Value->common.Unlock();
151 ref.m_Value->common.Unlock();
158 template <
class Derived>
161 PromiseBase() NLIB_NOEXCEPT {}
162 #ifdef NLIB_CXX11_RVALUE_REFERENCES
163 PromiseBase(PromiseBase&& rhs) NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
167 bool IsValid() const NLIB_NOEXCEPT {
168 const Derived& ref =
static_cast<const Derived&
>(*this);
169 return !!ref.m_Value;
174 void swap(Derived& rhs) NLIB_NOEXCEPT {
176 Derived& ref =
static_cast<Derived&
>(*this);
177 swap(ref.m_Value, rhs.m_Value);
181 struct CommonStatus {
183 detail::FutureContinuationBase* cont;
187 CommonStatus() NLIB_NOEXCEPT
188 : status(0), cont(NULL), err(0) {
192 NLIB_ASSERT_NOERR(e);
194 NLIB_ASSERT_NOERR(e);
196 ~CommonStatus() NLIB_NOEXCEPT {
197 if (cont)
delete cont;
201 NLIB_ASSERT_NOERR(e);
203 NLIB_ASSERT_NOERR(e);
205 void Lock() NLIB_NOEXCEPT {
209 NLIB_ASSERT_NOERR(e);
211 void Unlock() NLIB_NOEXCEPT {
215 NLIB_ASSERT_NOERR(e);
217 bool IsReady() NLIB_NOEXCEPT {
218 return status == 20120915L;
220 bool SetReady() NLIB_NOEXCEPT {
221 if (status != 20120915L) {
228 void NotifyAndContinuation() NLIB_NOEXCEPT {
231 NLIB_ASSERT_NOERR(e);
233 if (cont) cont->DoContinuation();
236 void NotifyAndContinuation() NLIB_NOEXCEPT {
237 static_cast<Derived&
>(*this).m_Value->common.NotifyAndContinuation();
244 template <
class Derived>
245 errno_t PromiseBase<Derived>::Init() NLIB_NOEXCEPT {
249 Derived& ref =
static_cast<Derived&
>(*this);
250 if (ref.m_Value)
return EALREADY;
251 ref.m_Value.reset(
new (std::nothrow)
typename Derived::Status());
252 if (!ref.m_Value)
return ENOMEM;
256 template <
class Derived>
258 if (e == 0)
return 0;
259 Derived& ref =
static_cast<Derived&
>(*this);
262 if (ee != 0)
return ee;
265 ref.m_Value->common.Lock();
266 if (ref.m_Value->common.SetReady()) {
267 ref.m_Value->common.err = e;
268 ref.m_Value->common.Unlock();
270 ref.m_Value->common.Unlock();
274 this->NotifyAndContinuation();
278 template <
class Derived>
280 errno_t PromiseBase<Derived>::GetFuture(F* p) NLIB_NOEXCEPT {
281 if (!p)
return EINVAL;
282 Derived& ref =
static_cast<Derived&
>(*this);
285 if (e != 0)
return e;
287 errno_t e = p->m_Value.MakeSharedFrom(ref.m_Value);
288 if (e != 0)
return e;
295 class Promise :
public detail::PromiseBase<Promise<R> > {
296 typedef detail::PromiseBase<Promise<R> > BaseType;
302 NLIB_MOVE_MEMBER_HELPER_1(Promise, m_Value)
303 errno_t SetValue(const R& value);
306 errno_t Init() NLIB_NOEXCEPT {
return BaseType::Init(); }
309 return BaseType::GetFuture(p);
315 typename BaseType::CommonStatus common;
318 LimitedSharedPtr<Status> m_Value;
323 friend class detail::PromiseBase;
330 if (e != 0)
return e;
334 if (m_Value->common.SetReady()) {
336 m_Value->data = value;
338 #ifdef NLIB_EXCEPTION_ENABLED
339 NLIB_RETHROW_UNWIND {
340 this->SetError(ECANCELED);
344 return this->SetError(EINVAL);
351 this->NotifyAndContinuation();
355 template <
class T,
class DEL>
356 class Promise<
UniquePtr<T, DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
357 typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
361 NLIB_MOVE_MEMBER_HELPER_1(Promise, m_Value)
362 errno_t SetValue(T* value) NLIB_NOEXCEPT;
366 typename BaseType::CommonStatus common;
369 LimitedSharedPtr<Status> m_Value;
374 friend class detail::PromiseBase;
377 template <
class T,
class DEL>
378 errno_t Promise<UniquePtr<T, DEL> >::SetValue(T* value) NLIB_NOEXCEPT {
381 if (e != 0)
return e;
384 m_Value->common.Lock();
385 if (m_Value->common.SetReady()) {
386 m_Value->data.reset(value);
387 m_Value->common.Unlock();
389 m_Value->common.Unlock();
393 this->NotifyAndContinuation();
397 template <
class T,
class DEL>
398 class Promise<UniquePtr<T[], DEL> > :
public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
399 typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
401 typedef Future<UniquePtr<T[], DEL> > FutureType;
402 Promise() NLIB_NOEXCEPT {}
403 NLIB_MOVE_MEMBER_HELPER_1(Promise, m_Value)
404 errno_t SetValue(T* value) NLIB_NOEXCEPT;
408 typename BaseType::CommonStatus common;
409 UniquePtr<T[], DEL> data;
411 LimitedSharedPtr<Status> m_Value;
416 friend class detail::PromiseBase;
419 template <
class T,
class DEL>
420 errno_t Promise<UniquePtr<T[], DEL> >::SetValue(T* value) NLIB_NOEXCEPT {
423 if (e != 0)
return e;
426 m_Value->common.Lock();
427 if (m_Value->common.SetReady()) {
428 m_Value->data.reset(value);
429 m_Value->common.Unlock();
431 m_Value->common.Unlock();
435 this->NotifyAndContinuation();
440 class Promise<void> :
public detail::PromiseBase<Promise<void> > {
441 typedef detail::PromiseBase<Promise<void> > BaseType;
443 typedef Future<void> FutureType;
444 Promise() NLIB_NOEXCEPT {}
445 NLIB_MOVE_MEMBER_HELPER_1(Promise, m_Value)
450 BaseType::CommonStatus common;
452 LimitedSharedPtr<Status> m_Value;
457 friend class detail::PromiseBase;
461 class Promise<Future<R> > :
public detail::PromiseBase<Promise<Future<R> > > {
462 typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
464 typedef Future<Future<R> > FutureType;
465 Promise() NLIB_NOEXCEPT {}
466 NLIB_MOVE_MEMBER_HELPER_1(Promise, m_Value)
467 errno_t SetValue(const Future<R>& value) NLIB_NOEXCEPT;
471 typename BaseType::CommonStatus common;
474 LimitedSharedPtr<Status> m_Value;
479 friend class detail::PromiseBase;
483 errno_t Promise<Future<R> >::SetValue(
const Future<R>& value) NLIB_NOEXCEPT {
486 if (e != 0)
return e;
489 m_Value->common.Lock();
490 if (m_Value->common.SetReady()) {
491 errno_t e = m_Value->data.MakeSharedFrom(value);
492 m_Value->common.Unlock();
497 m_Value->common.Unlock();
501 this->NotifyAndContinuation();
506 class Future :
public detail::FutureBase<Future<R> > {
507 typedef detail::FutureBase<Future<R> > BaseType;
511 NLIB_MOVE_MEMBER_HELPER_1(
Future, m_Value)
516 NLIB_ASSERT_NOERR(e);
520 if (!ptr)
return EINVAL;
522 errno_t e = m_Value->common.err;
525 *ptr = m_Value->data;
527 #ifdef NLIB_EXCEPTION_ENABLED
528 NLIB_RETHROW_UNWIND {
537 bool IsValid() const NLIB_NOEXCEPT {
return BaseType::IsValid(); }
538 bool IsReady() const NLIB_NOEXCEPT {
return BaseType::IsReady(); }
542 return BaseType::WaitUntil(datetime);
544 template <
class RNEXT>
546 return BaseType::Then(next, cont);
551 LimitedSharedPtr<typename Promise<R>::Status> m_Value;
556 friend class detail::FutureBase;
558 friend class detail::PromiseBase;
561 template <
class T,
class DEL>
562 class Future<
UniquePtr<T, DEL> > :
public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
563 typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
566 Future() NLIB_NOEXCEPT {}
567 NLIB_MOVE_MEMBER_HELPER_1(Future, m_Value)
568 T* Get() NLIB_NOEXCEPT {
570 return m_Value->data.get();
572 errno_t Get(T** ptr) NLIB_NOEXCEPT {
573 if (!ptr)
return EINVAL;
575 errno_t e = m_Value->common.err;
576 if (e == 0) *ptr = m_Value->data.get();
579 T* Release() NLIB_NOEXCEPT {
581 return m_Value->data.release();
585 LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> m_Value;
588 friend class Promise;
590 friend class detail::FutureBase;
592 friend class detail::PromiseBase;
595 template <
class T,
class DEL>
596 class Future<UniquePtr<T[], DEL> > :
public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
597 typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
600 Future() NLIB_NOEXCEPT {}
601 NLIB_MOVE_MEMBER_HELPER_1(Future, m_Value)
602 T* Get() NLIB_NOEXCEPT {
604 return m_Value->data.get();
606 errno_t Get(T** ptr) NLIB_NOEXCEPT {
607 if (!ptr)
return EINVAL;
609 errno_t e = m_Value->common.err;
610 if (e == 0) *ptr = m_Value->data.get();
613 T* Release() NLIB_NOEXCEPT {
615 return m_Value->common.data.release();
619 LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> m_Value;
622 friend class Promise;
624 friend class detail::FutureBase;
626 friend class detail::PromiseBase;
630 class Future<void> :
public detail::FutureBase<Future<void> > {
631 typedef detail::FutureBase<Future<void> > BaseType;
634 Future() NLIB_NOEXCEPT {}
635 NLIB_MOVE_MEMBER_HELPER_1(Future, m_Value)
638 return m_Value->common.err;
642 LimitedSharedPtr<Promise<void>::Status> m_Value;
645 friend class Promise;
647 friend class detail::FutureBase;
649 friend class detail::PromiseBase;
653 class Future<Future<R> > :
public detail::FutureBase<Future<Future<R> > > {
654 typedef detail::FutureBase<Future<Future<R> > > BaseType;
657 Future() NLIB_NOEXCEPT {}
658 NLIB_MOVE_MEMBER_HELPER_1(Future, m_Value)
659 errno_t Get(Future<R>* inner) NLIB_NOEXCEPT {
660 if (!inner)
return EINVAL;
662 errno_t e = m_Value->common.err;
663 if (e != 0)
return e;
664 return inner->MakeSharedFrom(m_Value->data);
668 LimitedSharedPtr<typename Promise<Future<R> >::Status> m_Value;
671 friend class Promise;
673 friend class detail::FutureBase;
675 friend class detail::PromiseBase;
681 class FuncHolderBase0 {
683 virtual ~FuncHolderBase0() {}
684 virtual R operator()() = 0;
687 template <
class R,
class T1>
688 class FuncHolderBase1 {
690 virtual ~FuncHolderBase1() {}
691 virtual R operator()(T1 NLIB_RREF arg1) = 0;
694 template <
class R,
class T1,
class T2>
695 class FuncHolderBase2 {
697 virtual ~FuncHolderBase2() {}
698 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0;
701 template <
class R,
class T1,
class T2,
class T3>
702 class FuncHolderBase3 {
704 virtual ~FuncHolderBase3() {}
705 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0;
708 template <
class R,
class T1,
class T2,
class T3,
class T4>
709 class FuncHolderBase4 {
711 virtual ~FuncHolderBase4() {}
712 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
713 T4 NLIB_RREF arg4) = 0;
716 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
717 class FuncHolderBase5 {
719 virtual ~FuncHolderBase5() {}
720 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
721 T5 NLIB_RREF arg5) = 0;
724 template <
class FUNC,
bool USESWAP>
727 FuncWrap_(FUNC& func) NLIB_NOEXCEPT : m_Func() {
731 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
738 template <
class FUNC>
739 class FuncWrap_<FUNC, false> {
741 FuncWrap_(FUNC& func) : m_Func(func) {}
742 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
749 template <
class FUNC>
750 class FuncWrap :
public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
751 typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
754 FuncWrap(FUNC& func) : BaseType(func) {}
758 class FuncWrap<R()> {
761 explicit FuncWrap(FUNC func) : m_Func(func) {}
762 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
769 template <
class R,
class T1>
770 class FuncWrap<R(T1)> {
772 typedef R (*FUNC)(T1);
773 explicit FuncWrap(FUNC func) : m_Func(func) {}
774 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
781 template <
class R,
class T1,
class T2>
782 class FuncWrap<R(T1, T2)> {
784 typedef R (*FUNC)(T1, T2);
785 explicit FuncWrap(FUNC func) : m_Func(func) {}
786 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
793 template <
class R,
class T1,
class T2,
class T3>
794 class FuncWrap<R(T1, T2, T3)> {
796 typedef R (*FUNC)(T1, T2, T3);
797 explicit FuncWrap(FUNC func) : m_Func(func) {}
798 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
805 template <
class R,
class T1,
class T2,
class T3,
class T4>
806 class FuncWrap<R(T1, T2, T3, T4)> {
808 typedef R (*FUNC)(T1, T2, T3, T4);
809 explicit FuncWrap(FUNC func) : m_Func(func) {}
810 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
817 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
818 class FuncWrap<R(T1, T2, T3, T4, T5)> {
820 typedef R (*FUNC)(T1, T2, T3, T4, T5);
821 explicit FuncWrap(FUNC func) : m_Func(func) {}
822 FUNC&
get() NLIB_NOEXCEPT {
return m_Func; }
829 template <
class FUNC,
class R>
830 class FuncHolder0 :
public FuncHolderBase0<R> {
832 FuncHolder0(FUNC& f) : m_Func(f) {}
835 return m_Func.get()();
839 FuncWrap<FUNC> m_Func;
842 template <
class FUNC,
class R,
class T1>
843 class FuncHolder1 :
public FuncHolderBase1<R, T1> {
845 FuncHolder1(FUNC& f) : m_Func(f) {}
848 return m_Func.get()(NLIB_FWD(T1, arg1));
852 FuncWrap<FUNC> m_Func;
855 template <
class FUNC,
class R,
class T1,
class T2>
856 class FuncHolder2 :
public FuncHolderBase2<R, T1, T2> {
858 FuncHolder2(FUNC& f) : m_Func(f) {}
860 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)
NLIB_OVERRIDE {
861 return m_Func.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
865 FuncWrap<FUNC> m_Func;
868 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
869 class FuncHolder3 :
public FuncHolderBase3<R, T1, T2, T3> {
871 FuncHolder3(FUNC& f) : m_Func(f) {}
873 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)
NLIB_OVERRIDE {
874 return m_Func.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
878 FuncWrap<FUNC> m_Func;
881 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
882 class FuncHolder4 :
public FuncHolderBase4<R, T1, T2, T3, T4> {
884 FuncHolder4(FUNC& f) : m_Func(f) {}
886 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
888 return m_Func.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
893 FuncWrap<FUNC> m_Func;
896 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
897 class FuncHolder5 :
public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
899 FuncHolder5(FUNC& f) : m_Func(f) {}
901 virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
903 return m_Func.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
904 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
908 FuncWrap<FUNC> m_Func;
918 template <class FUNC>
928 typedef R ReturnType;
931 NLIB_MOVE_MEMBER_HELPER_2(
PackagedTask, m_Func, m_Promise)
932 template <
class FUNC>
935 if (e != 0)
return e;
936 m_Func.reset(
new (std::nothrow) detail::FuncHolder0<FUNC, R>(func_));
937 return !m_Func ? ENOMEM : 0;
942 swap(m_Func, rhs.m_Func);
943 swap(m_Promise, rhs.m_Promise);
950 template <
class DUMMY>
951 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec() {
953 R rval = (*m_Func)();
956 m_Promise.SetValue(rval);
958 m_Promise.SetError(e);
961 #ifdef NLIB_EXCEPTION_ENABLED
962 NLIB_RETHROW_UNWIND {
963 m_Promise.SetError(ECANCELED);
966 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
969 template <
class DUMMY>
970 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec() {
973 m_Promise.SetValue();
975 #ifdef NLIB_EXCEPTION_ENABLED
976 NLIB_RETHROW_UNWIND {
977 m_Promise.SetError(ECANCELED);
980 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
989 template <
class R,
class T1>
992 typedef R ReturnType;
995 NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, m_Func, m_Promise)
996 template <class FUNC>
999 if (e != 0)
return e;
1000 m_Func.reset(
new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func_));
1001 return !m_Func ? ENOMEM : 0;
1003 errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT {
return m_Promise.GetFuture(p); }
1004 void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1006 swap(m_Func, rhs.m_Func);
1007 swap(m_Promise, rhs.m_Promise);
1009 void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1012 template <
class DUMMY>
1013 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(T1 NLIB_RREF arg1) {
1015 R rval = (*m_Func)(NLIB_FWD(T1, arg1));
1018 m_Promise.SetValue(rval);
1020 m_Promise.SetError(e);
1023 #ifdef NLIB_EXCEPTION_ENABLED
1024 NLIB_RETHROW_UNWIND {
1025 m_Promise.SetError(ECANCELED);
1028 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1031 template <
class DUMMY>
1032 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(T1 NLIB_RREF arg1) {
1034 (*m_Func)(NLIB_FWD(T1, arg1));
1035 m_Promise.SetValue();
1037 #ifdef NLIB_EXCEPTION_ENABLED
1038 NLIB_RETHROW_UNWIND {
1039 m_Promise.SetError(ECANCELED);
1042 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1046 UniquePtr<detail::FuncHolderBase1<R, T1> > m_Func;
1047 Promise<R> m_Promise;
1051 template <
class R,
class T1,
class T2>
1052 class PackagedTask<R(T1, T2)> {
1054 typedef R ReturnType;
1055 typedef PackagedTask<ReturnType(T1, T2)> ThisType;
1056 PackagedTask() NLIB_NOEXCEPT {}
1057 NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, m_Func, m_Promise)
1058 template <class FUNC>
1061 if (e != 0)
return e;
1062 m_Func.reset(
new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func_));
1063 return !m_Func ? ENOMEM : 0;
1065 errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT {
return m_Promise.GetFuture(p); }
1066 void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1068 swap(m_Func, rhs.m_Func);
1069 swap(m_Promise, rhs.m_Promise);
1071 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1072 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1076 template <
class DUMMY>
1077 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1078 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1080 R rval = (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1083 m_Promise.SetValue(rval);
1085 m_Promise.SetError(e);
1088 #ifdef NLIB_EXCEPTION_ENABLED
1089 NLIB_RETHROW_UNWIND {
1090 m_Promise.SetError(ECANCELED);
1093 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1096 template <
class DUMMY>
1097 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1098 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1100 (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1101 m_Promise.SetValue();
1103 #ifdef NLIB_EXCEPTION_ENABLED
1104 NLIB_RETHROW_UNWIND {
1105 m_Promise.SetError(ECANCELED);
1108 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1112 UniquePtr<detail::FuncHolderBase2<R, T1, T2> > m_Func;
1113 Promise<ReturnType> m_Promise;
1117 template <
class R,
class T1,
class T2,
class T3>
1118 class PackagedTask<R(T1, T2, T3)> {
1120 typedef R ReturnType;
1121 typedef PackagedTask<ReturnType(T1, T2, T3)> ThisType;
1122 PackagedTask() NLIB_NOEXCEPT {}
1123 NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, m_Func, m_Promise)
1124 template <class FUNC>
1127 if (e != 0)
return e;
1128 m_Func.reset(
new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func_));
1129 return !m_Func ? ENOMEM : 0;
1131 errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT {
return m_Promise.GetFuture(p); }
1132 void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1134 swap(m_Func, rhs.m_Func);
1135 swap(m_Promise, rhs.m_Promise);
1137 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1138 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1142 template <
class DUMMY>
1143 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1144 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1146 R rval = (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1149 m_Promise.SetValue(rval);
1151 m_Promise.SetError(e);
1154 #ifdef NLIB_EXCEPTION_ENABLED
1155 NLIB_RETHROW_UNWIND {
1156 m_Promise.SetError(ECANCELED);
1159 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1162 template <
class DUMMY>
1163 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1164 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1166 (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1167 m_Promise.SetValue();
1169 #ifdef NLIB_EXCEPTION_ENABLED
1170 NLIB_RETHROW_UNWIND {
1171 m_Promise.SetError(ECANCELED);
1174 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1178 UniquePtr<detail::FuncHolderBase3<R, T1, T2, T3> > m_Func;
1179 Promise<ReturnType> m_Promise;
1183 template <
class R,
class T1,
class T2,
class T3,
class T4>
1184 class PackagedTask<R(T1, T2, T3, T4)> {
1186 typedef R ReturnType;
1187 typedef PackagedTask<ReturnType(T1, T2, T3, T4)> ThisType;
1188 PackagedTask() NLIB_NOEXCEPT {}
1189 NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, m_Func, m_Promise)
1190 template <class FUNC>
1193 if (e != 0)
return e;
1194 m_Func.reset(
new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func_));
1195 return !m_Func ? ENOMEM : 0;
1197 errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT {
return m_Promise.GetFuture(p); }
1198 void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1200 swap(m_Func, rhs.m_Func);
1201 swap(m_Promise, rhs.m_Promise);
1203 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1204 T4 NLIB_RREF arg4) {
1205 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1209 template <
class DUMMY>
1210 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1211 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1213 R rval = (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1214 NLIB_FWD(T4, arg4));
1217 m_Promise.SetValue(rval);
1219 m_Promise.SetError(e);
1222 #ifdef NLIB_EXCEPTION_ENABLED
1223 NLIB_RETHROW_UNWIND {
1224 m_Promise.SetError(ECANCELED);
1227 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1230 template <
class DUMMY>
1231 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1232 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1234 (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1235 NLIB_FWD(T4, arg4));
1236 m_Promise.SetValue();
1238 #ifdef NLIB_EXCEPTION_ENABLED
1239 NLIB_RETHROW_UNWIND {
1240 m_Promise.SetError(ECANCELED);
1243 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1247 UniquePtr<detail::FuncHolderBase4<R, T1, T2, T3, T4> > m_Func;
1248 Promise<ReturnType> m_Promise;
1252 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1253 class PackagedTask<R(T1, T2, T3, T4, T5)> {
1255 typedef R ReturnType;
1256 typedef PackagedTask<ReturnType(T1, T2, T3, T4, T5)> ThisType;
1257 PackagedTask() NLIB_NOEXCEPT {}
1258 NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, m_Func, m_Promise)
1259 template <class FUNC>
1262 if (e != 0)
return e;
1263 m_Func.reset(
new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func_));
1264 return !m_Func ? ENOMEM : 0;
1266 errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT {
return m_Promise.GetFuture(p); }
1267 void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1269 swap(m_Func, rhs.m_Func);
1270 swap(m_Promise, rhs.m_Promise);
1272 void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1273 T5 NLIB_RREF arg5) {
1274 Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1275 NLIB_FWD(T5, arg5));
1279 template <
class DUMMY>
1280 typename EnableIf<!IsSame<DUMMY, void>::value,
void>::type Exec(
1281 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1282 T5 NLIB_RREF arg5) {
1284 R rval = (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1285 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1288 m_Promise.SetValue(rval);
1290 m_Promise.SetError(e);
1293 #ifdef NLIB_EXCEPTION_ENABLED
1294 NLIB_RETHROW_UNWIND {
1295 m_Promise.SetError(ECANCELED);
1298 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1301 template <
class DUMMY>
1302 typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1303 T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1304 T5 NLIB_RREF arg5) {
1306 (*m_Func)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1307 NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1308 m_Promise.SetValue();
1310 #ifdef NLIB_EXCEPTION_ENABLED
1311 NLIB_RETHROW_UNWIND {
1312 m_Promise.SetError(ECANCELED);
1315 NLIB_CATCH(...) { m_Promise.SetError(EINVAL); }
1319 UniquePtr<detail::FuncHolderBase5<R, T1, T2, T3, T4, T5> > m_Func;
1320 Promise<ReturnType> m_Promise;
1326 template <
class T,
bool B>
1328 explicit XHolder(
const T& value_) : value() {
1330 swap(const_cast<T&>(value_), value);
1336 struct XHolder<T, false> {
1337 explicit XHolder(
const T& value_) : value(value_) {}
1342 struct XHolder<R(), false> {
1343 XHolder(R (*value_)()) : value(value_) {}
1347 template <
class R,
class T1>
1348 struct XHolder<R(T1), false> {
1349 XHolder(R (*value_)(T1)) : value(value_) {}
1353 template <
class R,
class T1,
class T2>
1354 struct XHolder<R(T1, T2), false> {
1355 XHolder(R (*value_)(T1, T2)) : value(value_) {}
1359 template <
class R,
class T1,
class T2,
class T3>
1360 struct XHolder<R(T1, T2, T3), false> {
1361 XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1362 R (*value)(T1, T2, T3);
1365 template <
class R,
class T1,
class T2,
class T3,
class T4>
1366 struct XHolder<R(T1, T2, T3, T4), false> {
1367 XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1368 R (*value)(T1, T2, T3, T4);
1371 template <
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1372 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1373 XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1374 R (*value)(T1, T2, T3, T4, T5);
1377 #define NLIB_ASYNC_HOLDER(T, B) \
1378 XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value>
1379 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \
1380 XHolder<FUNC, B::value && IsSwappable<FUNC>::value && !IsPointer<FUNC>::value>
1382 template <
class FUNC,
class R,
class BF>
1383 errno_t Async_(Future<R>* future,
const FUNC& func,
const ThreadSettings& settings, BF) {
1384 if (!future || !settings.GetDetachState())
return EINVAL;
1385 PackagedTask<R()> task;
1386 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1387 errno_t e = task.Init(func_.value);
1388 if (e != 0) return e;
1389 e = task.GetFuture(future);
1390 if (e != 0) return e;
1392 e = th.Start(settings, task, move_tag());
1396 template <class FUNC, class R, class BF, class T1>
1397 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const ThreadSettings& settings,
1399 if (!future || !settings.GetDetachState())
return EINVAL;
1400 PackagedTask<R(T1)> task;
1401 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1402 errno_t e = task.Init(func_.value);
1403 if (e != 0) return e;
1404 e = task.GetFuture(future);
1405 if (e != 0) return e;
1407 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1408 e = th.Start(settings, task, arg1_.value, move_tag());
1412 template <class FUNC, class R, class BF, class T1, class T2>
1413 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1414 const ThreadSettings& settings, BF) {
1415 if (!future || !settings.GetDetachState())
return EINVAL;
1416 PackagedTask<R(T1, T2)> task;
1417 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1418 errno_t e = task.Init(func_.value);
1419 if (e != 0) return e;
1420 e = task.GetFuture(future);
1421 if (e != 0) return e;
1423 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1424 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1425 e = th.Start(settings, task, arg1_.value, arg2_.value, move_tag());
1429 template <class FUNC, class R, class BF, class T1, class T2, class T3>
1430 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2, const T3& arg3,
1431 const ThreadSettings& settings, BF) {
1432 if (!future || !settings.GetDetachState())
return EINVAL;
1433 PackagedTask<R(T1, T2, T3)> task;
1434 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1435 errno_t e = task.Init(func_.value);
1436 if (e != 0) return e;
1437 e = task.GetFuture(future);
1438 if (e != 0) return e;
1440 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1441 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1442 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1443 e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, move_tag());
1447 template <class FUNC, class R, class BF, class T1, class T2, class T3, class T4>
1448 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2, const T3& arg3,
1449 const T4& arg4, const ThreadSettings& settings, BF) {
1450 if (!future || !settings.GetDetachState())
return EINVAL;
1451 PackagedTask<R(T1, T2, T3, T4)> task;
1452 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1453 errno_t e = task.Init(func_.value);
1454 if (e != 0) return e;
1455 e = task.GetFuture(future);
1456 if (e != 0) return e;
1458 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1459 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1460 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1461 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1462 e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, move_tag());
1466 template <class FUNC, class R, class BF, class T1, class T2, class T3, class T4, class T5>
1467 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2, const T3& arg3,
1468 const T4& arg4, const T5& arg5, const ThreadSettings& settings, BF) {
1469 if (!future || !settings.GetDetachState())
return EINVAL;
1470 PackagedTask<R(T1, T2, T3, T4, T5)> task;
1471 NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1472 errno_t e = task.Init(func_.value);
1473 if (e != 0) return e;
1474 e = task.GetFuture(future);
1475 if (e != 0) return e;
1477 NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1478 NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1479 NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1480 NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1481 NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1482 e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1487 #undef NLIB_ASYNC_HOLDER
1488 #undef NLIB_ASYNC_HOLDER_F
1492 template <
class FUNC,
class R>
1494 return detail::Async_(future, func, settings, FalseType());
1497 template <
class FUNC,
class R>
1500 return detail::Async_(future, func, settings, TrueType());
1503 template <
class FUNC,
class R>
1507 return Async(future, func, settings);
1510 template <
class FUNC,
class R>
1514 return Async(future, func, settings, move_tag());
1517 template <
class FUNC,
class R,
class T1>
1520 return detail::Async_(future, func, arg1, settings, FalseType());
1523 template <
class FUNC,
class R,
class T1>
1526 return detail::Async_(future, func, arg1, settings, TrueType());
1529 template <
class FUNC,
class R,
class T1>
1533 return Async(future, func, arg1, settings);
1536 template <
class FUNC,
class R,
class T1>
1540 return Async(future, func, arg1, settings, move_tag());
1543 template <
class FUNC,
class R,
class T1,
class T2>
1546 return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1549 template <
class FUNC,
class R,
class T1,
class T2>
1552 return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1555 template <
class FUNC,
class R,
class T1,
class T2>
1559 return Async(future, func, arg1, arg2, settings);
1562 template <
class FUNC,
class R,
class T1,
class T2>
1567 return Async(future, func, arg1, arg2, settings, move_tag());
1570 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1573 return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1576 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1579 return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1582 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1587 return Async(future, func, arg1, arg2, arg3, settings);
1590 template <
class FUNC,
class R,
class T1,
class T2,
class T3>
1592 const T3& arg3, move_tag) {
1595 return Async(future, func, arg1, arg2, arg3, settings, move_tag());
1598 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1600 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings) {
1601 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1604 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1606 const T3& arg3,
const T4& arg4,
const ThreadSettings& settings, move_tag) {
1607 return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1610 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1612 const T3& arg3,
const T4& arg4) {
1615 return Async(future, func, arg1, arg2, arg3, arg4, settings);
1618 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4>
1620 const T3& arg3,
const T4& arg4, move_tag) {
1623 return Async(future, func, arg1, arg2, arg3, arg4, settings, move_tag());
1626 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1628 const T3& arg3,
const T4& arg4,
const T5& arg5,
1630 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1633 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1635 const T3& arg3,
const T4& arg4,
const T5& arg5,
const ThreadSettings& settings,
1637 return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1640 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1642 const T3& arg3,
const T4& arg4,
const T5& arg5) {
1645 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1648 template <
class FUNC,
class R,
class T1,
class T2,
class T3,
class T4,
class T5>
1650 const T3& arg3,
const T4& arg4,
const T5& arg5, move_tag) {
1653 return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings, move_tag());
1658 if (!future)
return EINVAL;
1661 if (e != 0)
return e;
1662 e = promise.SetValue(value);
1663 if (e != 0)
return e;
1664 e = promise.GetFuture(future);
1665 if (e != 0)
return e;
1670 template <
class FUTURE,
class R,
typename CONT>
1671 class FutureContinuation :
public FutureContinuationBase {
1673 FutureContinuation(FUTURE& f, CONT cont) NLIB_NOEXCEPT
1677 errno_t Init() NLIB_NOEXCEPT {
return m_Next.Init(); }
1678 errno_t GetFuture(Future<R>* future) NLIB_NOEXCEPT {
return m_Next.GetFuture(future); }
1679 virtual ~FutureContinuation() NLIB_NOEXCEPT
NLIB_OVERRIDE {}
1689 template <class FUTURE, class R, typename CONT>
1690 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
1691 int32_t expected = 0;
1695 R rval = m_Func(m_Parent);
1698 (void)m_Next.SetValue(rval);
1700 (void)m_Next.SetError(e);
1703 #ifdef NLIB_EXCEPTION_ENABLED
1704 NLIB_RETHROW_UNWIND {
1705 m_Next.SetError(ECANCELED);
1708 NLIB_CATCH(...) { (void)m_Next.SetError(EINVAL); }
1713 template <
class Derived>
1715 errno_t FutureBase<Derived>::Then(Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT {
1716 Derived& ref =
static_cast<Derived&
>(*this);
1717 if (!ref.m_Value)
return EINVAL;
1719 typedef R (*CONT)(Derived&);
1720 UniquePtr<FutureContinuation<Derived, R, CONT> > ptr(
1721 new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
1722 if (!ptr)
return ENOMEM;
1724 if (e != 0)
return e;
1725 e = ptr->GetFuture(next);
1726 if (e != 0)
return e;
1728 ref.m_Value->common.Lock();
1729 ref.m_Value->common.cont = ptr.release();
1730 bool isready = ref.IsReady_();
1731 ref.m_Value->common.Unlock();
1733 ref.m_Value->common.cont->DoContinuation();
1740 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
1741 struct FutureTuple {
1750 struct FutureTuple<None, None, None, None, None>;
1752 struct FutureTuple<R1, None, None, None, None>;
1754 template <
class R1,
class R2>
1755 struct FutureTuple<R1, R2, None, None, None> {
1760 template <
class R1,
class R2,
class R3>
1761 struct FutureTuple<R1, R2, R3, None, None> {
1767 template <
class R1,
class R2,
class R3,
class R4>
1768 struct FutureTuple<R1, R2, R3, R4, None> {
1775 template <
class R1 = None,
class R2 = None,
class R3 = None,
class R4 = None,
class R5 = None>
1782 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
1786 return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
1791 typedef void (*FuncType)(ArgType& ptr);
1794 static void Call(ArgType& ptr) {
1798 static void CallWhenAny(ArgType& ptr) {
1800 if (ptr->m_Tuple->f1.IsReady() || ptr->m_Tuple->f2.IsReady() ||
1801 ptr->m_Tuple->f3.IsReady() || ptr->m_Tuple->f4.IsReady() ||
1802 ptr->m_Tuple->f5.IsReady()) {
1807 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
1809 static void CallWhenAll(ArgType& ptr) {
1810 ptr->m_Tuple->f1.Wait();
1811 ptr->m_Tuple->f2.Wait();
1812 ptr->m_Tuple->f3.Wait();
1813 ptr->m_Tuple->f4.Wait();
1814 ptr->m_Tuple->f5.Wait();
1815 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
1817 explicit WhenFutureComplete(FuncType f) : func(f) {}
1818 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
1819 Future<R4>* f4, Future<R5>* f5) {
1821 if (e != 0)
return e;
1822 m_Tuple.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
1823 if (!m_Tuple)
return ENOMEM;
1824 e = m_Promise.GetFuture(f);
1825 if (e != 0)
return e;
1826 e = m_Tuple->f1.MakeSharedFrom(*f1);
1827 if (e != 0)
return e;
1828 e = m_Tuple->f2.MakeSharedFrom(*f2);
1829 if (e != 0)
return e;
1830 e = m_Tuple->f3.MakeSharedFrom(*f3);
1831 if (e != 0)
return e;
1832 e = m_Tuple->f4.MakeSharedFrom(*f4);
1833 if (e != 0)
return e;
1834 e = m_Tuple->f5.MakeSharedFrom(*f5);
1835 if (e != 0)
return e;
1842 Promise<ReturnType> m_Promise;
1844 friend class Thread;
1847 template <
class R1,
class R2,
class R3,
class R4,
class R5>
1848 errno_t WhenFutureComplete<R1, R2, R3, R4, R5>::DoWhen(FutureType* f, Future<R1>* f1,
1849 Future<R2>* f2, Future<R3>* f3,
1850 Future<R4>* f4, Future<R5>* f5,
1852 if (!f1 || !f2 || !f3 || !f4 || !f5)
return EINVAL;
1853 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
1856 e = ptr->Init(f, f1, f2, f3, f4, f5);
1857 if (e != 0)
return e;
1859 e = th.StartRaw(ptr);
1860 if (e != 0)
return e;
1865 class WhenFutureComplete<None, None, None, None, None>;
1867 class WhenFutureComplete<R1, None, None, None, None>;
1869 template <
class R1,
class R2>
1870 class WhenFutureComplete<R1, R2, None, None, None> {
1872 typedef UniquePtr<FutureTuple<R1, R2> > ReturnType;
1873 typedef Future<ReturnType> FutureType;
1874 static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2) {
1875 return DoWhen(f, f1, f2, CallWhenAll);
1877 static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2) {
1878 return DoWhen(f, f1, f2, CallWhenAny);
1882 typedef UniquePtr<WhenFutureComplete> ArgType;
1883 typedef void (*FuncType)(ArgType& ptr);
1884 static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, FuncType func);
1885 static void Call(ArgType& ptr) {
1889 static void CallWhenAny(ArgType& ptr) {
1891 if (ptr->m_Tuple->f1.IsReady() || ptr->m_Tuple->f2.IsReady()) {
1896 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
1898 static void CallWhenAll(ArgType& ptr) {
1899 ptr->m_Tuple->f1.Wait();
1900 ptr->m_Tuple->f2.Wait();
1901 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
1903 explicit WhenFutureComplete(FuncType f) : func(f) {}
1904 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2) {
1906 if (e != 0)
return e;
1907 m_Tuple.reset(
new (std::nothrow) FutureTuple<R1, R2>());
1908 if (!m_Tuple)
return ENOMEM;
1909 e = m_Promise.GetFuture(f);
1910 if (e != 0)
return e;
1911 e = m_Tuple->f1.MakeSharedFrom(*f1);
1912 if (e != 0)
return e;
1913 e = m_Tuple->f2.MakeSharedFrom(*f2);
1914 if (e != 0)
return e;
1921 Promise<ReturnType> m_Promise;
1923 friend class Thread;
1926 template <
class R1,
class R2>
1927 errno_t WhenFutureComplete<R1, R2>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
1929 if (!f1 || !f2)
return EINVAL;
1930 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
1933 e = ptr->Init(f, f1, f2);
1934 if (e != 0)
return e;
1936 e = th.StartRaw(ptr);
1937 if (e != 0)
return e;
1941 template <
class R1,
class R2,
class R3>
1942 class WhenFutureComplete<R1, R2, R3, None, None> {
1944 typedef UniquePtr<FutureTuple<R1, R2, R3> > ReturnType;
1945 typedef Future<ReturnType> FutureType;
1946 static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
1947 return DoWhen(f, f1, f2, f3, CallWhenAll);
1949 static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
1950 return DoWhen(f, f1, f2, f3, CallWhenAny);
1954 typedef UniquePtr<WhenFutureComplete> ArgType;
1955 typedef void (*FuncType)(ArgType& ptr);
1956 static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
1958 static void Call(ArgType& ptr) {
1962 static void CallWhenAny(ArgType& ptr) {
1964 if (ptr->m_Tuple->f1.IsReady() || ptr->m_Tuple->f2.IsReady() ||
1965 ptr->m_Tuple->f3.IsReady()) {
1970 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
1972 static void CallWhenAll(ArgType& ptr) {
1973 ptr->m_Tuple->f1.Wait();
1974 ptr->m_Tuple->f2.Wait();
1975 ptr->m_Tuple->f3.Wait();
1976 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
1978 explicit WhenFutureComplete(FuncType f) : func(f) {}
1979 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
1981 if (e != 0)
return e;
1982 m_Tuple.reset(
new (std::nothrow) FutureTuple<R1, R2, R3>());
1983 if (!m_Tuple)
return ENOMEM;
1984 e = m_Promise.GetFuture(f);
1985 if (e != 0)
return e;
1986 e = m_Tuple->f1.MakeSharedFrom(*f1);
1987 if (e != 0)
return e;
1988 e = m_Tuple->f2.MakeSharedFrom(*f2);
1989 if (e != 0)
return e;
1990 e = m_Tuple->f3.MakeSharedFrom(*f3);
1991 if (e != 0)
return e;
1998 Promise<ReturnType> m_Promise;
2000 friend class Thread;
2003 template <
class R1,
class R2,
class R3>
2004 errno_t WhenFutureComplete<R1, R2, R3>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
2005 Future<R3>* f3, FuncType func) {
2006 if (!f1 || !f2 || !f3)
return EINVAL;
2007 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
2010 e = ptr->Init(f, f1, f2, f3);
2011 if (e != 0)
return e;
2013 e = th.StartRaw(ptr);
2014 if (e != 0)
return e;
2018 template <
class R1,
class R2,
class R3,
class R4>
2019 class WhenFutureComplete<R1, R2, R3, R4, None> {
2021 typedef UniquePtr<FutureTuple<R1, R2, R3, R4> > ReturnType;
2022 typedef Future<ReturnType> FutureType;
2023 static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2025 return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2027 static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2029 return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2033 typedef UniquePtr<WhenFutureComplete> ArgType;
2034 typedef void (*FuncType)(ArgType& ptr);
2035 static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2036 Future<R4>* f4, FuncType func);
2037 static void Call(ArgType& ptr) {
2041 static void CallWhenAny(ArgType& ptr) {
2043 if (ptr->m_Tuple->f1.IsReady() || ptr->m_Tuple->f2.IsReady() ||
2044 ptr->m_Tuple->f3.IsReady() || ptr->m_Tuple->f4.IsReady()) {
2049 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
2051 static void CallWhenAll(ArgType& ptr) {
2052 ptr->m_Tuple->f1.Wait();
2053 ptr->m_Tuple->f2.Wait();
2054 ptr->m_Tuple->f3.Wait();
2055 ptr->m_Tuple->f4.Wait();
2056 ptr->m_Promise.SetValue(ptr->m_Tuple.release());
2058 explicit WhenFutureComplete(FuncType f) : func(f) {}
2059 errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2062 if (e != 0)
return e;
2063 m_Tuple.reset(
new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2064 if (!m_Tuple)
return ENOMEM;
2065 e = m_Promise.GetFuture(f);
2066 if (e != 0)
return e;
2067 e = m_Tuple->f1.MakeSharedFrom(*f1);
2068 if (e != 0)
return e;
2069 e = m_Tuple->f2.MakeSharedFrom(*f2);
2070 if (e != 0)
return e;
2071 e = m_Tuple->f3.MakeSharedFrom(*f3);
2072 if (e != 0)
return e;
2073 e = m_Tuple->f4.MakeSharedFrom(*f4);
2074 if (e != 0)
return e;
2081 Promise<ReturnType> m_Promise;
2083 friend class Thread;
2086 template <
class R1,
class R2,
class R3,
class R4>
2087 errno_t WhenFutureComplete<R1, R2, R3, R4>::DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2,
2088 Future<R3>* f3, Future<R4>* f4, FuncType func) {
2089 if (!f1 || !f2 || !f3 || !f4)
return EINVAL;
2090 ArgType ptr(
new (std::nothrow) WhenFutureComplete(func));
2093 e = ptr->Init(f, f1, f2, f3, f4);
2094 if (e != 0)
return e;
2096 e = th.StartRaw(ptr);
2097 if (e != 0)
return e;
2104 #ifndef NLIB_STD_SWAP_WORKAROUND
2105 NLIB_NAMESPACE_BEGIN
2108 NLIB_DEFINE_STD_SWAP_T_BEGIN1(threading)
2109 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise)
2110 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask)
2111 NLIB_DEFINE_STD_SWAP_T_END1(threading)
2113 #ifndef NLIB_STD_SWAP_WORKAROUND
2117 #endif // INCLUDE_NN_NLIB_THREADING_FUTURE_H_
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
errno_t MakeReadyFuture(Future< R > *future, const R &value)
Creates a Future with preset values.
errno_t Async(Future< R > *future, const FUNC &func, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, move_tag)
Async that moves arguments and function objects.
static errno_t Any(FutureType *f, Future< R1 > *f1, Future< R2 > *f2, Future< R3 > *f3, Future< R4 > *f4, Future< R5 > *f5)
When an error has been set to any of Future f1, f2, f3, f4, and f5, a value is set in f...
errno_t Sleep(const TimeSpan &span) noexcept
Makes the thread sleep for a specified period of time.
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
#define NLIB_CATCH(x)
Defines catch(x) if exceptions are enabled. If not, defines if (true).
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Implements mutex, reentrant timeout mutex, and reentrant mutex.
errno_t Wait() noexcept
Waits for conditions that allow results to be acquired.
#define NLIB_OVERRIDE
Defines override if it is available for use. If not, holds an empty string.
void swap(Promise &rhs) noexcept
Swaps an object.
void SetDetachState(bool detached) noexcept
Sets whether to start a thread in a detached state.
#define NLIB_TRY
Defines try if exceptions are enabled. If not, defines if (true).
errno_t GetFuture(Future< R > *p) noexcept
Sets Future to get the result of execution.
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Defines that class that is corresponding to std::unique_ptr.
errno_t WaitUntil(const DateTime &datetime) noexcept
Waits for conditions that allow results to be acquired, until the defined time.
Class that calls the result of thread execution and outputs it in a thread safe manner. This class is similar to the std::promise class of C++11.
The class for representing the date and time.
errno_t WaitFor(const TimeSpan &span) noexcept
Waits for conditions that allow results to be acquired, for a specified amount of time...
bool IsReady() const noexcept
Returns whether a value has been set for Future (whether Promise set a value or an error)...
Defines a Future for which to set the value, under the condition that a value has been set for the Fu...
errno_t SetError(errno_t e) noexcept
Sets an error value.
The class to wrap nlib_thread_attr. nlib_thread_attr_init() and nlib_thread_attr_destroy() are run au...
bool IsValid() const noexcept
errno_t MakeSharedFrom(const Future &f) noexcept
Shares a Future so that it may be viewed.
static errno_t All(FutureType *f, Future< R1 > *f1, Future< R2 > *f2, Future< R3 > *f3, Future< R4 > *f4, Future< R5 > *f5)
When an error has been set to all Future f1, f2, f3, f4, and f5, sets a value to f.
errno_t Get(R *ptr)
Waits until a result is acquired, and then gets the result.
Defines the class for handling times and durations.
errno_t GetFutureError(FutureResult &result) noexcept
Function that enables systems to get error values when threads hold an error value.
Class that gets the output of a different thread executing in a thread safe manner. This class is similar to the std::shared_future class of C++11.
Future< R > FutureType
The type for Future.
Wraps objects like CriticalSection. Locks with a constructor, and unlocks with a destructor.
Class that wraps a function to run in a different thread, and gets the return value in a thread safe ...
Promise() noexcept
Instantiates the object with default parameters (default constructor).
PackagedTask< T > ThisType
The object type.
The class for representing the time.
errno_t Then(Future< RNEXT > *next, RNEXT(*cont)(Future< R > &)) noexcept
Registers the process to continue (continuation) to this future.
Future< ReturnType > FutureType
Type of the newly created Future.
Future() noexcept
Instantiates the object with default parameters (default constructor).
UniquePtr< FutureTuple< R1, R2, R3, R4, R5 > > ReturnType
Type of value to set to the newly created Future.