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