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