nlib
Future.h
Go to the documentation of this file.
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_THREADING_FUTURE_H_
17 #define INCLUDE_NN_NLIB_THREADING_FUTURE_H_
18 
19 #include "nn/nlib/Swap.h"
20 #include "nn/nlib/UniquePtr.h"
21 #include "nn/nlib/DateTime.h"
22 #include "nn/nlib/TypeTraits.h"
24 #include "nn/nlib/threading/LimitedSharedPtr.h"
26 
27 NLIB_NAMESPACE_BEGIN
28 class TimeSpan;
29 class DateTime;
30 namespace threading {
31 
32 template <class FutureResult>
33 inline errno_t GetFutureError(FutureResult& result) NLIB_NOEXCEPT { // NOLINT
34  NLIB_UNUSED(result);
35  return 0;
36 }
37 
38 template <class R>
39 class Future;
40 template <class R>
41 class Promise;
42 
43 namespace detail {
44 
45 class NLIB_VIS_PUBLIC FutureContinuationBase {
46  public:
47  FutureContinuationBase() NLIB_NOEXCEPT {}
48  virtual ~FutureContinuationBase() NLIB_NOEXCEPT {}
49  virtual void DoContinuation() {}
50 
51  private:
52  NLIB_DISALLOW_COPY_AND_ASSIGN(FutureContinuationBase);
53 };
54 
55 template <class FUTURE, class R, typename CONT>
56 class FutureContinuation;
57 
58 template <class Derived>
59 class FutureBase {
60  public:
61  FutureBase() NLIB_NOEXCEPT {}
62 #ifdef NLIB_CXX11_RVALUE_REFERENCES
63  FutureBase(FutureBase&& rhs) NLIB_NOEXCEPT { NLIB_UNUSED(rhs); } // NOLINT
64 #endif
65  errno_t Wait() NLIB_NOEXCEPT;
66  NLIB_CHECK_RESULT errno_t WaitFor(const TimeSpan& span) NLIB_NOEXCEPT;
67  NLIB_CHECK_RESULT errno_t WaitUntil(const DateTime& datetime) NLIB_NOEXCEPT;
68  bool IsValid() const NLIB_NOEXCEPT {
69  const Derived& ref = static_cast<const Derived&>(*this);
70  return !!ref.value_; // for explicit operator bool
71  }
72  bool IsReady() const NLIB_NOEXCEPT;
73  errno_t MakeSharedFrom(const Derived& f) NLIB_NOEXCEPT {
74  Derived& ref = static_cast<Derived&>(*this);
75  return ref.value_.MakeSharedFrom(f.value_);
76  }
77  template <class R>
78  errno_t Then(Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT;
79  void swap(Derived& rhs) NLIB_NOEXCEPT {
80  static_cast<Derived&>(*this).value_.swap(rhs.value_);
81  }
82 
83  private:
84  bool IsReady_() const NLIB_NOEXCEPT {
85  return static_cast<const Derived&>(*this).value_->common.IsReady();
86  }
87 };
88 
89 template <class Derived>
90 bool FutureBase<Derived>::IsReady() const NLIB_NOEXCEPT {
91  const Derived& ref = static_cast<const Derived&>(*this);
92  if (ref.value_) {
93  ref.value_->common.Lock();
94  bool rval = IsReady_();
95  ref.value_->common.Unlock();
96  return rval;
97  } else {
98  return false;
99  }
100 }
101 
102 template <class Derived>
103 errno_t FutureBase<Derived>::Wait() NLIB_NOEXCEPT {
104  Derived& ref = static_cast<Derived&>(*this);
105  NLIB_ASSERT(ref.value_);
106  if (!ref.value_) return EINVAL;
107  ref.value_->common.Lock();
108  while (!IsReady_()) {
109  errno_t e = ref.value_->common.Wait();
110  if (e != 0) {
111  ref.value_->common.Unlock();
112  NLIB_ASSERT_NOERR(e);
113  return e;
114  }
115  }
116  ref.value_->common.Unlock();
117  return 0;
118 }
119 
120 template <class Derived>
121 errno_t FutureBase<Derived>::WaitFor(const TimeSpan& span) NLIB_NOEXCEPT {
122  Derived& ref = static_cast<Derived&>(*this);
123  NLIB_ASSERT(ref.value_);
124  if (!ref.value_) return EINVAL;
125  DateTime abstime;
126  errno_t e = DateTime::GetNow(&abstime);
127  abstime += span;
128  if (e != 0) return e;
129  ref.value_->common.Lock();
130  while (!IsReady_()) {
131  // NOTE:
132  // Because of spurious wakeup, WaitUntil is better than WaitFor.
133  // Also note that CAFE's nlib_cond_wait_for
134  // always makes spurious wakeup and returns 0 if duration >= 0.
135  // CAFE's nlib_cond_wait_until can return ETIMEDOUT on the other hand.
136  e = nlib_cond_wait_until(&ref.value_->common.cond,
137  &ref.value_->common.lock,
138  abstime.ToTimeValue().tick);
139  if (e != 0) {
140  ref.value_->common.Unlock();
141  return e;
142  }
143  }
144  ref.value_->common.Unlock();
145  return 0;
146 }
147 
148 template <class Derived>
149 errno_t FutureBase<Derived>::WaitUntil(const DateTime& datetime) NLIB_NOEXCEPT {
150  Derived& ref = static_cast<Derived&>(*this);
151  NLIB_ASSERT(ref.value_);
152  if (!ref.value_) return EINVAL;
153  ref.value_->common.Lock();
154  while (!IsReady_()) {
155  errno_t e = nlib_cond_wait_until(&ref.value_->common.cond,
156  &ref.value_->common.lock,
157  datetime.ToTimeValue().tick);
158  if (e != 0) {
159  ref.value_->common.Unlock();
160  return e;
161  }
162  }
163  ref.value_->common.Unlock();
164  return 0;
165 }
166 
167 } // namespace detail
168 
169 namespace detail {
170 template <class Derived>
171 class PromiseBase {
172  public:
173  PromiseBase() NLIB_NOEXCEPT {}
174 #ifdef NLIB_CXX11_RVALUE_REFERENCES
175  PromiseBase(PromiseBase&& rhs) NLIB_NOEXCEPT { NLIB_UNUSED(rhs); } // NOLINT
176 #endif
177  errno_t Init() NLIB_NOEXCEPT;
178 
179  bool IsValid() const NLIB_NOEXCEPT {
180  const Derived& ref = static_cast<const Derived&>(*this);
181  return !!ref.value_;
182  }
183  errno_t SetError(errno_t e) NLIB_NOEXCEPT;
184  template <class F>
185  errno_t GetFuture(F* p) NLIB_NOEXCEPT;
186  void swap(Derived& rhs) NLIB_NOEXCEPT {
187  using std::swap;
188  Derived& ref = static_cast<Derived&>(*this);
189  swap(ref.value_, rhs.value_);
190  }
191 
192  protected:
193  struct NLIB_CAPABILITY("mutex") CommonStatus {
194  int32_t status;
195  detail::FutureContinuationBase* cont;
196  errno_t err;
197  nlib_mutex lock;
198  nlib_cond cond;
199  CommonStatus() NLIB_NOEXCEPT
200  : status(0), cont(NULL), err(0) {
201  errno_t e;
202  NLIB_UNUSED(e);
203  e = nlib_mutex_init(&lock);
204  NLIB_ASSERT_NOERR(e);
205  e = nlib_cond_init(&cond);
206  NLIB_ASSERT_NOERR(e);
207  }
208  ~CommonStatus() NLIB_NOEXCEPT {
209  if (cont) delete cont;
210  errno_t e;
211  NLIB_UNUSED(e);
212  e = nlib_mutex_destroy(&lock);
213  NLIB_ASSERT_NOERR(e);
214  e = nlib_cond_destroy(&cond);
215  NLIB_ASSERT_NOERR(e);
216  }
217  void Lock() NLIB_NOEXCEPT NLIB_ACQUIRE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
218  errno_t e;
219  NLIB_UNUSED(e);
220  e = nlib_mutex_lock(&lock);
221  NLIB_ASSERT_NOERR(e);
222  }
223  void Unlock() NLIB_NOEXCEPT NLIB_RELEASE() NLIB_NO_THREAD_SAFETY_ANALYSIS {
224  errno_t e;
225  NLIB_UNUSED(e);
226  e = nlib_mutex_unlock(&lock);
227  NLIB_ASSERT_NOERR(e);
228  }
229  errno_t Wait() NLIB_NOEXCEPT NLIB_REQUIRES(*this) NLIB_NO_THREAD_SAFETY_ANALYSIS {
230  return nlib_cond_wait(&cond, &lock);
231  }
232  bool IsReady() NLIB_NOEXCEPT {
233  return status == 20120915L;
234  }
235  bool SetReady() NLIB_NOEXCEPT {
236  if (status != 20120915L) {
237  status = 20120915L;
238  return true;
239  } else {
240  return false;
241  }
242  }
243  void NotifyAndContinuation() NLIB_NOEXCEPT {
244  // have to notify all the threads waiting
245  errno_t e = nlib_cond_broadcast(&cond);
246  NLIB_ASSERT_NOERR(e);
247  NLIB_UNUSED(e);
248  if (cont) cont->DoContinuation();
249  }
250  };
251  void NotifyAndContinuation() NLIB_NOEXCEPT {
252  static_cast<Derived&>(*this).value_->common.NotifyAndContinuation();
253  }
254 
255  private:
256  NLIB_DISALLOW_COPY_AND_ASSIGN(PromiseBase);
257 };
258 
259 template <class Derived>
260 errno_t PromiseBase<Derived>::Init() NLIB_NOEXCEPT {
261  // NOTE:
262  // This is not thread safe
263  // Note that Promise<R> itself is not thread safe.
264  Derived& ref = static_cast<Derived&>(*this);
265  if (ref.value_) return EALREADY;
266  ref.value_.reset(new (std::nothrow) typename Derived::Status());
267  if (!ref.value_) return ENOMEM;
268  return 0;
269 }
270 
271 template <class Derived>
272 errno_t PromiseBase<Derived>::SetError(errno_t e) NLIB_NOEXCEPT {
273  if (e == 0) return 0;
274  Derived& ref = static_cast<Derived&>(*this);
275  if (!ref.value_) {
276  errno_t ee = ref.Init();
277  if (ee != 0) return ee;
278  }
279  {
280  ref.value_->common.Lock();
281  if (ref.value_->common.SetReady()) {
282  ref.value_->common.err = e;
283  ref.value_->common.Unlock();
284  } else {
285  ref.value_->common.Unlock();
286  return EALREADY;
287  }
288  }
289  this->NotifyAndContinuation();
290  return 0;
291 }
292 
293 template <class Derived>
294 template <class F>
295 errno_t PromiseBase<Derived>::GetFuture(F* p) NLIB_NOEXCEPT {
296  if (!p) return EINVAL;
297  Derived& ref = static_cast<Derived&>(*this);
298  if (!ref.value_) {
299  errno_t e = this->Init();
300  if (e != 0) return e;
301  }
302  errno_t e = p->value_.MakeSharedFrom(ref.value_);
303  if (e != 0) return e;
304  return 0;
305 }
306 
307 } // namespace detail
308 
309 template <class R>
310 class Promise : public detail::PromiseBase<Promise<R> > {
311  typedef detail::PromiseBase<Promise<R> > BaseType;
312 
313  public:
315  Promise() NLIB_NOEXCEPT {}
316  ~Promise() NLIB_NOEXCEPT {}
317  NLIB_MOVE_MEMBER_HELPER_1(Promise, value_)
318  errno_t SetValue(const R& value);
319 
320  // for doxygen :(
321  errno_t Init() NLIB_NOEXCEPT { return BaseType::Init(); }
322  errno_t SetError(errno_t e) NLIB_NOEXCEPT { return BaseType::SetError(e); }
323  errno_t GetFuture(Future<R>* p) NLIB_NOEXCEPT {
324  return BaseType::GetFuture(p);
325  }
326  void swap(Promise& rhs) NLIB_NOEXCEPT { BaseType::swap(rhs); }
327 
328  private:
329  struct Status {
330  typename BaseType::CommonStatus common;
331  R data;
332  };
333  LimitedSharedPtr<Status> value_;
335  template <class RR>
336  friend class Future;
337  template <class RR>
338  friend class detail::PromiseBase;
339 };
340 
341 template <class R>
342 errno_t Promise<R>::SetValue(const R& value) {
343  if (!value_) {
344  errno_t e = this->Init();
345  if (e != 0) return e;
346  }
347  {
348  ScopedLock<nlib_mutex> lock(value_->common.lock);
349  if (value_->common.SetReady()) {
350  NLIB_TRY {
351  value_->data = value; // may throw
352  }
353 #ifdef NLIB_EXCEPTION_ENABLED
354  NLIB_RETHROW_UNWIND {
355  this->SetError(ECANCELED);
356  throw;
357  }
358  NLIB_CATCH(...) {
359  return this->SetError(EINVAL);
360  }
361 #endif
362  } else {
363  return EALREADY;
364  }
365  }
366  this->NotifyAndContinuation();
367  return 0;
368 }
369 
370 template <class T, class DEL>
371 class Promise<UniquePtr<T, DEL> > : public detail::PromiseBase<Promise<UniquePtr<T, DEL> > > {
372  typedef detail::PromiseBase<Promise<UniquePtr<T, DEL> > > BaseType;
373  public:
375  Promise() NLIB_NOEXCEPT {}
376  NLIB_MOVE_MEMBER_HELPER_1(Promise, value_)
377  errno_t SetValue(T* value) NLIB_NOEXCEPT;
378 
379  private:
380  struct Status {
381  typename BaseType::CommonStatus common;
382  UniquePtr<T, DEL> data;
383  };
384  LimitedSharedPtr<Status> value_;
386  template <class RR>
387  friend class Future;
388  template <class RR>
389  friend class detail::PromiseBase;
390 };
391 
392 template <class T, class DEL>
393 errno_t Promise<UniquePtr<T, DEL> >::SetValue(T* value) NLIB_NOEXCEPT {
394  if (!value_) {
395  errno_t e = this->Init();
396  if (e != 0) return e;
397  }
398  {
399  value_->common.Lock();
400  if (value_->common.SetReady()) {
401  value_->data.reset(value);
402  value_->common.Unlock();
403  } else {
404  value_->common.Unlock();
405  return EALREADY;
406  }
407  }
408  this->NotifyAndContinuation();
409  return 0;
410 }
411 
412 template <class T, class DEL>
413 class Promise<UniquePtr<T[], DEL> > : public detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > {
414  typedef detail::PromiseBase<Promise<UniquePtr<T[], DEL> > > BaseType;
415  public:
417  Promise() NLIB_NOEXCEPT {}
418  NLIB_MOVE_MEMBER_HELPER_1(Promise, value_)
419  errno_t SetValue(T* value) NLIB_NOEXCEPT;
420 
421  private:
422  struct Status {
423  typename BaseType::CommonStatus common;
424  UniquePtr<T[], DEL> data;
425  };
426  LimitedSharedPtr<Status> value_;
428  template <class RR>
429  friend class Future;
430  template <class RR>
431  friend class detail::PromiseBase;
432 };
433 
434 template <class T, class DEL>
435 errno_t Promise<UniquePtr<T[], DEL> >::SetValue(T* value) NLIB_NOEXCEPT {
436  if (!value_) {
437  errno_t e = this->Init();
438  if (e != 0) return e;
439  }
440  {
441  value_->common.Lock();
442  if (value_->common.SetReady()) {
443  value_->data.reset(value);
444  value_->common.Unlock();
445  } else {
446  value_->common.Unlock();
447  return EALREADY;
448  }
449  }
450  this->NotifyAndContinuation();
451  return 0;
452 }
453 
454 template <>
455 class Promise<void> : public detail::PromiseBase<Promise<void> > {
456  typedef detail::PromiseBase<Promise<void> > BaseType;
457  public:
458  typedef Future<void> FutureType;
459  Promise() NLIB_NOEXCEPT {}
460  NLIB_MOVE_MEMBER_HELPER_1(Promise, value_)
462 
463  private:
464  struct Status {
465  BaseType::CommonStatus common;
466  };
467  LimitedSharedPtr<Status> value_;
469  template <class RR>
470  friend class Future;
471  template <class RR>
472  friend class detail::PromiseBase;
473 };
474 
475 template <class R>
476 class Promise<Future<R> > : public detail::PromiseBase<Promise<Future<R> > > {
477  typedef detail::PromiseBase<Promise<Future<R> > > BaseType;
478  public:
479  typedef Future<Future<R> > FutureType;
480  Promise() NLIB_NOEXCEPT {}
481  NLIB_MOVE_MEMBER_HELPER_1(Promise, value_)
482  errno_t SetValue(const Future<R>& value) NLIB_NOEXCEPT;
483 
484  private:
485  struct Status {
486  typename BaseType::CommonStatus common;
487  Future<R> data;
488  };
489  LimitedSharedPtr<Status> value_;
491  template <class RR>
492  friend class Future;
493  template <class RR>
494  friend class detail::PromiseBase;
495 };
496 
497 template <class R>
498 errno_t Promise<Future<R> >::SetValue(const Future<R>& value) NLIB_NOEXCEPT {
499  if (!value_) {
500  errno_t e = this->Init();
501  if (e != 0) return e;
502  }
503  {
504  value_->common.Lock();
505  if (value_->common.SetReady()) {
506  errno_t e = value_->data.MakeSharedFrom(value);
507  value_->common.Unlock();
508  if (e != 0) {
509  return e;
510  }
511  } else {
512  value_->common.Unlock();
513  return EALREADY;
514  }
515  }
516  this->NotifyAndContinuation();
517  return 0;
518 }
519 
520 template <class R>
521 class Future : public detail::FutureBase<Future<R> > {
522  typedef detail::FutureBase<Future<R> > BaseType;
523 
524  public:
525  Future() NLIB_NOEXCEPT {}
526  NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
527  R Get() {
528  R tmp = R(); // may throw
529  errno_t e = this->Get(&tmp);
530  NLIB_UNUSED(e);
531  NLIB_ASSERT_NOERR(e);
532  return tmp;
533  }
534  errno_t Get(R* ptr) {
535  if (!ptr) return EINVAL;
536  BaseType::Wait();
537  errno_t e = value_->common.err;
538  if (e == 0) {
539  NLIB_TRY {
540  *ptr = value_->data; // may throw
541  }
542 #ifdef NLIB_EXCEPTION_ENABLED
543  NLIB_RETHROW_UNWIND {
544  throw;
545  }
546  NLIB_CATCH(...) { return ENOMEM; }
547 #endif
548  }
549  return e;
550  }
551  // for doxygen :(
552  bool IsValid() const NLIB_NOEXCEPT { return BaseType::IsValid(); }
553  bool IsReady() const NLIB_NOEXCEPT { return BaseType::IsReady(); }
554  errno_t Wait() NLIB_NOEXCEPT { return BaseType::Wait(); }
555  NLIB_CHECK_RESULT errno_t WaitFor(const TimeSpan& span) NLIB_NOEXCEPT {
556  return BaseType::WaitFor(span);
557  }
558  NLIB_CHECK_RESULT errno_t WaitUntil(const DateTime& datetime) NLIB_NOEXCEPT {
559  return BaseType::WaitUntil(datetime);
560  }
561  template <class RNEXT>
562  errno_t Then(Future<RNEXT>* next, RNEXT (*cont)(Future<R>&)) NLIB_NOEXCEPT {
563  return BaseType::Then(next, cont);
564  }
565  errno_t MakeSharedFrom(const Future& f) NLIB_NOEXCEPT { return BaseType::MakeSharedFrom(f); }
566 
567  private:
568  LimitedSharedPtr<typename Promise<R>::Status> value_;
570  template <class RR>
571  friend class Promise;
572  template <class RR>
573  friend class detail::FutureBase;
574  template <class RR>
575  friend class detail::PromiseBase;
576 };
577 
578 template <class T, class DEL>
579 class Future<UniquePtr<T, DEL> > : public detail::FutureBase<Future<UniquePtr<T, DEL> > > {
580  typedef detail::FutureBase<Future<UniquePtr<T, DEL> > > BaseType;
581 
582  public:
583  Future() NLIB_NOEXCEPT {}
584  NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
585  T* Get() NLIB_NOEXCEPT {
586  BaseType::Wait();
587  return value_->data.get();
588  }
589  errno_t Get(T** ptr) NLIB_NOEXCEPT {
590  if (!ptr) return EINVAL;
591  BaseType::Wait();
592  errno_t e = value_->common.err;
593  if (e == 0) *ptr = value_->data.get();
594  return e;
595  }
596  T* Release() NLIB_NOEXCEPT {
597  BaseType::Wait();
598  return value_->data.release();
599  }
600 
601  private:
602  LimitedSharedPtr<typename Promise<UniquePtr<T, DEL> >::Status> value_;
604  template <class RR>
605  friend class Promise;
606  template <class RR>
607  friend class detail::FutureBase;
608  template <class RR>
609  friend class detail::PromiseBase;
610 };
611 
612 template <class T, class DEL>
613 class Future<UniquePtr<T[], DEL> > : public detail::FutureBase<Future<UniquePtr<T[], DEL> > > {
614  typedef detail::FutureBase<Future<UniquePtr<T[], DEL> > > BaseType;
615 
616  public:
617  Future() NLIB_NOEXCEPT {}
618  NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
619  T* Get() NLIB_NOEXCEPT {
620  BaseType::Wait();
621  return value_->data.get();
622  }
623  errno_t Get(T** ptr) NLIB_NOEXCEPT {
624  if (!ptr) return EINVAL;
625  BaseType::Wait();
626  errno_t e = value_->common.err;
627  if (e == 0) *ptr = value_->data.get();
628  return e;
629  }
630  T* Release() NLIB_NOEXCEPT {
631  BaseType::Wait();
632  return value_->common.data.release();
633  }
634 
635  private:
636  LimitedSharedPtr<typename Promise<UniquePtr<T[], DEL> >::Status> value_;
638  template <class RR>
639  friend class Promise;
640  template <class RR>
641  friend class detail::FutureBase;
642  template <class RR>
643  friend class detail::PromiseBase;
644 };
645 
646 template <>
647 class Future<void> : public detail::FutureBase<Future<void> > {
648  typedef detail::FutureBase<Future<void> > BaseType;
649 
650  public:
651  Future() NLIB_NOEXCEPT {}
652  NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
653  errno_t Get() NLIB_NOEXCEPT {
654  BaseType::Wait();
655  return value_->common.err;
656  }
657 
658  private:
659  LimitedSharedPtr<Promise<void>::Status> value_;
661  template <class RR>
662  friend class Promise;
663  template <class RR>
664  friend class detail::FutureBase;
665  template <class RR>
666  friend class detail::PromiseBase;
667 };
668 
669 template <class R>
670 class Future<Future<R> > : public detail::FutureBase<Future<Future<R> > > {
671  typedef detail::FutureBase<Future<Future<R> > > BaseType;
672 
673  public:
674  Future() NLIB_NOEXCEPT {}
675  NLIB_MOVE_MEMBER_HELPER_1(Future, value_)
676  errno_t Get(Future<R>* inner) NLIB_NOEXCEPT {
677  if (!inner) return EINVAL;
678  BaseType::Wait();
679  errno_t e = value_->common.err;
680  if (e != 0) return e;
681  return inner->MakeSharedFrom(value_->data);
682  }
683 
684  private:
685  LimitedSharedPtr<typename Promise<Future<R> >::Status> value_;
687  template <class RR>
688  friend class Promise;
689  template <class RR>
690  friend class detail::FutureBase;
691  template <class RR>
692  friend class detail::PromiseBase;
693 };
694 
695 namespace detail {
696 
697 template <class R>
698 class FuncHolderBase0 {
699  public:
700  virtual ~FuncHolderBase0() {}
701  virtual R operator()() = 0; // NOLINT
702 };
703 
704 template <class R, class T1>
705 class FuncHolderBase1 {
706  public:
707  virtual ~FuncHolderBase1() {}
708  virtual R operator()(T1 NLIB_RREF arg1) = 0; // NOLINT
709 };
710 
711 template <class R, class T1, class T2>
712 class FuncHolderBase2 {
713  public:
714  virtual ~FuncHolderBase2() {}
715  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) = 0; // NOLINT
716 };
717 
718 template <class R, class T1, class T2, class T3>
719 class FuncHolderBase3 {
720  public:
721  virtual ~FuncHolderBase3() {}
722  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) = 0; // NOLINT
723 };
724 
725 template <class R, class T1, class T2, class T3, class T4>
726 class FuncHolderBase4 {
727  public:
728  virtual ~FuncHolderBase4() {}
729  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
730  T4 NLIB_RREF arg4) = 0;
731 };
732 
733 template <class R, class T1, class T2, class T3, class T4, class T5>
734 class FuncHolderBase5 {
735  public:
736  virtual ~FuncHolderBase5() {}
737  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
738  T5 NLIB_RREF arg5) = 0;
739 };
740 
741 template <class FUNC, bool USESWAP>
742 class FuncWrap_ {
743  public:
744  FuncWrap_(FUNC& func) NLIB_NOEXCEPT : func_() { // NOLINT
745  using std::swap;
746  swap(func, func_);
747  }
748  FUNC& get() NLIB_NOEXCEPT { return func_; }
749 
750  protected:
751  FUNC func_;
753 };
754 
755 template <class FUNC>
756 class FuncWrap_<FUNC, false> {
757  public:
758  FuncWrap_(FUNC& func) : func_(func) {} // NOLINT
759  FUNC& get() NLIB_NOEXCEPT { return func_; }
760 
761  protected:
762  FUNC func_;
764 };
765 
766 template <class FUNC>
767 class FuncWrap : public FuncWrap_<FUNC, IsSwappable<FUNC>::value> {
768  typedef FuncWrap_<FUNC, IsSwappable<FUNC>::value> BaseType;
769 
770  public:
771  FuncWrap(FUNC& func) : BaseType(func) {} // NOLINT
772 };
773 
774 template <class R>
775 class FuncWrap<R()> {
776  public:
777  typedef R (*FUNC)();
778  explicit FuncWrap(FUNC func) : func_(func) {}
779  FUNC& get() NLIB_NOEXCEPT { return func_; }
780 
781  protected:
782  FUNC func_;
784 };
785 
786 template <class R, class T1>
787 class FuncWrap<R(T1)> {
788  public:
789  typedef R (*FUNC)(T1);
790  explicit FuncWrap(FUNC func) : func_(func) {}
791  FUNC& get() NLIB_NOEXCEPT { return func_; }
792 
793  protected:
794  FUNC func_;
796 };
797 
798 template <class R, class T1, class T2>
799 class FuncWrap<R(T1, T2)> {
800  public:
801  typedef R (*FUNC)(T1, T2);
802  explicit FuncWrap(FUNC func) : func_(func) {}
803  FUNC& get() NLIB_NOEXCEPT { return func_; }
804 
805  protected:
806  FUNC func_;
808 };
809 
810 template <class R, class T1, class T2, class T3>
811 class FuncWrap<R(T1, T2, T3)> {
812  public:
813  typedef R (*FUNC)(T1, T2, T3);
814  explicit FuncWrap(FUNC func) : func_(func) {}
815  FUNC& get() NLIB_NOEXCEPT { return func_; }
816 
817  protected:
818  FUNC func_;
820 };
821 
822 template <class R, class T1, class T2, class T3, class T4>
823 class FuncWrap<R(T1, T2, T3, T4)> {
824  public:
825  typedef R (*FUNC)(T1, T2, T3, T4);
826  explicit FuncWrap(FUNC func) : func_(func) {}
827  FUNC& get() NLIB_NOEXCEPT { return func_; }
828 
829  protected:
830  FUNC func_;
832 };
833 
834 template <class R, class T1, class T2, class T3, class T4, class T5>
835 class FuncWrap<R(T1, T2, T3, T4, T5)> {
836  public:
837  typedef R (*FUNC)(T1, T2, T3, T4, T5);
838  explicit FuncWrap(FUNC func) : func_(func) {}
839  FUNC& get() NLIB_NOEXCEPT { return func_; }
840 
841  protected:
842  FUNC func_;
844 };
845 
846 template <class FUNC, class R>
847 class FuncHolder0 : public FuncHolderBase0<R> {
848  public:
849  FuncHolder0(FUNC& f) : func_(f) {} // NOLINT
850  virtual ~FuncHolder0() NLIB_OVERRIDE {}
851  virtual R operator()() NLIB_OVERRIDE { // NOLINT
852  return func_.get()();
853  }
854 
855  private:
856  FuncWrap<FUNC> func_;
857 };
858 
859 template <class FUNC, class R, class T1>
860 class FuncHolder1 : public FuncHolderBase1<R, T1> {
861  public:
862  FuncHolder1(FUNC& f) : func_(f) {} // NOLINT
863  virtual ~FuncHolder1() NLIB_OVERRIDE {}
864  virtual R operator()(T1 NLIB_RREF arg1)NLIB_OVERRIDE {
865  return func_.get()(NLIB_FWD(T1, arg1));
866  }
867 
868  private:
869  FuncWrap<FUNC> func_;
870 };
871 
872 template <class FUNC, class R, class T1, class T2>
873 class FuncHolder2 : public FuncHolderBase2<R, T1, T2> {
874  public:
875  FuncHolder2(FUNC& f) : func_(f) {} // NOLINT
876  virtual ~FuncHolder2() NLIB_OVERRIDE {}
877  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2)NLIB_OVERRIDE { // NOLINT
878  return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
879  }
880 
881  private:
882  FuncWrap<FUNC> func_;
883 };
884 
885 template <class FUNC, class R, class T1, class T2, class T3>
886 class FuncHolder3 : public FuncHolderBase3<R, T1, T2, T3> {
887  public:
888  FuncHolder3(FUNC& f) : func_(f) {} // NOLINT
889  virtual ~FuncHolder3() NLIB_OVERRIDE {}
890  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3)NLIB_OVERRIDE {
891  return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
892  }
893 
894  private:
895  FuncWrap<FUNC> func_;
896 };
897 
898 template <class FUNC, class R, class T1, class T2, class T3, class T4>
899 class FuncHolder4 : public FuncHolderBase4<R, T1, T2, T3, T4> {
900  public:
901  FuncHolder4(FUNC& f) : func_(f) {} // NOLINT
902  virtual ~FuncHolder4() NLIB_OVERRIDE {}
903  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
904  T4 NLIB_RREF arg4)NLIB_OVERRIDE { // NOLINT
905  return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
906  NLIB_FWD(T4, arg4));
907  }
908 
909  private:
910  FuncWrap<FUNC> func_;
911 };
912 
913 template <class FUNC, class R, class T1, class T2, class T3, class T4, class T5>
914 class FuncHolder5 : public FuncHolderBase5<R, T1, T2, T3, T4, T5> {
915  public:
916  FuncHolder5(FUNC& f) : func_(f) {} // NOLINT
917  virtual ~FuncHolder5() NLIB_OVERRIDE {}
918  virtual R operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
919  T5 NLIB_RREF arg5)NLIB_OVERRIDE { // NOLINT
920  return func_.get()(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
921  NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
922  }
923 
924  private:
925  FuncWrap<FUNC> func_;
926 };
927 
928 } // namespace detail
929 
930 template <class T>
931 class PackagedTask { // defined for doygen ....
932  public:
934  PackagedTask() NLIB_NOEXCEPT;
935  template <class FUNC>
936  errno_t Init(FUNC& func); // NOLINT
937  template <class R>
938  errno_t GetFuture(Future<R>* p) NLIB_NOEXCEPT;
939  void swap(PackagedTask& rhs) NLIB_NOEXCEPT;
940 };
941 
942 template <class R>
943 class PackagedTask<R()> {
944  public:
945  typedef R ReturnType;
946  typedef PackagedTask<ReturnType()> ThisType;
947  PackagedTask() NLIB_NOEXCEPT {}
948  NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, func_, promise_)
949  template <class FUNC>
950  errno_t Init(FUNC& func) { // NOLINT
951  errno_t e = promise_.Init();
952  if (e != 0) return e;
953  func_.reset(new (std::nothrow) detail::FuncHolder0<FUNC, R>(func));
954  return !func_ ? ENOMEM : 0;
955  }
956  errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT { return promise_.GetFuture(p); }
957  void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
958  using std::swap;
959  swap(func_, rhs.func_);
960  swap(promise_, rhs.promise_);
961  }
962  void operator()() { // NOLINT
963  Exec<R>();
964  }
965 
966  private:
967  template <class DUMMY>
968  typename EnableIf<!IsSame<DUMMY, void>::value, void>::type Exec() { // NOLINT
969  NLIB_TRY {
970  R rval = (*func_)();
971  errno_t e = GetFutureError(rval);
972  if (e == 0) {
973  promise_.SetValue(rval);
974  } else {
975  promise_.SetError(e);
976  }
977  }
978 #ifdef NLIB_EXCEPTION_ENABLED
979  NLIB_RETHROW_UNWIND {
980  promise_.SetError(ECANCELED);
981  throw;
982  }
983  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
984 #endif
985  }
986  template <class DUMMY>
987  typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec() { // NOLINT
988  NLIB_TRY {
989  (*func_)();
990  promise_.SetValue();
991  }
992 #ifdef NLIB_EXCEPTION_ENABLED
993  NLIB_RETHROW_UNWIND {
994  promise_.SetError(ECANCELED);
995  throw;
996  }
997  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
998 #endif
999  }
1000 
1002  Promise<R> promise_;
1004 };
1005 
1006 template <class R, class T1>
1007 class PackagedTask<R(T1)> {
1008  public:
1009  typedef R ReturnType;
1010  typedef PackagedTask<ReturnType(T1)> ThisType;
1011  PackagedTask() NLIB_NOEXCEPT {}
1012  NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, func_, promise_)
1013  template <class FUNC>
1014  errno_t Init(FUNC& func) { // NOLINT
1015  errno_t e = promise_.Init();
1016  if (e != 0) return e;
1017  func_.reset(new (std::nothrow) detail::FuncHolder1<FUNC, R, T1>(func));
1018  return !func_ ? ENOMEM : 0;
1019  }
1020  errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT { return promise_.GetFuture(p); }
1021  void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1022  using std::swap;
1023  swap(func_, rhs.func_);
1024  swap(promise_, rhs.promise_);
1025  }
1026  void operator()(T1 NLIB_RREF arg1) { Exec<R>(NLIB_FWD(T1, arg1)); }
1027 
1028  private:
1029  template <class DUMMY>
1030  typename EnableIf<!IsSame<DUMMY, void>::value, void>::type Exec(T1 NLIB_RREF arg1) { // NOLINT
1031  NLIB_TRY {
1032  R rval = (*func_)(NLIB_FWD(T1, arg1));
1033  errno_t e = GetFutureError(rval);
1034  if (e == 0) {
1035  promise_.SetValue(rval);
1036  } else {
1037  promise_.SetError(e);
1038  }
1039  }
1040 #ifdef NLIB_EXCEPTION_ENABLED
1041  NLIB_RETHROW_UNWIND {
1042  promise_.SetError(ECANCELED);
1043  throw;
1044  }
1045  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1046 #endif
1047  }
1048  template <class DUMMY>
1049  typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(T1 NLIB_RREF arg1) { // NOLINT
1050  NLIB_TRY {
1051  (*func_)(NLIB_FWD(T1, arg1));
1052  promise_.SetValue();
1053  }
1054 #ifdef NLIB_EXCEPTION_ENABLED
1055  NLIB_RETHROW_UNWIND {
1056  promise_.SetError(ECANCELED);
1057  throw;
1058  }
1059  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1060 #endif
1061  }
1062 
1064  Promise<R> promise_;
1066 };
1067 
1068 template <class R, class T1, class T2>
1069 class PackagedTask<R(T1, T2)> {
1070  public:
1071  typedef R ReturnType;
1072  typedef PackagedTask<ReturnType(T1, T2)> ThisType;
1073  PackagedTask() NLIB_NOEXCEPT {}
1074  NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, func_, promise_)
1075  template <class FUNC>
1076  errno_t Init(FUNC& func) { // NOLINT
1077  errno_t e = promise_.Init();
1078  if (e != 0) return e;
1079  func_.reset(new (std::nothrow) detail::FuncHolder2<FUNC, R, T1, T2>(func));
1080  return !func_ ? ENOMEM : 0;
1081  }
1082  errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT { return promise_.GetFuture(p); }
1083  void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1084  using std::swap;
1085  swap(func_, rhs.func_);
1086  swap(promise_, rhs.promise_);
1087  }
1088  void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) {
1089  Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1090  }
1091 
1092  private:
1093  template <class DUMMY>
1094  typename EnableIf<!IsSame<DUMMY, void>::value, void>::type Exec(
1095  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) { // NOLINT
1096  NLIB_TRY {
1097  R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1098  errno_t e = GetFutureError(rval);
1099  if (e == 0) {
1100  promise_.SetValue(rval);
1101  } else {
1102  promise_.SetError(e);
1103  }
1104  }
1105 #ifdef NLIB_EXCEPTION_ENABLED
1106  NLIB_RETHROW_UNWIND {
1107  promise_.SetError(ECANCELED);
1108  throw;
1109  }
1110  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1111 #endif
1112  }
1113  template <class DUMMY>
1114  typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1115  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2) { // NOLINT
1116  NLIB_TRY {
1117  (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2));
1118  promise_.SetValue();
1119  }
1120 #ifdef NLIB_EXCEPTION_ENABLED
1121  NLIB_RETHROW_UNWIND {
1122  promise_.SetError(ECANCELED);
1123  throw;
1124  }
1125  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1126 #endif
1127  }
1128 
1130  Promise<ReturnType> promise_;
1132 };
1133 
1134 template <class R, class T1, class T2, class T3>
1135 class PackagedTask<R(T1, T2, T3)> {
1136  public:
1137  typedef R ReturnType;
1138  typedef PackagedTask<ReturnType(T1, T2, T3)> ThisType;
1139  PackagedTask() NLIB_NOEXCEPT {}
1140  NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, func_, promise_)
1141  template <class FUNC>
1142  errno_t Init(FUNC& func) { // NOLINT
1143  errno_t e = promise_.Init();
1144  if (e != 0) return e;
1145  func_.reset(new (std::nothrow) detail::FuncHolder3<FUNC, R, T1, T2, T3>(func));
1146  return !func_ ? ENOMEM : 0;
1147  }
1148  errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT { return promise_.GetFuture(p); }
1149  void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1150  using std::swap;
1151  swap(func_, rhs.func_);
1152  swap(promise_, rhs.promise_);
1153  }
1154  void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) {
1155  Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1156  }
1157 
1158  private:
1159  template <class DUMMY>
1160  typename EnableIf<!IsSame<DUMMY, void>::value, void>::type Exec(
1161  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) { // NOLINT
1162  NLIB_TRY {
1163  R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1164  errno_t e = GetFutureError(rval);
1165  if (e == 0) {
1166  promise_.SetValue(rval);
1167  } else {
1168  promise_.SetError(e);
1169  }
1170  }
1171 #ifdef NLIB_EXCEPTION_ENABLED
1172  NLIB_RETHROW_UNWIND {
1173  promise_.SetError(ECANCELED);
1174  throw;
1175  }
1176  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1177 #endif
1178  }
1179  template <class DUMMY>
1180  typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1181  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3) { // NOLINT
1182  NLIB_TRY {
1183  (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3));
1184  promise_.SetValue();
1185  }
1186 #ifdef NLIB_EXCEPTION_ENABLED
1187  NLIB_RETHROW_UNWIND {
1188  promise_.SetError(ECANCELED);
1189  throw;
1190  }
1191  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1192 #endif
1193  }
1194 
1196  Promise<ReturnType> promise_;
1198 };
1199 
1200 template <class R, class T1, class T2, class T3, class T4>
1201 class PackagedTask<R(T1, T2, T3, T4)> {
1202  public:
1203  typedef R ReturnType;
1205  PackagedTask() NLIB_NOEXCEPT {}
1206  NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, func_, promise_)
1207  template <class FUNC>
1208  errno_t Init(FUNC& func) { // NOLINT
1209  errno_t e = promise_.Init();
1210  if (e != 0) return e;
1211  func_.reset(new (std::nothrow) detail::FuncHolder4<FUNC, R, T1, T2, T3, T4>(func));
1212  return !func_ ? ENOMEM : 0;
1213  }
1214  errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT { return promise_.GetFuture(p); }
1215  void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1216  using std::swap;
1217  swap(func_, rhs.func_);
1218  swap(promise_, rhs.promise_);
1219  }
1220  void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3,
1221  T4 NLIB_RREF arg4) {
1222  Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4));
1223  }
1224 
1225  private:
1226  template <class DUMMY>
1227  typename EnableIf<!IsSame<DUMMY, void>::value, void>::type Exec(
1228  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1229  NLIB_TRY {
1230  R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1231  NLIB_FWD(T4, arg4));
1232  errno_t e = GetFutureError(rval);
1233  if (e == 0) {
1234  promise_.SetValue(rval);
1235  } else {
1236  promise_.SetError(e);
1237  }
1238  }
1239 #ifdef NLIB_EXCEPTION_ENABLED
1240  NLIB_RETHROW_UNWIND {
1241  promise_.SetError(ECANCELED);
1242  throw;
1243  }
1244  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1245 #endif
1246  }
1247  template <class DUMMY>
1248  typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1249  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4) {
1250  NLIB_TRY {
1251  (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1252  NLIB_FWD(T4, arg4));
1253  promise_.SetValue();
1254  }
1255 #ifdef NLIB_EXCEPTION_ENABLED
1256  NLIB_RETHROW_UNWIND {
1257  promise_.SetError(ECANCELED);
1258  throw;
1259  }
1260  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1261 #endif
1262  }
1263 
1265  Promise<ReturnType> promise_;
1267 };
1268 
1269 template <class R, class T1, class T2, class T3, class T4, class T5>
1270 class PackagedTask<R(T1, T2, T3, T4, T5)> {
1271  public:
1272  typedef R ReturnType;
1274  PackagedTask() NLIB_NOEXCEPT {}
1275  NLIB_MOVE_MEMBER_HELPER_2(PackagedTask, func_, promise_)
1276  template <class FUNC>
1277  errno_t Init(FUNC& func) { // NOLINT
1278  errno_t e = promise_.Init();
1279  if (e != 0) return e;
1280  func_.reset(new (std::nothrow) detail::FuncHolder5<FUNC, R, T1, T2, T3, T4, T5>(func));
1281  return !func_ ? ENOMEM : 0;
1282  }
1283  errno_t GetFuture(Future<ReturnType>* p) NLIB_NOEXCEPT { return promise_.GetFuture(p); }
1284  void swap(PackagedTask& rhs) NLIB_NOEXCEPT {
1285  using std::swap;
1286  swap(func_, rhs.func_);
1287  swap(promise_, rhs.promise_);
1288  }
1289  void operator()(T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1290  T5 NLIB_RREF arg5) { // NOLINT
1291  Exec<R>(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3), NLIB_FWD(T4, arg4),
1292  NLIB_FWD(T5, arg5));
1293  }
1294 
1295  private:
1296  template <class DUMMY>
1297  typename EnableIf<!IsSame<DUMMY, void>::value, void>::type Exec(
1298  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1299  T5 NLIB_RREF arg5) {
1300  NLIB_TRY {
1301  R rval = (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1302  NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1303  errno_t e = GetFutureError(rval);
1304  if (e == 0) {
1305  promise_.SetValue(rval);
1306  } else {
1307  promise_.SetError(e);
1308  }
1309  }
1310 #ifdef NLIB_EXCEPTION_ENABLED
1311  NLIB_RETHROW_UNWIND {
1312  promise_.SetError(ECANCELED);
1313  throw;
1314  }
1315  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1316 #endif
1317  }
1318  template <class DUMMY>
1319  typename EnableIf<IsSame<DUMMY, void>::value, DUMMY>::type Exec(
1320  T1 NLIB_RREF arg1, T2 NLIB_RREF arg2, T3 NLIB_RREF arg3, T4 NLIB_RREF arg4,
1321  T5 NLIB_RREF arg5) {
1322  NLIB_TRY {
1323  (*func_)(NLIB_FWD(T1, arg1), NLIB_FWD(T2, arg2), NLIB_FWD(T3, arg3),
1324  NLIB_FWD(T4, arg4), NLIB_FWD(T5, arg5));
1325  promise_.SetValue();
1326  }
1327 #ifdef NLIB_EXCEPTION_ENABLED
1328  NLIB_RETHROW_UNWIND {
1329  promise_.SetError(ECANCELED);
1330  throw;
1331  }
1332  NLIB_CATCH(...) { promise_.SetError(EINVAL); }
1333 #endif
1334  }
1335 
1337  Promise<ReturnType> promise_;
1339 };
1340 
1341 namespace detail {
1342 
1343 template <class T, bool B>
1344 struct XHolder {
1345  explicit XHolder(const T& value_) : value() {
1346  using std::swap;
1347  swap(const_cast<T&>(value_), value);
1348  }
1349  T value;
1350 };
1351 
1352 template <class T>
1353 struct XHolder<T, false> {
1354  explicit XHolder(const T& value_) : value(value_) {}
1355  T value;
1356 };
1357 
1358 template <class R>
1359 struct XHolder<R(), false> {
1360  XHolder(R (*value_)()) : value(value_) {}
1361  R (*value)();
1362 };
1363 
1364 template <class R, class T1>
1365 struct XHolder<R(T1), false> {
1366  XHolder(R (*value_)(T1)) : value(value_) {}
1367  R (*value)(T1);
1368 };
1369 
1370 template <class R, class T1, class T2>
1371 struct XHolder<R(T1, T2), false> {
1372  XHolder(R (*value_)(T1, T2)) : value(value_) {}
1373  R (*value)(T1, T2);
1374 };
1375 
1376 template <class R, class T1, class T2, class T3>
1377 struct XHolder<R(T1, T2, T3), false> {
1378  XHolder(R (*value_)(T1, T2, T3)) : value(value_) {}
1379  R (*value)(T1, T2, T3);
1380 };
1381 
1382 template <class R, class T1, class T2, class T3, class T4>
1383 struct XHolder<R(T1, T2, T3, T4), false> {
1384  XHolder(R (*value_)(T1, T2, T3, T4)) : value(value_) {}
1385  R (*value)(T1, T2, T3, T4);
1386 };
1387 
1388 template <class R, class T1, class T2, class T3, class T4, class T5>
1389 struct XHolder<R(T1, T2, T3, T4, T5), false> {
1390  XHolder(R (*value_)(T1, T2, T3, T4, T5)) : value(value_) {}
1391  R (*value)(T1, T2, T3, T4, T5);
1392 };
1393 
1394 #define NLIB_ASYNC_HOLDER(T, B) \
1395  XHolder<T, B::value && IsSwappable<T>::value && !IsArithmetic<T>::value>
1396 #define NLIB_ASYNC_HOLDER_F(FUNC, B) \
1397  XHolder<FUNC, B::value && IsSwappable<FUNC>::value && !IsPointer<FUNC>::value>
1398 
1399 template <class FUNC, class R, class BF>
1400 errno_t Async_(Future<R>* future, const FUNC& func, const ThreadSettings& settings, BF) {
1401  if (!future || !settings.GetDetachState()) return EINVAL;
1402  PackagedTask<R()> task;
1403  NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1404  errno_t e = task.Init(func_.value);
1405  if (e != 0) return e;
1406  e = task.GetFuture(future);
1407  if (e != 0) return e;
1408  Thread th;
1409  e = th.Start(settings, task, move_tag());
1410  return e;
1411 }
1412 
1413 template <class FUNC, class R, class BF, class T1>
1414 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const ThreadSettings& settings,
1415  BF) {
1416  if (!future || !settings.GetDetachState()) return EINVAL;
1417  PackagedTask<R(T1)> task;
1418  NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1419  errno_t e = task.Init(func_.value);
1420  if (e != 0) return e;
1421  e = task.GetFuture(future);
1422  if (e != 0) return e;
1423  Thread th;
1424  NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1425  e = th.Start(settings, task, arg1_.value, move_tag());
1426  return e;
1427 }
1428 
1429 template <class FUNC, class R, class BF, class T1, class T2>
1430 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1431  const ThreadSettings& settings, BF) {
1432  if (!future || !settings.GetDetachState()) return EINVAL;
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;
1439  Thread th;
1440  NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1441  NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1442  e = th.Start(settings, task, arg1_.value, arg2_.value, move_tag());
1443  return e;
1444 }
1445 
1446 template <class FUNC, class R, class BF, class T1, class T2, class T3>
1447 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2, const T3& arg3,
1448  const ThreadSettings& settings, BF) {
1449  if (!future || !settings.GetDetachState()) return EINVAL;
1451  NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1452  errno_t e = task.Init(func_.value);
1453  if (e != 0) return e;
1454  e = task.GetFuture(future);
1455  if (e != 0) return e;
1456  Thread th;
1457  NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1458  NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1459  NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1460  e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, move_tag());
1461  return e;
1462 }
1463 
1464 template <class FUNC, class R, class BF, class T1, class T2, class T3, class T4>
1465 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2, const T3& arg3,
1466  const T4& arg4, const ThreadSettings& settings, BF) {
1467  if (!future || !settings.GetDetachState()) return EINVAL;
1469  NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1470  errno_t e = task.Init(func_.value);
1471  if (e != 0) return e;
1472  e = task.GetFuture(future);
1473  if (e != 0) return e;
1474  Thread th;
1475  NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1476  NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1477  NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1478  NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1479  e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, move_tag());
1480  return e;
1481 }
1482 
1483 template <class FUNC, class R, class BF, class T1, class T2, class T3, class T4, class T5>
1484 errno_t Async_(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2, const T3& arg3,
1485  const T4& arg4, const T5& arg5, const ThreadSettings& settings, BF) {
1486  if (!future || !settings.GetDetachState()) return EINVAL;
1488  NLIB_ASYNC_HOLDER_F(FUNC, BF) func_(func);
1489  errno_t e = task.Init(func_.value);
1490  if (e != 0) return e;
1491  e = task.GetFuture(future);
1492  if (e != 0) return e;
1493  Thread th;
1494  NLIB_ASYNC_HOLDER(T1, BF) arg1_(arg1);
1495  NLIB_ASYNC_HOLDER(T2, BF) arg2_(arg2);
1496  NLIB_ASYNC_HOLDER(T3, BF) arg3_(arg3);
1497  NLIB_ASYNC_HOLDER(T4, BF) arg4_(arg4);
1498  NLIB_ASYNC_HOLDER(T5, BF) arg5_(arg5);
1499  e = th.Start(settings, task, arg1_.value, arg2_.value, arg3_.value, arg4_.value, arg5_.value,
1500  move_tag());
1501  return e;
1502 }
1503 
1504 #undef NLIB_ASYNC_HOLDER
1505 #undef NLIB_ASYNC_HOLDER_F
1506 
1507 } // namespace detail
1508 
1509 template <class FUNC, class R>
1510 inline errno_t Async(Future<R>* future, const FUNC& func, const ThreadSettings& settings) {
1511  return detail::Async_(future, func, settings, FalseType());
1512 }
1513 
1514 template <class FUNC, class R>
1515 inline errno_t Async(Future<R>* future, const FUNC& func, const ThreadSettings& settings,
1516  move_tag) {
1517  return detail::Async_(future, func, settings, TrueType());
1518 }
1519 
1520 template <class FUNC, class R>
1521 inline errno_t Async(Future<R>* future, const FUNC& func) {
1522  ThreadSettings settings;
1523  settings.SetDetachState(true);
1524  return Async(future, func, settings);
1525 }
1526 
1527 template <class FUNC, class R>
1528 inline errno_t Async(Future<R>* future, const FUNC& func, move_tag) {
1529  ThreadSettings settings;
1530  settings.SetDetachState(true);
1531  return Async(future, func, settings, move_tag());
1532 }
1533 
1534 template <class FUNC, class R, class T1>
1535 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1,
1536  const ThreadSettings& settings) {
1537  return detail::Async_(future, func, arg1, settings, FalseType());
1538 }
1539 
1540 template <class FUNC, class R, class T1>
1541 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1,
1542  const ThreadSettings& settings, move_tag) {
1543  return detail::Async_(future, func, arg1, settings, TrueType());
1544 }
1545 
1546 template <class FUNC, class R, class T1>
1547 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1) {
1548  ThreadSettings settings;
1549  settings.SetDetachState(true);
1550  return Async(future, func, arg1, settings);
1551 }
1552 
1553 template <class FUNC, class R, class T1>
1554 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, move_tag) {
1555  ThreadSettings settings;
1556  settings.SetDetachState(true);
1557  return Async(future, func, arg1, settings, move_tag());
1558 }
1559 
1560 template <class FUNC, class R, class T1, class T2>
1561 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1562  const ThreadSettings& settings) {
1563  return detail::Async_(future, func, arg1, arg2, settings, FalseType());
1564 }
1565 
1566 template <class FUNC, class R, class T1, class T2>
1567 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1568  const ThreadSettings& settings, move_tag) {
1569  return detail::Async_(future, func, arg1, arg2, settings, TrueType());
1570 }
1571 
1572 template <class FUNC, class R, class T1, class T2>
1573 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2) {
1574  ThreadSettings settings;
1575  settings.SetDetachState(true);
1576  return Async(future, func, arg1, arg2, settings);
1577 }
1578 
1579 template <class FUNC, class R, class T1, class T2>
1580 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1581  move_tag) {
1582  ThreadSettings settings;
1583  settings.SetDetachState(true);
1584  return Async(future, func, arg1, arg2, settings, move_tag());
1585 }
1586 
1587 template <class FUNC, class R, class T1, class T2, class T3>
1588 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1589  const T3& arg3, const ThreadSettings& settings) {
1590  return detail::Async_(future, func, arg1, arg2, arg3, settings, FalseType());
1591 }
1592 
1593 template <class FUNC, class R, class T1, class T2, class T3>
1594 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1595  const T3& arg3, const ThreadSettings& settings, move_tag) {
1596  return detail::Async_(future, func, arg1, arg2, arg3, settings, TrueType());
1597 }
1598 
1599 template <class FUNC, class R, class T1, class T2, class T3>
1600 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1601  const T3& arg3) {
1602  ThreadSettings settings;
1603  settings.SetDetachState(true);
1604  return Async(future, func, arg1, arg2, arg3, settings);
1605 }
1606 
1607 template <class FUNC, class R, class T1, class T2, class T3>
1608 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1609  const T3& arg3, move_tag) {
1610  ThreadSettings settings;
1611  settings.SetDetachState(true);
1612  return Async(future, func, arg1, arg2, arg3, settings, move_tag());
1613 }
1614 
1615 template <class FUNC, class R, class T1, class T2, class T3, class T4>
1616 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1617  const T3& arg3, const T4& arg4, const ThreadSettings& settings) {
1618  return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, FalseType());
1619 }
1620 
1621 template <class FUNC, class R, class T1, class T2, class T3, class T4>
1622 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1623  const T3& arg3, const T4& arg4, const ThreadSettings& settings, move_tag) {
1624  return detail::Async_(future, func, arg1, arg2, arg3, arg4, settings, TrueType());
1625 }
1626 
1627 template <class FUNC, class R, class T1, class T2, class T3, class T4>
1628 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1629  const T3& arg3, const T4& arg4) {
1630  ThreadSettings settings;
1631  settings.SetDetachState(true);
1632  return Async(future, func, arg1, arg2, arg3, arg4, settings);
1633 }
1634 
1635 template <class FUNC, class R, class T1, class T2, class T3, class T4>
1636 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1637  const T3& arg3, const T4& arg4, move_tag) {
1638  ThreadSettings settings;
1639  settings.SetDetachState(true);
1640  return Async(future, func, arg1, arg2, arg3, arg4, settings, move_tag());
1641 }
1642 
1643 template <class FUNC, class R, class T1, class T2, class T3, class T4, class T5>
1644 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1645  const T3& arg3, const T4& arg4, const T5& arg5,
1646  const ThreadSettings& settings) {
1647  return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, FalseType());
1648 }
1649 
1650 template <class FUNC, class R, class T1, class T2, class T3, class T4, class T5>
1651 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1652  const T3& arg3, const T4& arg4, const T5& arg5, const ThreadSettings& settings,
1653  move_tag) {
1654  return detail::Async_(future, func, arg1, arg2, arg3, arg4, arg5, settings, TrueType());
1655 }
1656 
1657 template <class FUNC, class R, class T1, class T2, class T3, class T4, class T5>
1658 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1659  const T3& arg3, const T4& arg4, const T5& arg5) {
1660  ThreadSettings settings;
1661  settings.SetDetachState(true);
1662  return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings);
1663 }
1664 
1665 template <class FUNC, class R, class T1, class T2, class T3, class T4, class T5>
1666 inline errno_t Async(Future<R>* future, const FUNC& func, const T1& arg1, const T2& arg2,
1667  const T3& arg3, const T4& arg4, const T5& arg5, move_tag) {
1668  ThreadSettings settings;
1669  settings.SetDetachState(true);
1670  return Async(future, func, arg1, arg2, arg3, arg4, arg5, settings, move_tag());
1671 }
1672 
1673 template <class R>
1674 inline errno_t MakeReadyFuture(Future<R>* future, const R& value) {
1675  if (!future) return EINVAL;
1676  Promise<R> promise;
1677  errno_t e = promise.Init();
1678  if (e != 0) return e;
1679  e = promise.SetValue(value);
1680  if (e != 0) return e;
1681  e = promise.GetFuture(future);
1682  if (e != 0) return e;
1683  return 0;
1684 }
1685 
1686 namespace detail {
1687 template <class FUTURE, class R, typename CONT>
1688 class FutureContinuation : public FutureContinuationBase {
1689  public:
1690  FutureContinuation(FUTURE& f, CONT cont) NLIB_NOEXCEPT // NOLINT
1691  : status_(0),
1692  parent_(f),
1693  func_(cont) {}
1694  errno_t Init() NLIB_NOEXCEPT { return next_.Init(); }
1695  errno_t GetFuture(Future<R>* future) NLIB_NOEXCEPT { return next_.GetFuture(future); }
1696  virtual ~FutureContinuation() NLIB_NOEXCEPT NLIB_OVERRIDE {}
1697  virtual void DoContinuation() NLIB_OVERRIDE;
1698 
1699  private:
1700  int32_t status_;
1701  FUTURE& parent_;
1702  CONT func_;
1703  Promise<R> next_;
1704 };
1705 
1706 template <class FUTURE, class R, typename CONT>
1707 void FutureContinuation<FUTURE, R, CONT>::DoContinuation() {
1708  int32_t expected = 0;
1709  if (nlib_atomic_compare_exchange32(&status_, &expected, 20120901L, 0,
1711  NLIB_TRY {
1712  R rval = func_(parent_);
1713  errno_t e = GetFutureError(rval);
1714  if (e == 0) {
1715  (void)next_.SetValue(rval);
1716  } else {
1717  (void)next_.SetError(e);
1718  }
1719  }
1720 #ifdef NLIB_EXCEPTION_ENABLED
1721  NLIB_RETHROW_UNWIND {
1722  next_.SetError(ECANCELED);
1723  throw;
1724  }
1725  NLIB_CATCH(...) { (void)next_.SetError(EINVAL); }
1726 #endif
1727  }
1728 }
1729 
1730 template <class Derived>
1731 template <class R>
1732 errno_t FutureBase<Derived>::Then(Future<R>* next, R (*cont)(Derived&)) NLIB_NOEXCEPT {
1733  Derived& ref = static_cast<Derived&>(*this);
1734  if (!ref.value_) return EINVAL;
1735 
1736  typedef R (*CONT)(Derived&);
1738  new (std::nothrow) FutureContinuation<Derived, R, CONT>(ref, cont));
1739  if (!ptr) return ENOMEM;
1740  errno_t e = ptr->Init();
1741  if (e != 0) return e;
1742  e = ptr->GetFuture(next);
1743  if (e != 0) return e;
1744 
1745  ref.value_->common.Lock();
1746  ref.value_->common.cont = ptr.release();
1747  bool isready = ref.IsReady_();
1748  ref.value_->common.Unlock();
1749  if (isready) {
1750  ref.value_->common.cont->DoContinuation();
1751  }
1752  return 0;
1753 }
1754 
1755 } // namespace detail
1756 
1757 template <class R1 = None, class R2 = None, class R3 = None, class R4 = None, class R5 = None>
1758 struct FutureTuple {
1759  Future<R1> f1;
1760  Future<R2> f2;
1761  Future<R3> f3;
1762  Future<R4> f4;
1763  Future<R5> f5;
1764 };
1765 
1766 template <>
1767 struct FutureTuple<None, None, None, None, None>;
1768 template <class R1>
1769 struct FutureTuple<R1, None, None, None, None>;
1770 
1771 template <class R1, class R2>
1772 struct FutureTuple<R1, R2, None, None, None> {
1773  Future<R1> f1;
1774  Future<R2> f2;
1775 };
1776 
1777 template <class R1, class R2, class R3>
1778 struct FutureTuple<R1, R2, R3, None, None> {
1779  Future<R1> f1;
1780  Future<R2> f2;
1781  Future<R3> f3;
1782 };
1783 
1784 template <class R1, class R2, class R3, class R4>
1785 struct FutureTuple<R1, R2, R3, R4, None> {
1786  Future<R1> f1;
1787  Future<R2> f2;
1788  Future<R3> f3;
1789  Future<R4> f4;
1790 };
1791 
1792 template <class R1 = None, class R2 = None, class R3 = None, class R4 = None, class R5 = None>
1794  public:
1797  static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
1798  Future<R4>* f4, Future<R5>* f5) {
1799  return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAll);
1800  }
1801  static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
1802  Future<R4>* f4, Future<R5>* f5) {
1803  return DoWhen(f, f1, f2, f3, f4, f5, CallWhenAny);
1804  }
1805 
1806  private:
1808  typedef void (*FuncType)(ArgType& ptr); // NOLINT
1809  static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
1810  Future<R4>* f4, Future<R5>* f5, FuncType func);
1811  static void Call(ArgType& ptr) { // NOLINT
1812  // called from Thread::Exec()
1813  ptr->func_(ptr);
1814  }
1815  static void CallWhenAny(ArgType& ptr) { // NOLINT
1816  for (;;) {
1817  if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
1818  ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady() ||
1819  ptr->tuple_->f5.IsReady()) {
1820  break;
1821  }
1822  this_thread::Sleep(TimeSpan(0, 0, 0, 200));
1823  }
1824  ptr->promise_.SetValue(ptr->tuple_.release());
1825  }
1826  static void CallWhenAll(ArgType& ptr) { // NOLINT
1827  ptr->tuple_->f1.Wait();
1828  ptr->tuple_->f2.Wait();
1829  ptr->tuple_->f3.Wait();
1830  ptr->tuple_->f4.Wait();
1831  ptr->tuple_->f5.Wait();
1832  ptr->promise_.SetValue(ptr->tuple_.release());
1833  }
1834  explicit WhenFutureComplete(FuncType f) : func_(f) {}
1836  Future<R4>* f4, Future<R5>* f5) {
1837  errno_t e = promise_.Init();
1838  if (e != 0) return e;
1839  tuple_.reset(new (std::nothrow) FutureTuple<R1, R2, R3, R4, R5>());
1840  if (!tuple_) return ENOMEM;
1841  e = promise_.GetFuture(f);
1842  if (e != 0) return e;
1843  e = tuple_->f1.MakeSharedFrom(*f1);
1844  if (e != 0) return e;
1845  e = tuple_->f2.MakeSharedFrom(*f2);
1846  if (e != 0) return e;
1847  e = tuple_->f3.MakeSharedFrom(*f3);
1848  if (e != 0) return e;
1849  e = tuple_->f4.MakeSharedFrom(*f4);
1850  if (e != 0) return e;
1851  e = tuple_->f5.MakeSharedFrom(*f5);
1852  if (e != 0) return e;
1853  return 0;
1854  }
1855 
1856  private:
1857  FuncType func_;
1858  ReturnType tuple_;
1859  Promise<ReturnType> promise_;
1861  friend class Thread;
1862 };
1863 
1864 template <class R1, class R2, class R3, class R4, class R5>
1866  Future<R2>* f2, Future<R3>* f3,
1867  Future<R4>* f4, Future<R5>* f5,
1868  FuncType func) {
1869  if (!f1 || !f2 || !f3 || !f4 || !f5) return EINVAL;
1870  ArgType ptr(new (std::nothrow) WhenFutureComplete(func));
1871  if (!ptr) return 0;
1872  errno_t e;
1873  e = ptr->Init(f, f1, f2, f3, f4, f5);
1874  if (e != 0) return e;
1875  Thread th;
1876  e = th.StartRaw(ptr);
1877  if (e != 0) return e;
1878  return 0;
1879 }
1880 
1881 template <>
1882 class WhenFutureComplete<None, None, None, None, None>;
1883 template <class R1>
1884 class WhenFutureComplete<R1, None, None, None, None>;
1885 
1886 template <class R1, class R2>
1887 class WhenFutureComplete<R1, R2, None, None, None> {
1888  public:
1891  static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2) {
1892  return DoWhen(f, f1, f2, CallWhenAll);
1893  }
1894  static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2) {
1895  return DoWhen(f, f1, f2, CallWhenAny);
1896  }
1897 
1898  private:
1900  typedef void (*FuncType)(ArgType& ptr); // NOLINT
1901  static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, FuncType func);
1902  static void Call(ArgType& ptr) { // NOLINT
1903  // called from Thread::Exec()
1904  ptr->func_(ptr);
1905  }
1906  static void CallWhenAny(ArgType& ptr) { // NOLINT
1907  for (;;) {
1908  if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady()) {
1909  break;
1910  }
1911  this_thread::Sleep(TimeSpan(0, 0, 0, 200));
1912  }
1913  ptr->promise_.SetValue(ptr->tuple_.release());
1914  }
1915  static void CallWhenAll(ArgType& ptr) { // NOLINT
1916  ptr->tuple_->f1.Wait();
1917  ptr->tuple_->f2.Wait();
1918  ptr->promise_.SetValue(ptr->tuple_.release());
1919  }
1920  explicit WhenFutureComplete(FuncType f) : func_(f) {}
1921  errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2) {
1922  errno_t e = promise_.Init();
1923  if (e != 0) return e;
1924  tuple_.reset(new (std::nothrow) FutureTuple<R1, R2>());
1925  if (!tuple_) return ENOMEM;
1926  e = promise_.GetFuture(f);
1927  if (e != 0) return e;
1928  e = tuple_->f1.MakeSharedFrom(*f1);
1929  if (e != 0) return e;
1930  e = tuple_->f2.MakeSharedFrom(*f2);
1931  if (e != 0) return e;
1932  return 0;
1933  }
1934 
1935  private:
1936  FuncType func_;
1937  ReturnType tuple_;
1938  Promise<ReturnType> promise_;
1940  friend class Thread;
1941 };
1942 
1943 template <class R1, class R2>
1945  FuncType func) {
1946  if (!f1 || !f2) return EINVAL;
1947  ArgType ptr(new (std::nothrow) WhenFutureComplete(func));
1948  if (!ptr) return 0;
1949  errno_t e;
1950  e = ptr->Init(f, f1, f2);
1951  if (e != 0) return e;
1952  Thread th;
1953  e = th.StartRaw(ptr);
1954  if (e != 0) return e;
1955  return 0;
1956 }
1957 
1958 template <class R1, class R2, class R3>
1959 class WhenFutureComplete<R1, R2, R3, None, None> {
1960  public:
1963  static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
1964  return DoWhen(f, f1, f2, f3, CallWhenAll);
1965  }
1966  static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
1967  return DoWhen(f, f1, f2, f3, CallWhenAny);
1968  }
1969 
1970  private:
1972  typedef void (*FuncType)(ArgType& ptr); // NOLINT
1973  static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
1974  FuncType func);
1975  static void Call(ArgType& ptr) { // NOLINT
1976  // called from Thread::Exec()
1977  ptr->func_(ptr);
1978  }
1979  static void CallWhenAny(ArgType& ptr) { // NOLINT
1980  for (;;) {
1981  if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
1982  ptr->tuple_->f3.IsReady()) {
1983  break;
1984  }
1985  this_thread::Sleep(TimeSpan(0, 0, 0, 200));
1986  }
1987  ptr->promise_.SetValue(ptr->tuple_.release());
1988  }
1989  static void CallWhenAll(ArgType& ptr) { // NOLINT
1990  ptr->tuple_->f1.Wait();
1991  ptr->tuple_->f2.Wait();
1992  ptr->tuple_->f3.Wait();
1993  ptr->promise_.SetValue(ptr->tuple_.release());
1994  }
1995  explicit WhenFutureComplete(FuncType f) : func_(f) {}
1996  errno_t Init(Future<ReturnType>* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3) {
1997  errno_t e = promise_.Init();
1998  if (e != 0) return e;
1999  tuple_.reset(new (std::nothrow) FutureTuple<R1, R2, R3>());
2000  if (!tuple_) return ENOMEM;
2001  e = promise_.GetFuture(f);
2002  if (e != 0) return e;
2003  e = tuple_->f1.MakeSharedFrom(*f1);
2004  if (e != 0) return e;
2005  e = tuple_->f2.MakeSharedFrom(*f2);
2006  if (e != 0) return e;
2007  e = tuple_->f3.MakeSharedFrom(*f3);
2008  if (e != 0) return e;
2009  return 0;
2010  }
2011 
2012  private:
2013  FuncType func_;
2014  ReturnType tuple_;
2015  Promise<ReturnType> promise_;
2017  friend class Thread;
2018 };
2019 
2020 template <class R1, class R2, class R3>
2022  Future<R3>* f3, FuncType func) {
2023  if (!f1 || !f2 || !f3) return EINVAL;
2024  ArgType ptr(new (std::nothrow) WhenFutureComplete(func));
2025  if (!ptr) return 0;
2026  errno_t e;
2027  e = ptr->Init(f, f1, f2, f3);
2028  if (e != 0) return e;
2029  Thread th;
2030  e = th.StartRaw(ptr);
2031  if (e != 0) return e;
2032  return 0;
2033 }
2034 
2035 template <class R1, class R2, class R3, class R4>
2036 class WhenFutureComplete<R1, R2, R3, R4, None> {
2037  public:
2040  static errno_t All(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2041  Future<R4>* f4) {
2042  return DoWhen(f, f1, f2, f3, f4, CallWhenAll);
2043  }
2044  static errno_t Any(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2045  Future<R4>* f4) {
2046  return DoWhen(f, f1, f2, f3, f4, CallWhenAny);
2047  }
2048 
2049  private:
2051  typedef void (*FuncType)(ArgType& ptr); // NOLINT
2052  static errno_t DoWhen(FutureType* f, Future<R1>* f1, Future<R2>* f2, Future<R3>* f3,
2053  Future<R4>* f4, FuncType func);
2054  static void Call(ArgType& ptr) { // NOLINT
2055  // called from Thread::Exec()
2056  ptr->func_(ptr);
2057  }
2058  static void CallWhenAny(ArgType& ptr) { // NOLINT
2059  for (;;) {
2060  if (ptr->tuple_->f1.IsReady() || ptr->tuple_->f2.IsReady() ||
2061  ptr->tuple_->f3.IsReady() || ptr->tuple_->f4.IsReady()) {
2062  break;
2063  }
2064  this_thread::Sleep(TimeSpan(0, 0, 0, 200));
2065  }
2066  ptr->promise_.SetValue(ptr->tuple_.release());
2067  }
2068  static void CallWhenAll(ArgType& ptr) { // NOLINT
2069  ptr->tuple_->f1.Wait();
2070  ptr->tuple_->f2.Wait();
2071  ptr->tuple_->f3.Wait();
2072  ptr->tuple_->f4.Wait();
2073  ptr->promise_.SetValue(ptr->tuple_.release());
2074  }
2075  explicit WhenFutureComplete(FuncType f) : func_(f) {}
2077  Future<R4>* f4) {
2078  errno_t e = promise_.Init();
2079  if (e != 0) return e;
2080  tuple_.reset(new (std::nothrow) FutureTuple<R1, R2, R3, R4>());
2081  if (!tuple_) return ENOMEM;
2082  e = promise_.GetFuture(f);
2083  if (e != 0) return e;
2084  e = tuple_->f1.MakeSharedFrom(*f1);
2085  if (e != 0) return e;
2086  e = tuple_->f2.MakeSharedFrom(*f2);
2087  if (e != 0) return e;
2088  e = tuple_->f3.MakeSharedFrom(*f3);
2089  if (e != 0) return e;
2090  e = tuple_->f4.MakeSharedFrom(*f4);
2091  if (e != 0) return e;
2092  return 0;
2093  }
2094 
2095  private:
2096  FuncType func_;
2097  ReturnType tuple_;
2098  Promise<ReturnType> promise_;
2100  friend class Thread;
2101 };
2102 
2103 template <class R1, class R2, class R3, class R4>
2105  Future<R3>* f3, Future<R4>* f4, FuncType func) {
2106  if (!f1 || !f2 || !f3 || !f4) return EINVAL;
2107  ArgType ptr(new (std::nothrow) WhenFutureComplete(func));
2108  if (!ptr) return 0;
2109  errno_t e;
2110  e = ptr->Init(f, f1, f2, f3, f4);
2111  if (e != 0) return e;
2112  Thread th;
2113  e = th.StartRaw(ptr);
2114  if (e != 0) return e;
2115  return 0;
2116 }
2117 
2118 } // namespace threading
2119 NLIB_NAMESPACE_END
2120 
2121 #ifndef NLIB_STD_SWAP_WORKAROUND
2122 NLIB_NAMESPACE_BEGIN
2123 #endif
2124 
2125 NLIB_DEFINE_STD_SWAP_T_BEGIN1(threading) // NOLINT
2126 NLIB_DEFINE_STD_SWAP_T1(R, NLIB_NS::threading::Promise) // NOLINT
2127 NLIB_DEFINE_STD_SWAP_T1(T, NLIB_NS::threading::PackagedTask) // NOLINT
2128 NLIB_DEFINE_STD_SWAP_T_END1(threading) // NOLINT
2129 
2130 #ifndef NLIB_STD_SWAP_WORKAROUND
2131 NLIB_NAMESPACE_END
2132 #endif
2133 
2134 #endif // INCLUDE_NN_NLIB_THREADING_FUTURE_H_
errno_t Start(const ThreadSettings &settings, const FUNC &f, move_tag)
This function is nearly identical to the version without start options, except that it can specify th...
Definition: Thread.h:536
errno_t MakeReadyFuture(Future< R > *future, const R &value)
Creates a Future with preset values.
Definition: Future.h:1674
int64_t tick
These can be used for nlib_time and nlib_duration.
Definition: DateTime.h:69
#define NLIB_OVERRIDE
Defines override if it is available for use. If not, holds an empty string.
Definition: Config.h:228
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.
Definition: Future.h:1666
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...
Definition: Future.h:1801
errno_t Sleep(const TimeSpan &span) noexcept
Makes the thread sleep for a specified period of time.
Definition: Thread.h:805
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:163
Implements mutex, reentrant timeout mutex, and reentrant mutex.
errno_t nlib_mutex_unlock(nlib_mutex *mutex) NLIB_RELEASE(*mutex)
Unlocks the specified mutex.
errno_t Wait() noexcept
Waits for conditions that allow results to be acquired.
Definition: Future.h:554
bool GetDetachState() const noexcept
Gets whether the thread is set to start in a detached state.
Definition: Thread.h:48
errno_t nlib_cond_broadcast(nlib_cond *cond)
Resumes the execution of all threads that are waiting for the conditional variable cond...
#define NLIB_CHECK_RESULT
Indicates that the caller of the function must check the returned value.
void swap(Promise &rhs) noexcept
Swaps an object.
Definition: Future.h:326
errno_t nlib_cond_init(nlib_cond *cond)
Initializes a condition variable.
void SetDetachState(bool detached) noexcept
Sets whether to start a thread in a detached state.
Definition: Thread.h:39
errno_t GetFuture(Future< R > *p) noexcept
Sets Future to get the result of execution.
Definition: Future.h:323
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Definition: UniquePtr.h:109
Defines that class that is corresponding to std::unique_ptr.
Class to create and start threads.
Definition: Thread.h:212
NLIB_CHECK_RESULT errno_t WaitUntil(const DateTime &datetime) noexcept
Waits for conditions that allow results to be acquired, until the defined time.
Definition: Future.h:558
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.
Definition: Future.h:41
errno_t nlib_mutex_init(nlib_mutex *mutex) NLIB_EXCLUDES(*mutex)
Initializes a mutex.
The class for representing the date and time.
Definition: DateTime.h:261
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:89
bool IsValid() const noexcept
Definition: Future.h:552
errno_t nlib_cond_wait(nlib_cond *cond, nlib_mutex *mutex) NLIB_REQUIRES(*mutex)
Unlocks mutex and waits for a condition variable. It then relocks mutex after execution resumes...
NLIB_CHECK_RESULT errno_t WaitFor(const TimeSpan &span) noexcept
Waits for conditions that allow results to be acquired, for a specified amount of time...
Definition: Future.h:555
#define NLIB_ATOMIC_ACQUIRE
Similar to __ATOMIC_ACQUIRE of gcc or std::memory_order_acquire of C++11.
Defines a Future for which to set the value, under the condition that a value has been set for the Fu...
Definition: Future.h:1793
errno_t SetError(errno_t e) noexcept
Sets an error value.
Definition: Future.h:322
Class to wrap nlib_thread_attr. nlib_thread_attr_init() and nlib_thread_attr_destroy() are run automa...
Definition: Thread.h:29
errno_t nlib_mutex_lock(nlib_mutex *mutex) NLIB_ACQUIRE(*mutex)
Locks the specified mutex.
errno_t GetFuture(Future< R > *p) noexcept
Sets Future to get the result of execution.
An empty structure indicating that an argument to a function needs to be moved.
Definition: Config.h:249
errno_t MakeSharedFrom(const Future &f) noexcept
Shares a Future so that it may be viewed.
Definition: Future.h:565
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.
Definition: Future.h:1797
#define NLIB_CATCH(x)
Defines catch(x) if exceptions are enabled. If not, defines if (true).
Definition: Config.h:129
Defines the thread.
#define NLIB_TRY
Defines try if exceptions are enabled. If not, defines if (true).
Definition: Config.h:128
errno_t nlib_cond_destroy(nlib_cond *cond)
Destroys a condition variable object.
errno_t Get(R *ptr)
Waits until a result is acquired, and then gets the result.
Definition: Future.h:534
Defines the class for handling times and durations.
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
pthread_cond_t nlib_cond
The type for a condition variable object.
errno_t GetFutureError(FutureResult &result) noexcept
Function that enables systems to get error values when threads hold an error value.
Definition: Future.h:33
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.
Definition: AsyncFileIo.h:26
Future< R > FutureType
The type for Future<R>.
Definition: Future.h:314
Wraps objects like CriticalSection. Locks with a constructor, and unlocks with a destructor.
errno_t StartRaw(ThreadFunc func, void *arg) noexcept
Starts running a function that has one void* type argument in a different thread. ...
pthread_mutex_t nlib_mutex
The type for mutex variables.
Class that wraps a function to run in a different thread, and gets the return value in a thread safe ...
Definition: Future.h:931
Promise() noexcept
Instantiates the object with default parameters (default constructor).
Definition: Future.h:315
TimeValue ToTimeValue() const noexcept
Returns a TimeValue object.
Definition: DateTime.h:310
bool IsReady() const noexcept
Returns whether a value has been set for Future (whether Promise set a value or an error)...
Definition: Future.h:553
errno_t SetValue(const R &value)
Sets a value, and makes it possible to use Future to extract it.
Definition: Future.h:342
int nlib_atomic_compare_exchange32(int32_t *ptr, int32_t *expected, int32_t desired, int weak, int success_memorder, int failure_memorder)
Compares and swaps atomic values. Its behavior is similar to the one for __atomic_compare_exchange_n(...
PackagedTask< T > ThisType
The object type.
Definition: Future.h:933
The class for representing the time.
Definition: DateTime.h:106
errno_t Then(Future< RNEXT > *next, RNEXT(*cont)(Future< R > &)) noexcept
Registers the process to continue (continuation) to this future.
Definition: Future.h:562
Future< ReturnType > FutureType
Type of the newly created Future.
Definition: Future.h:1796
Future() noexcept
Instantiates the object with default parameters (default constructor).
Definition: Future.h:525
errno_t Init() noexcept
Initializes the object.
Definition: Future.h:321
errno_t nlib_mutex_destroy(nlib_mutex *mutex) NLIB_EXCLUDES(*mutex)
Destroys the specified mutex object and frees any associated resources.
NLIB_CHECK_RESULT errno_t nlib_cond_wait_until(nlib_cond *cond, nlib_mutex *mutex, nlib_time abstime) NLIB_REQUIRES(*mutex)
Unlocks mutex and waits until abstime for a condition variable. It then relocks mutex after execution...
UniquePtr< FutureTuple< R1, R2, R3, R4, R5 > > ReturnType
Type of value to set to the newly created Future.
Definition: Future.h:1795
T * release() noexcept
Release ownership of the pointer and returns the pointer.
Definition: UniquePtr.h:146
errno_t Init(FUNC &func)
Performs initialization.
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:37