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