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