STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ppltasks.h
Go to the documentation of this file.
1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 * ==--==
7 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
8 *
9 * ppltasks.h
10 *
11 * Parallel Patterns Library - PPL Tasks
12 *
13 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
14 ****/
15 #pragma once
16 
17 #ifndef _PPLTASKS_H
18 #define _PPLTASKS_H
19 #include <pplwin.h>
20 
21 #include <functional>
22 #include <vector>
23 #include <utility>
24 #include <exception>
25 #include <algorithm>
26 #include <mutex>
27 
28 #if defined (__cplusplus_winrt)
29 #include <agile.h>
30 #endif /* #if defined(__cplusplus_winrt) */
31 
32 #ifdef _DEBUG
33  #define _DBG_ONLY(X) X
34 #else
35  #define _DBG_ONLY(X)
36 #endif // #ifdef _DEBUG
37 
38 #ifndef _PPLTASK_ASYNC_LOGGING
39 #define _PPLTASK_ASYNC_LOGGING 1
40 #endif // #ifndef _PPLTASK_ASYNC_LOGGING
41 
42 #if _PPLTASK_ASYNC_LOGGING
43 #pragma detect_mismatch("_PPLTASK_ASYNC_LOGGING", "1")
44 #else
45 #pragma detect_mismatch("_PPLTASK_ASYNC_LOGGING", "0")
46 #endif // #if _PPLTASK_ASYNC_LOGGING
47 
48 #pragma pack(push,_CRT_PACKING)
49 
50 #pragma warning(push)
51 #pragma warning(disable: 28197)
52 #pragma warning(disable: 4100) // Unreferenced formal parameter - needed for document generation
53 #pragma warning(disable: 4127) // constant express in if condition - we use it for meta programming
54 
55 // All CRT public header files are required to be protected from the macro new
56 #pragma push_macro("new")
57 #undef new
58 
59 // stuff ported from Dev11 CRT
60 // NOTE: this doesn't actually match std::declval. it behaves differently for void!
61 // so don't blindly change it to std::declval.
62 namespace Concurrency
63 {
64  namespace details
65  {
66  template<class _Ty>
67  _Ty&& declval();
68  }
69 }
70 
75 
76 namespace Concurrency
77 {
82 
84 
85 template <typename _Type> class task;
86 template <> class task<void>;
87 
88 // In debug builds, default to 10 frames, unless this is overridden prior to #include'ing ppltasks.h. In retail builds, default to only one frame.
89 #ifndef PPL_TASK_SAVE_FRAME_COUNT
90 #ifdef _DEBUG
91 #define PPL_TASK_SAVE_FRAME_COUNT 10
92 #else
93 #define PPL_TASK_SAVE_FRAME_COUNT 1
94 #endif
95 #endif
96 
97 #ifndef __EDG__
98 #define _EXPAND_STR(x) #x
99 #pragma detect_mismatch("ppltask_saved_frame_numbers", _EXPAND_STR(PPL_TASK_SAVE_FRAME_COUNT))
100 #undef _EXPAND_STR
101 #endif
102 
111 #if PPL_TASK_SAVE_FRAME_COUNT > 1
112 #if defined(__cplusplus_winrt) && !defined(_DEBUG)
113 #pragma message ("WARNING: Redefining PPL_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!")
114 #endif
115 #define _CAPTURE_CALLSTACK() ::Concurrency::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(_ReturnAddress(), PPL_TASK_SAVE_FRAME_COUNT)
116 #else
117 #define _CAPTURE_CALLSTACK() ::Concurrency::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
118 #endif
119 
120 
130 
131 inline __declspec(noreturn) void __cdecl cancel_current_task()
132 {
133  _THROW_NCEE(task_canceled, _EMPTY_ARGUMENT);
134 }
135 
136 namespace details
137 {
139  {
144  static void __declspec(noreturn) __cdecl _NoCallOnDefaultTask_ErrorImpl()
145  {
146  _THROW_NCEE(invalid_operation, "This function cannot be called on a default constructed task");
147  }
148  };
149 
156  {
157  private:
158  // If _M_SingleFrame != nullptr, there will be only one frame of callstacks, which is stored in _M_SingleFrame;
159  // otherwise, _M_Frame will store all the callstack frames.
161  std::vector<void *> _M_frames;
162  public:
164  {
165  _M_SingleFrame = nullptr;
166  }
167 
168  // Store one frame of callstack. This function works for both Debug / Release CRT.
170  {
172  _csc._M_SingleFrame = _SingleFrame;
173  return _csc;
174  }
175 
176  // Capture _CaptureFrames number of callstack frames. This function only work properly for Desktop or Debug CRT.
177  __declspec(noinline)
178  static _TaskCreationCallstack _CaptureMultiFramesCallstack(void *_SingleFrame, size_t _CaptureFrames)
179  {
181  _csc._M_SingleFrame = _SingleFrame;
182  if (_CaptureFrames > 1)
183  {
184  _csc._M_frames.resize(_CaptureFrames);
185  // skip 2 frames to make sure callstack starts from user code
186  _csc._M_frames.resize(::Concurrency::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames));
187  }
188  return _csc;
189  }
190  };
191  typedef unsigned char _Unit_type;
192 
200 
201  template<typename _Ty>
203  {
204  typedef _Ty _Type;
205  };
206 
207  template<>
209  {
210  typedef _Unit_type _Type;
211  };
212 
213  template<typename _Ty>
215  {
216  static const bool _Value = true;
217  };
218 
219  template<>
221  {
222  static const bool _Value = false;
223  };
224 
225  template <typename _Ty>
227  {
228  typedef _Ty _Type;
229  };
230 
231  template <typename _Ty>
232  struct _UnwrapTaskType<task<_Ty>>
233  {
234  typedef _Ty _Type;
235  };
236 
237  template <typename _Ty>
239 
241 
242 #if defined(__cplusplus_winrt)
243  template <typename _Type>
244  struct _Unhat
245  {
246  typedef _Type _Value;
247  };
248 
249  template <typename _Type>
250  struct _Unhat<_Type^>
251  {
252  typedef _Type _Value;
253  };
254 
255  value struct _NonUserType { public: int _Dummy; };
256 
257  template <typename _Type, bool _IsValueTypeOrRefType = __is_valid_winrt_type(_Type)>
258  struct _ValueTypeOrRefType
259  {
260  typedef _NonUserType _Value;
261  };
262 
263  template <typename _Type>
264  struct _ValueTypeOrRefType<_Type, true>
265  {
266  typedef _Type _Value;
267  };
268 
269  template <typename _T1, typename _T2>
270  _T2 _ProgressTypeSelector(Windows::Foundation::IAsyncOperationWithProgress<_T1,_T2>^);
271 
272  template <typename _T1>
273  _T1 _ProgressTypeSelector(Windows::Foundation::IAsyncActionWithProgress<_T1>^);
274 
275  template <typename _Type>
276  struct _GetProgressType
277  {
278  typedef decltype(_ProgressTypeSelector(details::declval<_Type>())) _Value;
279  };
280 
281  template <typename _Type>
282  struct _IsIAsyncInfo
283  {
284  static const bool _Value = __is_base_of(Windows::Foundation::IAsyncInfo, typename _Unhat<_Type>::_Value);
285  };
286 
287  template <typename _Ty>
288  _TypeSelectorAsyncOperation _AsyncOperationKindSelector(Windows::Foundation::IAsyncOperation<_Ty>^);
289 
290  _TypeSelectorAsyncAction _AsyncOperationKindSelector(Windows::Foundation::IAsyncAction^);
291 
292  template <typename _T1, typename _T2>
293  _TypeSelectorAsyncOperationWithProgress _AsyncOperationKindSelector(Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>^);
294 
295  template <typename _Ty>
296  _TypeSelectorAsyncActionWithProgress _AsyncOperationKindSelector(Windows::Foundation::IAsyncActionWithProgress<_Ty>^);
297 
299  struct _TaskTypeTraits
300  {
301  typedef typename _UnwrapTaskType<_Type>::_Type _TaskRetType;
302  typedef decltype(_AsyncOperationKindSelector(details::declval<_Type>())) _AsyncKind;
303  typedef typename _NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
304 
305  static const bool _IsAsyncTask = _IsAsync;
306  static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
307  };
308 
309  template<typename _Type>
310  struct _TaskTypeTraits<_Type, true >
311  {
312  typedef decltype(((_Type)nullptr)->GetResults()) _TaskRetType;
313  typedef _TaskRetType _NormalizedTaskRetType;
314  typedef decltype(_AsyncOperationKindSelector((_Type)nullptr)) _AsyncKind;
315 
316  static const bool _IsAsyncTask = true;
317  static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
318  };
319 
320 #else /* defined (__cplusplus_winrt) */
321  template <typename _Type>
323  {
324  static const bool _Value = false;
325  };
326 
327  template <typename _Type, bool _IsAsync = false>
329  {
331  typedef decltype(_AsyncOperationKindSelector(details::declval<_Type>())) _AsyncKind;
332  typedef typename _NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
333 
334  static const bool _IsAsyncTask = false;
335  static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
336  };
337 #endif /* defined (__cplusplus_winrt) */
338 
339  template <typename _Function> auto _IsCallable(_Function _Func, int) -> decltype(_Func(), std::true_type());
340  template <typename _Function> std::false_type _IsCallable(_Function, ...);
341 
342  template <>
344  {
345  typedef void _TaskRetType;
347  typedef _Unit_type _NormalizedTaskRetType;
348 
349  static const bool _IsAsyncTask = false;
350  static const bool _IsUnwrappedTaskOrAsync = false;
351  };
352 
354 
355  template <typename _Function, typename _Type> auto _ReturnTypeHelper(_Type _Obj, _Function _Func, int, int) -> decltype(_Func(std::declval<task<_Type>>()));
356  template <typename _Function, typename _Type> auto _ReturnTypeHelper(_Type _Obj, _Function _Func, int, ...) -> decltype(_Func(_Obj));
357  template <typename _Function, typename _Type> auto _ReturnTypeHelper(_Type _Obj, _Function _Func, ...) -> _BadContinuationParamType;
358 
359  template <typename _Function, typename _Type> auto _IsTaskHelper(_Type _Obj, _Function _Func, int, int) -> decltype(_Func(std::declval<task<_Type>>()), std::true_type());
360  template <typename _Function, typename _Type> auto _IsTaskHelper(_Type _Obj, _Function _Func, int, ...) -> std::false_type;
361 
362  template <typename _Function> auto _VoidReturnTypeHelper(_Function _Func, int, int) -> decltype(_Func(std::declval<task<void>>()));
363  template <typename _Function> auto _VoidReturnTypeHelper(_Function _Func, int, ...) -> decltype(_Func());
364 
365  template <typename _Function> auto _VoidIsTaskHelper(_Function _Func, int, int) -> decltype(_Func(std::declval<task<void>>()), std::true_type());
366  template <typename _Function> auto _VoidIsTaskHelper(_Function _Func, int, ...) -> std::false_type;
367 
368  template<typename _Function, typename _ExpectedParameterType>
370  {
371  typedef decltype(_ReturnTypeHelper(details::declval<_ExpectedParameterType>(),details::declval<_Function>(), 0, 0)) _FuncRetType;
372  static_assert(!std::is_same<_FuncRetType,_BadContinuationParamType>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)");
373 
374  typedef decltype(_IsTaskHelper(details::declval<_ExpectedParameterType>(),details::declval<_Function>(), 0, 0)) _Takes_task;
375  };
376 
377  template<typename _Function>
378  struct _FunctionTypeTraits<_Function, void>
379  {
380  typedef decltype(_VoidReturnTypeHelper(details::declval<_Function>(), 0, 0)) _FuncRetType;
381  typedef decltype(_VoidIsTaskHelper(details::declval<_Function>(), 0, 0)) _Takes_task;
382  };
383 
384 #ifndef _PPLTASKS_NO_STDFUNC
385  template<typename _Ty, typename _IsTaskType>
387  {
388  static_assert(std::is_same<_IsTaskType, std::false_type>::value, "_IsTaskType template parameter must be std::true_type or std::false_type");
389  typedef _Ty _ArgType;
390  };
391 
392  template<typename _Ty>
394  {
396  };
397 #endif
398 
399  template<typename _Function, typename _ReturnType>
401  {
403 #ifndef _PPLTASKS_NO_STDFUNC
406  typedef std::function<_RetTypeT __cdecl(_ArgTypeT)> _StdFuncT;
407 #endif
408  };
409  // _InitFunctorTypeTraits is used to decide whether a task constructed with a lambda should be unwrapped. Depending on how the variable is
410  // declared, the constructor may or may not perform unwrapping. For eg.
411  //
412  // This declaration SHOULD NOT cause unwrapping
413  // task<task<void>> t1([]() -> task<void> {
414  // task<void> t2([]() {});
415  // return t2;
416  // });
417  //
418  // This declaration SHOULD cause unwrapping
419  // task<void>> t1([]() -> task<void> {
420  // task<void> t2([]() {});
421  // return t2;
422  // });
423  // If the type of the task is the same as the return type of the function, no unwrapping should take place. Else normal rules apply.
424  template <typename _TaskType, typename _FuncRetType>
426  {
428  static const bool _IsAsyncTask = _TaskTypeTraits<_FuncRetType>::_IsAsyncTask;
429  static const bool _IsUnwrappedTaskOrAsync = _TaskTypeTraits<_FuncRetType>::_IsUnwrappedTaskOrAsync;
430  };
431 
432  template<typename _Ty>
433  struct _InitFunctorTypeTraits<_Ty, _Ty>
434  {
436  static const bool _IsAsyncTask = false;
437  static const bool _IsUnwrappedTaskOrAsync = false;
438  };
439 
444  {
445  _TaskProcThunk(const std::function<void ()> & _Callback) :
446  _M_func(_Callback)
447  {
448  }
449 
450  static void __cdecl _Bridge(void *_PData)
451  {
452  _TaskProcThunk *_PThunk = reinterpret_cast<_TaskProcThunk *>(_PData);
453  _Holder _ThunkHolder(_PThunk);
454  _PThunk->_M_func();
455  }
456  private:
457 
458  // RAII holder
459  struct _Holder
460  {
461  _Holder(_TaskProcThunk * _PThunk) : _M_pThunk(_PThunk)
462  {
463  }
464 
466  {
467  delete _M_pThunk;
468  }
469 
471 
472  private:
473  _Holder& operator=(const _Holder&);
474  };
475 
476  std::function<void()> _M_func;
477  _TaskProcThunk& operator=(const _TaskProcThunk&);
478  };
479 
491  static void _ScheduleFuncWithAutoInline(const std::function<void ()> & _Func, _TaskInliningMode_t _InliningMode)
492  {
494  }
495 
497  {
498  typedef std::function<void __cdecl (void)> _CallbackFunction;
499 
500  public:
501 
503  {
505  _Context._Capture();
506  return _Context;
507  }
508 
510  {
511  _Reset();
512  }
513 
514  _ContextCallback(bool _DeferCapture = false)
515  {
516  if (_DeferCapture)
517  {
518  _M_context._M_captureMethod = _S_captureDeferred;
519  }
520  else
521  {
522  _M_context._M_pContextCallback = nullptr;
523  }
524  }
525 
526  // Resolves a context that was created as _S_captureDeferred based on the environment (ancestor, current context).
527  void _Resolve(bool _CaptureCurrent)
528  {
529  if(_M_context._M_captureMethod == _S_captureDeferred)
530  {
531  _M_context._M_pContextCallback = nullptr;
532 
533  if (_CaptureCurrent && _IsCurrentOriginSTA())
534  {
535  _Capture();
536  }
537  }
538  }
539 
540 
541 
543  {
544  _Assign(_Src._M_context._M_pContextCallback);
545  }
546 
548  {
549  _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
550  _Src._M_context._M_pContextCallback = nullptr;
551  }
552 
554  {
555  if (this != &_Src)
556  {
557  _Reset();
558  _Assign(_Src._M_context._M_pContextCallback);
559  }
560  return *this;
561  }
562 
564  {
565  if (this != &_Src)
566  {
567  _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
568  _Src._M_context._M_pContextCallback = nullptr;
569  }
570  return *this;
571  }
572 
573  bool _HasCapturedContext() const
574  {
575  _ASSERTE(_M_context._M_captureMethod != _S_captureDeferred);
576  return (_M_context._M_pContextCallback != nullptr);
577  }
578 
579 
580 
581  bool operator==(const _ContextCallback& _Rhs) const
582  {
583  return (_M_context._M_pContextCallback == _Rhs._M_context._M_pContextCallback);
584  }
585 
586  bool operator != (const _ContextCallback& _Rhs) const
587  {
588  return !(operator==(_Rhs));
589  }
590 
591  _CRTIMP2 void __thiscall _CallInContext(_CallbackFunction _Func, bool _IgnoreDisconnect) const;
592 
593  void _CallInContext(_CallbackFunction _Func) const
594  {
595  _CallInContext(_Func, false);
596  }
597 
598  private:
599  _CRTIMP2 void __thiscall _Reset();
600 
601  _CRTIMP2 void __thiscall _Assign(void *_PContextCallback);
602 
603  // Returns the origin information for the caller (runtime / Windows Runtime apartment as far as task continuations need know)
604  _CRTIMP2 static bool __cdecl _IsCurrentOriginSTA();
605 
606  _CRTIMP2 void __thiscall _Capture();
607 
608  union
609  {
610  void *_M_pContextCallback; // IContextCallback *
612  } _M_context;
613 
614  static const size_t _S_captureDeferred = 1;
615 
616  };
617 
618  template<typename _Type>
620  {
621  _ResultHolder() = default;
622 
623  void Set(const _Type& _type)
624  {
625  _Result = _type;
626  }
627 
628  _Type Get()
629  {
630  return _Result;
631  }
632 
633  _Type _Result;
634  };
635 
636  // Special implementation of vector<bool> in STL will cause
637  // race condition when multiple threads write to the result
638  template<>
639  struct _ResultHolder<std::vector<bool>>
640  {
641  void Set(const std::vector<bool>& _type)
642  {
643  _Result.resize(_type.size());
644  std::transform(_type.begin(), _type.end(), _Result.begin(), [](bool _Val) { return static_cast<char>(_Val); });
645  }
646 
647  std::vector<bool> Get()
648  {
649  std::vector<bool> _Ret(_Result.size());
650  std::transform(_Result.begin(), _Result.end(), _Ret.begin(), [](char _Val) { return _Val != 0; });
651  return _Ret;
652  }
653 
654  std::vector<char> _Result;
655  };
656 
657 #if defined (__cplusplus_winrt)
658 
659  template<typename _Type>
660  struct _ResultHolder<_Type^>
661  {
662  void Set(_Type^ const & _type)
663  {
664  _M_Result = _type;
665  }
666 
667  _Type^ Get()
668  {
669  return _M_Result.Get();
670  }
671  private:
672  // ::Platform::Agile handle specialization of all hats
673  // including ::Platform::String and ::Platform::Array
674  ::Platform::Agile<_Type^> _M_Result;
675  };
676 
677  //
678  // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs.
679  //
680  template<typename _Type>
681  struct _ResultHolder<std::vector<_Type^>>
682  {
683  void Set(const std::vector<_Type^>& _type)
684  {
685  _Result.reserve(_type.size());
686 
687  for (auto _PTask = _type.begin(); _PTask != _type.end(); ++_PTask)
688  {
689  _Result.emplace_back(*_PTask);
690  }
691  }
692 
693  std::vector<_Type^> Get()
694  {
695  // Return vector<T^> with the objects that are marshaled in the proper apartment
696  std::vector<_Type^> _Return;
697  _Return.reserve(_Result.size());
698 
699  for (auto _PTask = _Result.begin(); _PTask != _Result.end(); ++_PTask)
700  {
701  _Return.push_back(_PTask->Get()); // Platform::Agile will marshal the object to appropriate apartment if necessary
702  }
703 
704  return _Return;
705  }
706 
707  std::vector< ::Platform::Agile<_Type^> > _Result;
708  };
709 
710  template<typename _Type>
711  struct _ResultHolder<std::pair<_Type^, void*> >
712  {
713  void Set(const std::pair<_Type^, size_t>& _type)
714  {
715  _M_Result = _type;
716  }
717 
718  std::pair<_Type^, size_t> Get()
719  {
720  return std::make_pair(_M_Result.first.Get(), _M_Result.second);
721  }
722  private:
723  std::pair< ::Platform::Agile<_Type^>, size_t> _M_Result;
724  };
725 
726 #endif /* defined (__cplusplus_winrt) */
727 
728  // An exception thrown by the task body is captured in an exception holder and it is shared with all value based continuations rooted at the task.
729  // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception
730  // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast.
732  {
733  private:
734  _CRTIMP2 void __thiscall ReportUnhandledError();
735 
736  public:
737  explicit _ExceptionHolder(const std::exception_ptr& _E, const _TaskCreationCallstack &_stackTrace) :
738  _M_exceptionObserved(0), _M_stdException(_E), _M_stackTrace(_stackTrace)
739  {
740  }
741 
742  __declspec(noinline)
744  {
745  if (_M_exceptionObserved == 0)
746  {
747  // If you are trapped here, it means an exception thrown in task chain didn't get handled.
748  // Please add task-based continuation to handle all exceptions coming from tasks.
749  // this->_M_stackTrace keeps the creation callstack of the task generates this exception.
751  }
752  }
753 
755  {
756  if (_M_exceptionObserved == 0)
757  {
758  atomic_exchange(_M_exceptionObserved, 1l);
759  }
760 
761  std::rethrow_exception(_M_stdException);
762  }
763 
764  // A variable that remembers if this exception was ever rethrown into user code (and hence handled by the user). Exceptions that
765  // are unobserved when the exception holder is destructed will terminate the process.
767 
768  // Either _M_stdException or _M_winRTException is populated based on the type of exception encountered.
769  std::exception_ptr _M_stdException;
770 
771  // Disassembling this value will point to a source instruction right after a call instruction. If the call is to create_task,
772  // a task constructor or the then method, the task created by that method is the one that encountered this exception. If the call
773  // is to task_completion_event::set_exception, the set_exception method was the source of the exception.
774  // DO NOT REMOVE THIS VARIABLE. It is extremely helpful for debugging.
776 
777  };
778 
779 #if defined (__cplusplus_winrt)
780  template<typename _AsyncOperationType, typename _CompletionHandlerType, typename _Result>
784  ref struct _AsyncInfoImpl abstract : Windows::Foundation::IAsyncOperation<_Result>
785  {
786  internal:
787  // The async action, action with progress or operation with progress that this stub forwards to.
789 
790  Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ _M_CompletedHandler;
791 
792  _AsyncInfoImpl( _AsyncOperationType _AsyncInfo ) : _M_asyncInfo(_AsyncInfo) {}
793 
794  public:
795  virtual void Cancel() { _M_asyncInfo.Get()->Cancel(); }
796  virtual void Close() { _M_asyncInfo.Get()->Close(); }
797 
798  virtual property Windows::Foundation::HResult ErrorCode
799  {
800  Windows::Foundation::HResult get()
801  {
802  return _M_asyncInfo.Get()->ErrorCode;
803  }
804  }
805 
806  virtual property UINT Id
807  {
808  UINT get()
809  {
810  return _M_asyncInfo.Get()->Id;
811  }
812  }
813 
814  virtual property Windows::Foundation::AsyncStatus Status
815  {
816  Windows::Foundation::AsyncStatus get()
817  {
818  return _M_asyncInfo.Get()->Status;
819  }
820  }
821 
822  virtual _Result GetResults() { throw std::runtime_error("derived class must implement"); }
823 
824  virtual property Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ Completed
825  {
826  Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ get()
827  {
828  return _M_CompletedHandler;
829  }
830 
831  void set(Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ _Value)
832  {
833  _M_CompletedHandler = _Value;
834  _M_asyncInfo.Get()->Completed = ref new _CompletionHandlerType([&](_AsyncOperationType, Windows::Foundation::AsyncStatus _Status) {
835  _M_CompletedHandler->Invoke(this, _Status);
836  });
837  }
838  }
839  };
840 
844  template<typename _Result, typename _Progress>
845  ref struct _IAsyncOperationWithProgressToAsyncOperationConverter sealed :
846  _AsyncInfoImpl<Windows::Foundation::IAsyncOperationWithProgress<_Result,_Progress>^,
847  Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_Result,_Progress>,
848  _Result>
849  {
850  internal:
851  _IAsyncOperationWithProgressToAsyncOperationConverter(Windows::Foundation::IAsyncOperationWithProgress<_Result,_Progress>^ _Operation) :
852  _AsyncInfoImpl<Windows::Foundation::IAsyncOperationWithProgress<_Result,_Progress>^,
853  Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_Result,_Progress>,
854  _Result>(_Operation) {}
855 
856  public:
857  virtual _Result GetResults() override { return _M_asyncInfo.Get()->GetResults(); }
858  };
859 
863  ref struct _IAsyncActionToAsyncOperationConverter sealed :
864  _AsyncInfoImpl<Windows::Foundation::IAsyncAction^,
865  Windows::Foundation::AsyncActionCompletedHandler,
866  details::_Unit_type>
867  {
868  internal:
869  _IAsyncActionToAsyncOperationConverter(Windows::Foundation::IAsyncAction^ _Operation) :
870  _AsyncInfoImpl<Windows::Foundation::IAsyncAction^,
871  Windows::Foundation::AsyncActionCompletedHandler,
872  details::_Unit_type>(_Operation) {}
873 
874  public:
875  virtual details::_Unit_type GetResults() override
876  {
877  // Invoke GetResults on the IAsyncAction to allow exceptions to be thrown to higher layers before returning a dummy value.
878  _M_asyncInfo.Get()->GetResults();
879  return details::_Unit_type();
880  }
881  };
882 
886  template<typename _Progress>
887  ref struct _IAsyncActionWithProgressToAsyncOperationConverter sealed :
888  _AsyncInfoImpl<Windows::Foundation::IAsyncActionWithProgress<_Progress>^,
889  Windows::Foundation::AsyncActionWithProgressCompletedHandler<_Progress>,
890  details::_Unit_type>
891  {
892  internal:
893  _IAsyncActionWithProgressToAsyncOperationConverter(Windows::Foundation::IAsyncActionWithProgress<_Progress>^ _Action) :
894  _AsyncInfoImpl<Windows::Foundation::IAsyncActionWithProgress<_Progress>^,
895  Windows::Foundation::AsyncActionWithProgressCompletedHandler<_Progress>,
896  details::_Unit_type>(_Action) {}
897  public:
898  virtual details::_Unit_type GetResults() override
899  {
900  // Invoke GetResults on the IAsyncActionWithProgress to allow exceptions to be thrown before returning a dummy value.
901  _M_asyncInfo.Get()->GetResults();
902  return details::_Unit_type();
903  }
904  };
905 #endif /* defined (__cplusplus_winrt) */
906 } // namespace details
907 
914 
916 {
917 public:
918 
935 
937  {
938  return task_continuation_context();
939  }
940 
954 
956  {
957  task_continuation_context _Current;
958  _Current._Resolve(true);
959  return _Current;
960  }
961 
962 #if defined (__cplusplus_winrt)
963 
977  static task_continuation_context use_arbitrary()
978  {
979  task_continuation_context _Arbitrary;
980  _Arbitrary._Resolve(false);
981  return _Arbitrary;
982  }
983 
997 
998  static task_continuation_context use_current()
999  {
1000  return get_current_winrt_context();
1001  }
1002 #endif /* defined (__cplusplus_winrt) */
1003 
1015 
1017  {
1018  task_continuation_context _Current;
1019  _Current._Resolve(false);
1020  _Current._M_RunInline = true;
1021  return _Current;
1022  }
1023 
1024  bool _ForceInline() const
1025  {
1026  return _M_RunInline;
1027  }
1028 private:
1029 
1030  _CRTIMP2 __thiscall task_continuation_context();
1031  bool _M_RunInline; // default, it's false
1032 };
1033 
1034 class task_options;
1035 namespace details
1036 {
1038  {
1041 
1043  {
1044  _M_hasPresetCreationCallstack = true;
1045  _M_presetCreationCallstack = _callstack;
1046  }
1048  {
1049  _M_hasPresetCreationCallstack = false;
1050  }
1051  };
1052 
1053  inline _Internal_task_options &_get_internal_task_options(task_options &_Options);
1054  inline const _Internal_task_options &_get_internal_task_options(const task_options &_Options);
1055 }
1060 {
1061 public:
1062 
1063 
1068  : _M_Scheduler(get_ambient_scheduler()),
1069  _M_CancellationToken(cancellation_token::none()),
1070  _M_ContinuationContext(task_continuation_context::use_default()),
1071  _M_HasCancellationToken(false),
1072  _M_HasScheduler(false)
1073  {
1074  }
1075 
1080  : _M_Scheduler(get_ambient_scheduler()),
1081  _M_CancellationToken(_Token),
1082  _M_ContinuationContext(task_continuation_context::use_default()),
1083  _M_HasCancellationToken(true),
1084  _M_HasScheduler(false)
1085  {
1086  }
1087 
1092  : _M_Scheduler(get_ambient_scheduler()),
1093  _M_CancellationToken(cancellation_token::none()),
1094  _M_ContinuationContext(_ContinuationContext),
1095  _M_HasCancellationToken(false),
1096  _M_HasScheduler(false)
1097  {
1098  }
1099 
1104  : _M_Scheduler(get_ambient_scheduler()),
1105  _M_CancellationToken(_Token),
1106  _M_ContinuationContext(_ContinuationContext),
1107  _M_HasCancellationToken(true),
1108  _M_HasScheduler(false)
1109  {
1110  }
1111 
1115  template<typename _SchedType>
1116  task_options(std::shared_ptr<_SchedType> _Scheduler)
1117  : _M_Scheduler(std::move(_Scheduler)),
1118  _M_CancellationToken(cancellation_token::none()),
1119  _M_ContinuationContext(task_continuation_context::use_default()),
1120  _M_HasCancellationToken(false),
1121  _M_HasScheduler(true)
1122  {
1123  }
1124 
1128  task_options(scheduler_interface& _Scheduler)
1129  : _M_Scheduler(&_Scheduler),
1130  _M_CancellationToken(cancellation_token::none()),
1131  _M_ContinuationContext(task_continuation_context::use_default()),
1132  _M_HasCancellationToken(false),
1133  _M_HasScheduler(true)
1134  {
1135  }
1136 
1141  : _M_Scheduler(std::move(_Scheduler)),
1142  _M_CancellationToken(cancellation_token::none()),
1143  _M_ContinuationContext(task_continuation_context::use_default()),
1144  _M_HasCancellationToken(false),
1145  _M_HasScheduler(true)
1146  {
1147  }
1148 
1152  task_options(const task_options& _TaskOptions)
1153  : _M_Scheduler(_TaskOptions.get_scheduler()),
1154  _M_CancellationToken(_TaskOptions.get_cancellation_token()),
1155  _M_ContinuationContext(_TaskOptions.get_continuation_context()),
1156  _M_HasCancellationToken(_TaskOptions.has_cancellation_token()),
1157  _M_HasScheduler(_TaskOptions.has_scheduler())
1158  {
1159  }
1160 
1165  {
1166  _M_CancellationToken = _Token;
1167  _M_HasCancellationToken = true;
1168  }
1169 
1174  {
1175  _M_ContinuationContext = _ContinuationContext;
1176  }
1177 
1182  {
1183  return _M_HasCancellationToken;
1184  }
1185 
1190  {
1191  return _M_CancellationToken;
1192  }
1193 
1198  {
1199  return _M_ContinuationContext;
1200  }
1201 
1205  bool has_scheduler() const
1206  {
1207  return _M_HasScheduler;
1208  }
1209 
1214  {
1215  return _M_Scheduler;
1216  }
1217 
1218 private:
1219 
1220  task_options const& operator=(task_options const& _Right);
1223 
1230 };
1231 
1232 namespace details
1233 {
1234 
1238  {
1239  _ThenImplOptions(_CancellationTokenState *_Token_state, const task_continuation_context* _Continuation_context,
1240  scheduler_ptr _PScheduler, _TaskCreationCallstack _Creation_stack, _TaskInliningMode_t _Inlining_mode = _NoInline) :
1241  _PTokenState(_Token_state), _PContinuationContext(const_cast<task_continuation_context*>(_Continuation_context)), _Scheduler(_PScheduler),
1242  _CreationStack(_Creation_stack), _InliningMode(_Inlining_mode) {}
1243 
1249 
1250  static _ThenImplOptions _CreateOptions(const task_options& _Task_Options, const task_continuation_context& _ContinuationContext,
1251  const scheduler_ptr& impl_scheduler)
1252  {
1253  _CancellationTokenState *_TokenState = _Task_Options.has_cancellation_token() ?
1254  _Task_Options.get_cancellation_token()._GetImplValue() : nullptr;
1255  auto _Scheduler = _Task_Options.has_scheduler() ? _Task_Options.get_scheduler() : impl_scheduler;
1256  auto _InliningMode = _Task_Options.get_continuation_context()._ForceInline() ? details::_ForceInline : details::_NoInline;
1257 
1258  auto _Task_Options_Int = details::_get_internal_task_options(_Task_Options);
1259  auto _CreationStack = _Task_Options_Int._M_hasPresetCreationCallstack ?
1260  _Task_Options_Int._M_presetCreationCallstack : details::_TaskCreationCallstack();
1261 
1262  return _ThenImplOptions(_TokenState, &_ContinuationContext, _Scheduler, _CreationStack,_InliningMode);
1263  }
1264  };
1265 
1267  {
1268  return _Options._M_InternalTaskOptions;
1269  }
1271  {
1272  return _Options._M_InternalTaskOptions;
1273  }
1274 
1275  struct _Task_impl_base;
1276  template<typename _ReturnType> struct _Task_impl;
1277 
1278  template<typename _ReturnType>
1279  struct _Task_ptr
1280  {
1281  typedef std::shared_ptr<_Task_impl<_ReturnType>> _Type;
1282  static _Type _Make(_CancellationTokenState * _Ct, scheduler_ptr _Scheduler_arg) { return std::make_shared<_Task_impl<_ReturnType>>(_Ct, _Scheduler_arg); }
1283  };
1284 
1286  typedef std::shared_ptr<_Task_impl_base> _Task_ptr_base;
1287 
1288  // The weak-typed base task handler for continuation tasks.
1289  struct _ContinuationTaskHandleBase : _UnrealizedChore_t
1290  {
1294 
1295  // This field gives inlining scheduling policy for current chore.
1297 
1298  virtual _Task_ptr_base _GetTaskImplBase() const = 0;
1299 
1301  _M_next(nullptr), _M_continuationContext(task_continuation_context::use_default()), _M_isTaskBasedContinuation(false), _M_inliningMode(details::_NoInline)
1302  {
1303  }
1304 
1306  };
1307 
1308 #if _PPLTASK_ASYNC_LOGGING
1309 
1310  // Stateful logger rests inside task_impl_base.
1312  {
1316 
1317  // Log before scheduling task
1318  _CRTIMP2 void __thiscall _LogScheduleTask(bool _isContinuation);
1319 
1320  // It will log the cancel event but not canceled state. _LogTaskCompleted will log the terminal state, which includes cancel state.
1321  _CRTIMP2 void __thiscall _LogCancelTask();
1322 
1323  // Log when task reaches terminal state. Note: the task can reach a terminal state (by cancellation or exception) without having run
1324  _CRTIMP2 void __thiscall _LogTaskCompleted();
1325 
1326  // Log when task body (which includes user lambda and other scheduling code) begin to run
1328 
1329  // Log when task body finish executing
1330  _CRTIMP2 void __thiscall _LogTaskExecutionCompleted();
1331 
1332  // Log right before user lambda being invoked
1333  _CRTIMP2 void __thiscall _LogWorkItemStarted();
1334 
1335  // Log right after user lambda being invoked
1336  _CRTIMP2 void __thiscall _LogWorkItemCompleted();
1337 
1338  _TaskEventLogger(_Task_impl_base *_task): _M_task(_task)
1339  {
1340  _M_scheduled = false;
1341  _M_taskPostEventStarted = false;
1342  }
1343  };
1344 
1345  // Exception safe logger for user lambda
1347  {
1349  _TaskWorkItemRAIILogger(_TaskEventLogger &_taskHandleLogger): _M_logger(_taskHandleLogger)
1350  {
1351  _M_logger._LogWorkItemStarted();
1352  }
1353 
1355  {
1356  _M_logger._LogWorkItemCompleted();
1357  }
1358  _TaskWorkItemRAIILogger &operator =(const _TaskWorkItemRAIILogger &); // cannot be assigned
1359  };
1360 
1361 #else
1362  inline void _LogCancelTask(_Task_impl_base *) {}
1363  struct _TaskEventLogger
1364  {
1365  void _LogScheduleTask(bool) {}
1366  void _LogCancelTask() {}
1367  void _LogWorkItemStarted() {}
1368  void _LogWorkItemCompleted() {}
1369  void _LogTaskExecutionStarted() {}
1370  void _LogTaskExecutionCompleted() {}
1371  void _LogTaskCompleted() {}
1372  _TaskEventLogger(_Task_impl_base *) {}
1373  };
1374  struct _TaskWorkItemRAIILogger
1375  {
1376  _TaskWorkItemRAIILogger(_TaskEventLogger &) {}
1377  };
1378 #endif
1379 
1395  template<typename _ReturnType, typename _DerivedTaskHandle, typename _BaseTaskHandle>
1396  struct _PPLTaskHandle : _BaseTaskHandle
1397  {
1398  _PPLTaskHandle(const typename _Task_ptr<_ReturnType>::_Type & _PTask) : _M_pTask(_PTask)
1399  {
1400  }
1401 
1403  {
1404  // Here is the sink of all task completion code paths
1405  _M_pTask->_M_taskEventLogger._LogTaskCompleted();
1406  }
1407 
1408  virtual void invoke() const
1409  {
1410  // All exceptions should be rethrown to finish cleanup of the task collection. They will be caught and handled
1411  // by the runtime.
1412  _ASSERTE((bool)_M_pTask);
1413  if (!_M_pTask->_TransitionedToStarted())
1414  {
1415  static_cast<const _DerivedTaskHandle *>(this)->_SyncCancelAndPropagateException();
1416  return;
1417  }
1418 
1419  _M_pTask->_M_taskEventLogger._LogTaskExecutionStarted();
1420 
1421  _TRY_BEGIN
1422  // All derived task handle must implement this contract function.
1423  static_cast<const _DerivedTaskHandle *>(this)->_Perform();
1424  _CATCH(const task_canceled &)
1425  _M_pTask->_Cancel(true);
1427  _M_pTask->_Cancel(true);
1428  _CATCH_ALL
1429  _M_pTask->_CancelWithException(std::current_exception());
1430  _CATCH_END
1431  _M_pTask->_M_taskEventLogger._LogTaskExecutionCompleted();
1432  }
1433 
1434  // Cast _M_pTask pointer to "type-less" _Task_impl_base pointer, which can be used in _ContinuationTaskHandleBase.
1435  // The return value should be automatically optimized by R-value ref.
1436  _Task_ptr_base _GetTaskImplBase() const
1437  {
1438  return _M_pTask;
1439  }
1440 
1442  private:
1443  _PPLTaskHandle const & operator=(_PPLTaskHandle const&); // no assignment operator
1444  };
1445 
1450 
1452  {
1454  {
1455  // Tracks the state of the task, rather than the task collection on which the task is scheduled
1461  };
1462 
1464  : _M_TaskState(_Created),
1465  _M_fFromAsync(false), _M_fUnwrappedTask(false),
1466  _M_pRegistration(nullptr), _M_Continuations(nullptr), _M_TaskCollection(_Scheduler_arg),
1467  _M_taskEventLogger(this)
1468  {
1469  // Set cancellation token
1470  _M_pTokenState = _PTokenState;
1471  _ASSERTE(_M_pTokenState != nullptr);
1472  if (_M_pTokenState != _CancellationTokenState::_None())
1473  _M_pTokenState->_Reference();
1474  }
1475 
1477  {
1478  _ASSERTE(_M_pTokenState != nullptr);
1479  if (_M_pTokenState != _CancellationTokenState::_None())
1480  {
1481  _M_pTokenState->_Release();
1482  }
1483  }
1484 
1485  task_status _Wait()
1486  {
1487  bool _DoWait = true;
1488 
1489  if (_IsNonBlockingThread())
1490  {
1491  // In order to prevent Windows Runtime STA threads from blocking the UI, calling task.wait() task.get() is illegal
1492  // if task has not been completed.
1493  if (!_IsCompleted() && !_IsCanceled())
1494  {
1495  _THROW_NCEE(invalid_operation, "Illegal to wait on a task in a Windows Runtime STA");
1496  }
1497  else
1498  {
1499  // Task Continuations are 'scheduled' *inside* the chore that is executing on the ancestor's task group. If a continuation
1500  // needs to be marshalled to a different apartment instead of scheduling, we make a synchronous cross-apartment COM
1501  // call to execute the continuation. If it then happens to do something which waits on the ancestor (say it calls .get(),
1502  // which task based continuations are wont to do), waiting on the task group results in waiting on the chore that is making
1503  // this synchronous callback, which causes a deadlock. To avoid this, we test the state of the ancestor's event,
1504  // and we will NOT wait on it if it has finished execution (which means now we are in the inline synchronous callback).
1505  _DoWait = false;
1506  }
1507  }
1508 
1509  if (_DoWait)
1510  {
1511  // If this task was created from a Windows Runtime async operation, do not attempt to inline it. The
1512  // async operation will take place on a thread in the appropriate apartment Simply wait for the completed
1513  // event to be set.
1514  if (_M_fFromAsync)
1515  {
1516  _M_TaskCollection._Wait();
1517  }
1518  else
1519  {
1520  // Wait on the task collection to complete. The task collection is guaranteed to still be
1521  // valid since the task must be still within scope so that the _Task_impl_base destructor
1522  // has not yet been called. This call to _Wait potentially inlines execution of work.
1523  _TRY_BEGIN
1524  // Invoking wait on a task collection resets the state of the task collection. This means that
1525  // if the task collection itself were canceled, or had encountered an exception, only the first
1526  // call to wait will receive this status. However, both cancellation and exceptions flowing through
1527  // tasks set state in the task impl itself.
1528 
1529  // When it returns cancelled, either work chore or the cancel thread should already have set task's state
1530  // properly -- cancelled state or completed state (because there was no interruption point).
1531  // For tasks with unwrapped tasks, we should not change the state of current task, since the unwrapped task are still running.
1532  _M_TaskCollection._RunAndWait();
1534  // The _TaskCollection will never be an interruption point since it has a none token.
1535  _ASSERTE(false);
1537  // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
1538  // must be called from code that is executed within the task (throwing it from parallel work created by and waited
1539  // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
1540  // the exception and canceled the task. Swallow the exception here.
1541  _ASSERTE(_IsCanceled());
1542  _CATCH_ALL
1543  // It's possible the task body hasn't seen the exception; if so we need to cancel with exception here.
1544  if(!_HasUserException())
1545  {
1546  _CancelWithException(std::current_exception());
1547  }
1548  // Rethrow will mark the exception as observed.
1549  _M_exceptionHolder->_RethrowUserException();
1550  _CATCH_END
1551 
1552  // If the lambda body for this task (executed or waited upon in _RunAndWait above) happened to return a task
1553  // which is to be unwrapped and plumbed to the output of this task, we must not only wait on the lambda body, we must
1554  // wait on the **INNER** body. It is in theory possible that we could inline such if we plumb a series of things through;
1555  // however, this takes the tact of simply waiting upon the completion signal.
1556  if (_M_fUnwrappedTask)
1557  {
1558  _M_TaskCollection._Wait();
1559  }
1560  }
1561  }
1562 
1563  if (_HasUserException())
1564  {
1565  _M_exceptionHolder->_RethrowUserException();
1566  }
1567  else if (_IsCanceled())
1568  {
1569  return canceled;
1570  }
1571  _ASSERTE(_IsCompleted());
1572  return completed;
1573  }
1574 
1594  virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr<_ExceptionHolder>& _ExHolder) = 0;
1595 
1596  bool _Cancel(bool _SynchronousCancel)
1597  {
1598  // Send in a dummy value for exception. It is not used when the first parameter is false.
1599  return _CancelAndRunContinuations(_SynchronousCancel, false, false, _M_exceptionHolder);
1600  }
1601 
1602  bool _CancelWithExceptionHolder(const std::shared_ptr<_ExceptionHolder>& _ExHolder, bool _PropagatedFromAncestor)
1603  {
1604  // This task was canceled because an ancestor task encountered an exception.
1605  return _CancelAndRunContinuations(true, true, _PropagatedFromAncestor, _ExHolder);
1606  }
1607 
1608  bool _CancelWithException(const std::exception_ptr& _Exception)
1609  {
1610  // This task was canceled because the task body encountered an exception.
1611  _ASSERTE(!_HasUserException());
1612  return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
1613  }
1614 
1615  void _RegisterCancellation(std::weak_ptr<_Task_impl_base> _WeakPtr)
1616  {
1617  _ASSERTE(details::_CancellationTokenState::_IsValid(_M_pTokenState));
1618 
1619  auto _CancellationCallback = [_WeakPtr](){
1620  // Taking ownership of the task prevents dead lock during destruction
1621  // if the destructor waits for the cancellations to be finished
1622  auto _task = _WeakPtr.lock();
1623  if (_task != nullptr)
1624  _task->_Cancel(false);
1625  };
1626 
1627  _M_pRegistration = new details::_CancellationTokenCallback<decltype(_CancellationCallback)>(_CancellationCallback);
1628  _M_pTokenState->_RegisterCallback(_M_pRegistration);
1629  }
1630 
1632  {
1633  if (_M_pRegistration != nullptr)
1634  {
1635  _M_pTokenState->_DeregisterCallback(_M_pRegistration);
1636  _M_pRegistration->_Release();
1637  _M_pRegistration = nullptr;
1638  }
1639  }
1640 
1641  bool _IsCreated()
1642  {
1643  return (_M_TaskState == _Created);
1644  }
1645 
1646  bool _IsStarted()
1647  {
1648  return (_M_TaskState == _Started);
1649  }
1650 
1652  {
1653  return (_M_TaskState == _PendingCancel);
1654  }
1655 
1657  {
1658  return (_M_TaskState == _Completed);
1659  }
1660 
1662  {
1663  return (_M_TaskState == _Canceled);
1664  }
1665 
1667  {
1668  return static_cast<bool>(_M_exceptionHolder);
1669  }
1670 
1671  const std::shared_ptr<_ExceptionHolder>& _GetExceptionHolder()
1672  {
1673  _ASSERTE(_HasUserException());
1674  return _M_exceptionHolder;
1675  }
1676 
1678  {
1679  return _M_fFromAsync;
1680  }
1681 
1682  void _SetAsync(bool _Async = true)
1683  {
1684  _M_fFromAsync = _Async;
1685  }
1686 
1688  {
1689  return _M_pTaskCreationCallstack;
1690  }
1691 
1693  {
1694  _M_pTaskCreationCallstack = _Callstack;
1695  }
1696 
1706  void _ScheduleTask(_UnrealizedChore_t * _PTaskHandle, _TaskInliningMode_t _InliningMode)
1707  {
1708  _TRY_BEGIN
1709  _M_TaskCollection._ScheduleTask(_PTaskHandle, _InliningMode);
1710  _CATCH(const task_canceled &)
1711  // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
1712  // must be called from code that is executed within the task (throwing it from parallel work created by and waited
1713  // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
1714  // the exception and canceled the task. Swallow the exception here.
1715  _ASSERTE(_IsCanceled());
1717  // The _TaskCollection will never be an interruption point since it has a none token.
1718  _ASSERTE(false);
1719  _CATCH_ALL
1720  // The exception could have come from two places:
1721  // 1. From the chore body, so it already should have been caught and canceled.
1722  // In this case swallow the exception.
1723  // 2. From trying to actually schedule the task on the scheduler.
1724  // In this case cancel the task with the current exception, otherwise the
1725  // task will never be signaled leading to deadlock when waiting on the task.
1726 
1727  if (!_HasUserException())
1728  {
1729  _CancelWithException(std::current_exception());
1730  }
1731  _CATCH_END
1732  }
1733 
1741 
1743  {
1744  _Task_ptr_base _ImplBase = _PTaskHandle->_GetTaskImplBase();
1745  if (_IsCanceled() && !_PTaskHandle->_M_isTaskBasedContinuation)
1746  {
1747  if (_HasUserException())
1748  {
1749  // If the ancestor encountered an exception, transfer the exception to the continuation
1750  // This traverses down the tree to propagate the exception.
1751  _ImplBase->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
1752  }
1753  else
1754  {
1755  // If the ancestor was canceled, then your own execution should be canceled.
1756  // This traverses down the tree to cancel it.
1757  _ImplBase->_Cancel(true);
1758  }
1759  }
1760  else
1761  {
1762  // This can only run when the ancestor has completed or it's a task based continuation that fires when a task is canceled
1763  // (with or without a user exception).
1764  _ASSERTE(_IsCompleted() || _PTaskHandle->_M_isTaskBasedContinuation);
1765  _ASSERTE(!_ImplBase->_IsCanceled());
1766  return _ImplBase->_ScheduleContinuationTask(_PTaskHandle);
1767  }
1768 
1769  // If the handle is not scheduled, we need to manually delete it.
1770  delete _PTaskHandle;
1771  }
1772 
1773  // Schedule a continuation to run
1775  {
1776 
1777  _M_taskEventLogger._LogScheduleTask(true);
1778  // Ensure that the continuation runs in proper context (this might be on a Concurrency Runtime thread or in a different Windows Runtime apartment)
1779  if (_PTaskHandle->_M_continuationContext._HasCapturedContext())
1780  {
1781  // For those continuations need to be scheduled inside captured context, we will try to apply automatic inlining to their inline modes,
1782  // if they haven't been specified as _ForceInline yet. This change will encourage those continuations to be executed inline so that reduce
1783  // the cost of marshaling.
1784  // For normal continuations we won't do any change here, and their inline policies are completely decided by ._ThenImpl method.
1785  if (_PTaskHandle->_M_inliningMode != details::_ForceInline)
1786  {
1788  }
1789  _ScheduleFuncWithAutoInline([_PTaskHandle]() {
1790  // Note that we cannot directly capture "this" pointer, instead, we should use _TaskImplPtr, a shared_ptr to the _Task_impl_base.
1791  // Because "this" pointer will be invalid as soon as _PTaskHandle get deleted. _PTaskHandle will be deleted after being scheduled.
1792  auto _TaskImplPtr = _PTaskHandle->_GetTaskImplBase();
1794  {
1795  _TaskImplPtr->_ScheduleTask(_PTaskHandle, details::_ForceInline);
1796  }
1797  else
1798  {
1799  //
1800  // It's entirely possible that the attempt to marshal the call into a differing context will fail. In this case, we need to handle
1801  // the exception and mark the continuation as canceled with the appropriate exception. There is one slight hitch to this:
1802  //
1803  // NOTE: COM's legacy behavior is to swallow SEH exceptions and marshal them back as HRESULTS. This will in effect turn an SEH into
1804  // a C++ exception that gets tagged on the task. One unfortunate result of this is that various pieces of the task infrastructure will
1805  // not be in a valid state after this in /EHsc (due to the lack of destructors running, etc...).
1806  //
1807  _TRY_BEGIN
1808  _PTaskHandle->_M_continuationContext._CallInContext( [_PTaskHandle, _TaskImplPtr](){
1809  _TaskImplPtr->_ScheduleTask(_PTaskHandle, details::_ForceInline);
1810  });
1811  _CATCH_ALL
1812  _TaskImplPtr->_CancelWithException(std::current_exception());
1813  _CATCH_END
1814  }
1815  }, _PTaskHandle->_M_inliningMode);
1816  }
1817  else
1818  {
1819  _ScheduleTask(_PTaskHandle, _PTaskHandle->_M_inliningMode);
1820  }
1821  }
1822 
1833 
1835  {
1836  enum { _Nothing, _Schedule, _Cancel, _CancelWithException } _Do = _Nothing;
1837 
1838  // If the task has canceled, cancel the continuation. If the task has completed, execute the continuation right away.
1839  // Otherwise, add it to the list of pending continuations
1840  {
1841  ::std::lock_guard<std::mutex> _LockHolder(_M_ContinuationsCritSec);
1842  if (_IsCompleted() || (_IsCanceled() && _PTaskHandle->_M_isTaskBasedContinuation))
1843  {
1844  _Do = _Schedule;
1845  }
1846  else if (_IsCanceled())
1847  {
1848  if (_HasUserException())
1849  {
1850  _Do = _CancelWithException;
1851  }
1852  else
1853  {
1854  _Do = _Cancel;
1855  }
1856  }
1857  else
1858  {
1859  // chain itself on the continuation chain.
1860  _PTaskHandle->_M_next = _M_Continuations;
1861  _M_Continuations = _PTaskHandle;
1862  }
1863  }
1864 
1865  // Cancellation and execution of continuations should be performed after releasing the lock. Continuations off of
1866  // async tasks may execute inline.
1867  switch (_Do)
1868  {
1869  case _Schedule:
1870  {
1871  _PTaskHandle->_GetTaskImplBase()->_ScheduleContinuationTask(_PTaskHandle);
1872  break;
1873  }
1874  case _Cancel:
1875  {
1876  // If the ancestor was canceled, then your own execution should be canceled.
1877  // This traverses down the tree to cancel it.
1878  _PTaskHandle->_GetTaskImplBase()->_Cancel(true);
1879 
1880  delete _PTaskHandle;
1881  break;
1882  }
1883  case _CancelWithException:
1884  {
1885  // If the ancestor encountered an exception, transfer the exception to the continuation
1886  // This traverses down the tree to propagate the exception.
1887  _PTaskHandle->_GetTaskImplBase()->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
1888 
1889  delete _PTaskHandle;
1890  break;
1891  }
1892  case _Nothing:
1893  default:
1894  // In this case, we have inserted continuation to continuation chain,
1895  // nothing more need to be done, just leave.
1896  break;
1897  }
1898  }
1899 
1901  {
1902  // The link list can no longer be modified at this point,
1903  // since all following up continuations will be scheduled by themselves.
1904  _ContinuationList _Cur = _M_Continuations, _Next;
1905  _M_Continuations = nullptr;
1906  while (_Cur)
1907  {
1908  // Current node might be deleted after running,
1909  // so we must fetch the next first.
1910  _Next = _Cur->_M_next;
1911  _RunContinuation(_Cur);
1912  _Cur = _Next;
1913  }
1914  }
1915 
1916  _CRTIMP2 static bool __cdecl _IsNonBlockingThread();
1917 
1918 #if defined (__cplusplus_winrt)
1919  template<typename _ReturnType, typename>
1920  static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type & _OuterTask,
1921  Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
1922  {
1923  // This method is invoked either when a task is created from an existing async operation or
1924  // when a lambda that creates an async operation executes.
1925 
1926  // If the outer task is pending cancel, cancel the async operation before setting the completed handler. The COM reference on
1927  // the IAsyncInfo object will be released when all ^references to the operation go out of scope.
1928 
1929  // This assertion uses the existence of taskcollection to determine if the task was created from an event.
1930  // That is no longer valid as even tasks created from a user lambda could have no underlying taskcollection
1931  // when a custom scheduler is used.
1932  // _ASSERTE((!_OuterTask->_M_TaskCollection._IsCreated() || _OuterTask->_M_fUnwrappedTask) && !_OuterTask->_IsCanceled());
1933 
1934  // Pass the shared_ptr by value into the lambda instead of using 'this'.
1935  _AsyncOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<_ReturnType>(
1936  [_OuterTask](Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _Operation, Windows::Foundation::AsyncStatus _Status) mutable
1937  {
1938  if (_Status == Windows::Foundation::AsyncStatus::Canceled)
1939  {
1940  _OuterTask->_Cancel(true);
1941  }
1942  else if (_Status == Windows::Foundation::AsyncStatus::Error)
1943  {
1944  _OuterTask->_CancelWithException(
1945  std::make_exception_ptr(::Platform::Exception::ReCreateException(static_cast<int>(_Operation->ErrorCode.Value))));
1946  }
1947  else
1948  {
1949  _ASSERTE(_Status == Windows::Foundation::AsyncStatus::Completed);
1950 
1951  try
1952  {
1953  _OuterTask->_FinalizeAndRunContinuations(_Operation->GetResults());
1954  }
1955  catch (...)
1956  {
1957  // unknown exceptions thrown from GetResult
1958  _OuterTask->_CancelWithException(std::current_exception());
1959  }
1960 
1961  }
1962 
1963  // Take away this shared pointers reference on the task instead of waiting for the delegate to be released. It could
1964  // be released on a different thread after a delay, and not releasing the reference here could cause the tasks to hold
1965  // on to resources longer than they should. As an example, without this reset, writing to a file followed by reading from
1966  // it using the Windows Runtime Async APIs causes a sharing violation.
1967  // Using const_cast is the workaround for failed mutable keywords
1968  const_cast<_Task_ptr<_ReturnType>::_Type &>(_OuterTask).reset();
1969  });
1970  _OuterTask->_SetUnwrappedAsyncOp(_AsyncOp);
1971  }
1972 #endif /* defined (__cplusplus_winrt) */
1973 
1974  template<typename _ReturnType, typename _InternalReturnType>
1975  static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type& _OuterTask, const task<_InternalReturnType> & _UnwrappedTask)
1976  {
1977  _ASSERTE(_OuterTask->_M_fUnwrappedTask && !_OuterTask->_IsCanceled());
1978 
1979  //
1980  // We must ensure that continuations off _OuterTask (especially exception handling ones) continue to function in the
1981  // presence of an exception flowing out of the inner task _UnwrappedTask. This requires an exception handling continuation
1982  // off the inner task which does the appropriate funnelling to the outer one. We use _Then instead of then to prevent
1983  // the exception from being marked as observed by our internal continuation. This continuation must be scheduled regardless
1984  // of whether or not the _OuterTask task is canceled.
1985  //
1986  _UnwrappedTask._Then([_OuterTask] (task<_InternalReturnType> _AncestorTask) {
1987 
1988  if (_AncestorTask._GetImpl()->_IsCompleted())
1989  {
1990  _OuterTask->_FinalizeAndRunContinuations(_AncestorTask._GetImpl()->_GetResult());
1991  }
1992  else
1993  {
1994  _ASSERTE(_AncestorTask._GetImpl()->_IsCanceled());
1995  if (_AncestorTask._GetImpl()->_HasUserException())
1996  {
1997  // Set _PropagatedFromAncestor to false, since _AncestorTask is not an ancestor of _UnwrappedTask.
1998  // Instead, it is the enclosing task.
1999  _OuterTask->_CancelWithExceptionHolder(_AncestorTask._GetImpl()->_GetExceptionHolder(), false);
2000  }
2001  else
2002  {
2003  _OuterTask->_Cancel(true);
2004  }
2005  }
2006  }, nullptr, details::_DefaultAutoInline);
2007 
2008  }
2009 
2011  {
2012  return _M_TaskCollection._GetScheduler();
2013  }
2014 
2015  // Tracks the internal state of the task
2017  // Set to true either if the ancestor task had the flag set to true, or if the lambda that does the work of this task returns an
2018  // async operation or async action that is unwrapped by the runtime.
2020  // Set to true when a continuation unwraps a task or async operation.
2022 
2023  // An exception thrown by the task body is captured in an exception holder and it is shared with all value based continuations rooted at the task.
2024  // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception
2025  // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast.
2026  std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
2027 
2029 
2031  _ContinuationList _M_Continuations;
2032 
2033  // The cancellation token state.
2035 
2036  // The registration on the token.
2038 
2039  // The async task collection wrapper
2041 
2042  // Callstack for function call (constructor or .then) that created this task impl.
2044 
2046  private:
2047  // Must not be copied by value:
2049  _Task_impl_base const & operator=(_Task_impl_base const&);
2050  };
2051 
2060 
2061  template<typename _ReturnType>
2062  struct _Task_impl : public _Task_impl_base
2063  {
2065  : _Task_impl_base(_Ct, _Scheduler_arg)
2066  {
2067  }
2068 
2069  virtual ~_Task_impl()
2070  {
2071  // We must invoke _DeregisterCancellation in the derived class destructor. Calling it in the base class destructor could cause
2072  // a partially initialized _Task_impl to be in the list of registrations for a cancellation token.
2073  _DeregisterCancellation();
2074  }
2075 
2076  virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr<_ExceptionHolder> & _ExceptionHolder_arg)
2077  {
2078  enum { _Nothing, _RunContinuations, _Cancel } _Do = _Nothing;
2079  {
2080  ::std::lock_guard<std::mutex> _LockHolder(_M_ContinuationsCritSec);
2081  if (_UserException)
2082  {
2083  _ASSERTE(_SynchronousCancel && !_IsCompleted());
2084  // If the state is _Canceled, the exception has to be coming from an ancestor.
2085  _ASSERTE(!_IsCanceled() || _PropagatedFromAncestor);
2086 
2087  // We should not be canceled with an exception more than once.
2088  _ASSERTE(!_HasUserException());
2089 
2090  if (_M_TaskState == _Canceled)
2091  {
2092  // If the task has finished cancelling there should not be any continuation records in the array.
2093  return false;
2094  }
2095  else
2096  {
2097  _ASSERTE(_M_TaskState != _Completed);
2098  _M_exceptionHolder = _ExceptionHolder_arg;
2099  }
2100  }
2101  else
2102  {
2103  // Completed is a non-cancellable state, and if this is an asynchronous cancel, we're unable to do better than the last async cancel
2104  // which is to say, cancellation is already initiated, so return early.
2105  if (_IsCompleted() || _IsCanceled() || (_IsPendingCancel() && !_SynchronousCancel))
2106  {
2107  _ASSERTE(!_IsCompleted() || !_HasUserException());
2108  return false;
2109  }
2110  _ASSERTE(!_SynchronousCancel || !_HasUserException());
2111  }
2112 
2113  if (_SynchronousCancel)
2114  {
2115  // Be aware that this set must be done BEFORE _M_Scheduled being set, or race will happen between this and wait()
2116  _M_TaskState = _Canceled;
2117  // Cancellation completes the task, so all dependent tasks must be run to cancel them
2118  // They are canceled when they begin running (see _RunContinuation) and see that their
2119  // ancestor has been canceled.
2120  _Do = _RunContinuations;
2121  }
2122  else
2123  {
2124  _ASSERTE(!_UserException);
2125 
2126  if (_IsStarted())
2127  {
2128  // should not initiate cancellation under a lock
2129  _Do = _Cancel;
2130  }
2131 
2132  // The _M_TaskState variable transitions to _Canceled when cancellation is completed (the task is not executing user code anymore).
2133  // In the case of a synchronous cancel, this can happen immediately, whereas with an asynchronous cancel, the task has to move from
2134  // _Started to _PendingCancel before it can move to _Canceled when it is finished executing.
2135  _M_TaskState = _PendingCancel;
2136 
2137  _M_taskEventLogger._LogCancelTask();
2138  }
2139  }
2140 
2141  switch (_Do)
2142  {
2143  case _Cancel:
2144  {
2145  if (_M_InternalCancellation)
2146  {
2147  // We will only try to cancel async operation but not unwrapped tasks, since unwrapped tasks cannot be canceled without its token.
2148  _M_InternalCancellation();
2149  }
2150  _M_TaskCollection._Cancel();
2151  break;
2152  }
2153  case _RunContinuations:
2154  {
2155  // Only execute continuations and mark the task as completed if we were able to move the task to the _Canceled state.
2156  _M_TaskCollection._Complete();
2157 
2158  if (_M_Continuations)
2159  {
2160  // Scheduling cancellation with automatic inlining.
2161  _ScheduleFuncWithAutoInline([=](){ _RunTaskContinuations(); }, details::_DefaultAutoInline);
2162  }
2163 
2164  break;
2165  }
2166  case _Nothing:
2167  default:
2168  break;
2169  }
2170  return true;
2171  }
2172 
2173  void _FinalizeAndRunContinuations(_ReturnType _Result)
2174  {
2175  _M_Result.Set(_Result);
2176 
2177  {
2178  //
2179  // Hold this lock to ensure continuations being concurrently either get added
2180  // to the _M_Continuations vector or wait for the result
2181  //
2182  ::std::lock_guard<std::mutex> _LockHolder(_M_ContinuationsCritSec);
2183 
2184  // A task could still be in the _Created state if it was created with a task_completion_event.
2185  // It could also be in the _Canceled state for the same reason.
2186  _ASSERTE(!_HasUserException() && !_IsCompleted());
2187  if (_IsCanceled())
2188  {
2189  return;
2190  }
2191 
2192  // Always transition to "completed" state, even in the face of unacknowledged pending cancellation
2193  _M_TaskState = _Completed;
2194  }
2195  _M_TaskCollection._Complete();
2196  _RunTaskContinuations();
2197  }
2198 
2199  //
2200  // This method is invoked when the starts executing. The task returns early if this method returns true.
2201  //
2203  {
2204  ::std::lock_guard<std::mutex> _LockHolder(_M_ContinuationsCritSec);
2205  // Canceled state could only result from antecedent task's canceled state, but that code path will not reach here.
2206  _ASSERT(!_IsCanceled());
2207  if (_IsPendingCancel())
2208  return false;
2209 
2210  _ASSERTE(_IsCreated());
2211  _M_TaskState = _Started;
2212  return true;
2213  }
2214 
2215 #if defined (__cplusplus_winrt)
2216  void _SetUnwrappedAsyncOp(Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
2217  {
2218  bool _DoCancel = false;
2219  {
2220  ::std::lock_guard<std::mutex> _LockHolder(_M_ContinuationsCritSec);
2221  // Cancel the async operation if the task itself is canceled, since the thread that canceled the task missed it.
2222  if (_IsPendingCancel())
2223  {
2224  _ASSERTE(!_IsCanceled());
2225  _DoCancel = true;
2226  }
2227  else if (!_IsCanceled() && !_IsCompleted())
2228  {
2229  _M_TaskState = _Started;
2230  _M_InternalCancellation = [=] {
2231  _AsyncOp->Cancel();
2232  };
2233  }
2234  }
2235  if (_DoCancel)
2236  {
2237  _AsyncOp->Cancel();
2238  }
2239  }
2240 #endif /* defined (__cplusplus_winrt) */
2241 
2242  // Return true if the task has reached a terminal state
2243  bool _IsDone()
2244  {
2245  return _IsCompleted() || _IsCanceled();
2246  }
2247 
2248  _ReturnType _GetResult()
2249  {
2250  return _M_Result.Get();
2251  }
2252 
2253  _ResultHolder<_ReturnType> _M_Result; // this means that the result type must have a public default ctor.
2254  std::function<void()> _M_InternalCancellation;
2255  };
2256 
2257  template<typename _ResultType>
2259  {
2260  private:
2263 
2264  public:
2265 
2266  typedef std::vector<typename _Task_ptr<_ResultType>::_Type> _TaskList;
2267 
2269  _M_fHasValue(false), _M_fIsCanceled(false)
2270  {
2271  }
2272 
2274  {
2275  return _M_exceptionHolder != nullptr;
2276  }
2277 
2279  {
2280  for( auto _TaskIt = _M_tasks.begin(); _TaskIt != _M_tasks.end(); ++_TaskIt )
2281  {
2282  _ASSERTE(!_M_fHasValue && !_M_fIsCanceled);
2283  // Cancel the tasks since the event was never signaled or canceled.
2284  (*_TaskIt)->_Cancel(true);
2285  }
2286  }
2287 
2288  // We need to protect the loop over the array, so concurrent_vector would not have helped
2289  _TaskList _M_tasks;
2292  std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
2295  };
2296 
2297  // Utility method for dealing with void functions
2298  inline std::function<_Unit_type(void)> _MakeVoidToUnitFunc(const std::function<void(void)>& _Func)
2299  {
2300  return [=]() -> _Unit_type { _Func(); return _Unit_type(); };
2301  }
2302 
2303  template <typename _Type>
2304  std::function<_Type(_Unit_type)> _MakeUnitToTFunc(const std::function<_Type(void)>& _Func)
2305  {
2306  return [=](_Unit_type) -> _Type { return _Func(); };
2307  }
2308 
2309  template <typename _Type>
2310  std::function<_Unit_type(_Type)> _MakeTToUnitFunc(const std::function<void(_Type)>& _Func)
2311  {
2312  return [=](_Type _Obj) -> _Unit_type { _Func(_Obj); return _Unit_type(); };
2313  }
2314 
2315  inline std::function<_Unit_type(_Unit_type)> _MakeUnitToUnitFunc(const std::function<void(void)>& _Func)
2316  {
2317  return [=](_Unit_type) -> _Unit_type { _Func(); return _Unit_type(); };
2318  }
2319 } // namespace details
2320 
2337 
2338 template<typename _ResultType>
2340 {
2341 public:
2345 
2347  : _M_Impl(std::make_shared<details::_Task_completion_event_impl<_ResultType>>())
2348  {
2349  }
2350 
2366 
2367  bool set(_ResultType _Result) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2368  {
2369  // Subsequent sets are ignored. This makes races to set benign: the first setter wins and all others are ignored.
2370  if (_IsTriggered())
2371  {
2372  return false;
2373  }
2374 
2375  _TaskList _Tasks;
2376  bool _RunContinuations = false;
2377  {
2378  ::std::lock_guard<std::mutex> _LockHolder(_M_Impl->_M_taskListCritSec);
2379 
2380  if (!_IsTriggered())
2381  {
2382  _M_Impl->_M_value.Set(_Result);
2383  _M_Impl->_M_fHasValue = true;
2384 
2385  _Tasks.swap(_M_Impl->_M_tasks);
2386  _RunContinuations = true;
2387  }
2388  }
2389 
2390  if (_RunContinuations)
2391  {
2392  for( auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt )
2393  {
2394  // If current task was cancelled by a cancellation_token, it would be in cancel pending state.
2395  if ((*_TaskIt)->_IsPendingCancel())
2396  (*_TaskIt)->_Cancel(true);
2397  else
2398  {
2399  // Tasks created with task_completion_events can be marked as async, (we do this in when_any and when_all
2400  // if one of the tasks involved is an async task). Since continuations of async tasks can execute inline, we
2401  // need to run continuations after the lock is released.
2402  (*_TaskIt)->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
2403  }
2404  }
2405 
2406  return true;
2407  }
2408 
2409  return false;
2410  }
2411 
2412  template<typename _E>
2413  __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
2414  bool set_exception(_E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2415  {
2416  // It is important that _CAPTURE_CALLSTACK() evaluates to the instruction after the call instruction for set_exception.
2417  return _Cancel(std::make_exception_ptr(_Except), _CAPTURE_CALLSTACK());
2418  }
2419 
2426 
2427  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
2428  bool set_exception(std::exception_ptr _ExceptionPtr) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2429  {
2430  // It is important that _CAPTURE_CALLSTACK() evaluates to the instruction after the call instruction for set_exception.
2431  return _Cancel(_ExceptionPtr, _CAPTURE_CALLSTACK());
2432  }
2433 
2438  bool _Cancel() const
2439  {
2440  // Cancel with the stored exception if one exists.
2441  return _CancelInternal();
2442  }
2443 
2448  template<typename _ExHolderType>
2449  bool _Cancel(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint = details::_TaskCreationCallstack ()) const
2450  {
2451  bool _Canceled;
2452  if(_StoreException(_ExHolder, _SetExceptionAddressHint))
2453  {
2454  _Canceled = _CancelInternal();
2455  _ASSERTE(_Canceled);
2456  }
2457  else
2458  {
2459  _Canceled = false;
2460  }
2461  return _Canceled;
2462  }
2463 
2469  template<typename _ExHolderType>
2470  bool _StoreException(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint = details::_TaskCreationCallstack ()) const
2471  {
2472  ::std::lock_guard<std::mutex> _LockHolder(_M_Impl->_M_taskListCritSec);
2473  if (!_IsTriggered() && !_M_Impl->_HasUserException())
2474  {
2475  // Create the exception holder only if we have ensured there we will be successful in setting it onto the
2476  // task completion event. Failing to do so will result in an unobserved task exception.
2477  _M_Impl->_M_exceptionHolder = _ToExceptionHolder(_ExHolder, _SetExceptionAddressHint);
2478  return true;
2479  }
2480  return false;
2481  }
2487  {
2488  ::std::lock_guard<std::mutex> _LockHolder(_M_Impl->_M_taskListCritSec);
2489  if (_M_Impl->_M_exceptionHolder)
2490  {
2491  details::atomic_exchange(_M_Impl->_M_exceptionHolder->_M_exceptionObserved, 1l);
2492  _M_Impl->_M_exceptionHolder.reset();
2493  }
2494  }
2495 
2499  bool _IsTriggered() const
2500  {
2501  return _M_Impl->_M_fHasValue || _M_Impl->_M_fIsCanceled;
2502  }
2503 
2504 private:
2505 
2506  static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder, const details::_TaskCreationCallstack&)
2507  {
2508  return _ExHolder;
2509  }
2510 
2511  static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(std::exception_ptr _ExceptionPtr, const details::_TaskCreationCallstack &_SetExceptionAddressHint)
2512  {
2513  return std::make_shared<details::_ExceptionHolder>(_ExceptionPtr, _SetExceptionAddressHint);
2514  }
2515 
2516 
2517  template <typename _Ty> friend class task; // task can register itself with the event by calling the private _RegisterTask
2518  template <typename _Ty> friend class task_completion_event;
2519 
2521 
2525  bool _CancelInternal() const
2526  {
2527  // Cancellation of task completion events is an internal only utility. Our usage is such that _CancelInternal
2528  // will never be invoked if the task completion event has been set.
2529  _ASSERTE(!_M_Impl->_M_fHasValue);
2530  if (_M_Impl->_M_fIsCanceled)
2531  {
2532  return false;
2533  }
2534 
2535  _TaskList _Tasks;
2536  bool _Cancel = false;
2537  {
2538  ::std::lock_guard<std::mutex> _LockHolder(_M_Impl->_M_taskListCritSec);
2539  _ASSERTE(!_M_Impl->_M_fHasValue);
2540  if (!_M_Impl->_M_fIsCanceled)
2541  {
2542  _M_Impl->_M_fIsCanceled = true;
2543  _Tasks.swap(_M_Impl->_M_tasks);
2544  _Cancel = true;
2545  }
2546  }
2547 
2548  bool _UserException = _M_Impl->_HasUserException();
2549 
2550  if (_Cancel)
2551  {
2552  for( auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt )
2553  {
2554  // Need to call this after the lock is released. See comments in set().
2555  if (_UserException)
2556  {
2557  (*_TaskIt)->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
2558  }
2559  else
2560  {
2561  (*_TaskIt)->_Cancel(true);
2562  }
2563  }
2564  }
2565  return _Cancel;
2566  }
2567 
2572  void _RegisterTask(const typename details::_Task_ptr<_ResultType>::_Type & _TaskParam)
2573  {
2574  enum { _Nothing, _Trigger, _Cancel } _Action = _Nothing;
2575  {
2576  ::std::lock_guard<std::mutex> _LockHolder(_M_Impl->_M_taskListCritSec);
2577 
2578  //If an exception was already set on this event, then cancel the task with the stored exception.
2579  if (_M_Impl->_HasUserException())
2580  {
2581  _Action = _Cancel;
2582  }
2583  else if (_M_Impl->_M_fHasValue)
2584  {
2585  _Action = _Trigger;
2586  }
2587  else
2588  {
2589  _M_Impl->_M_tasks.push_back(_TaskParam);
2590  }
2591  }
2592 
2593  switch (_Action)
2594  {
2595  case _Trigger:
2596  _TaskParam->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
2597  break;
2598  case _Cancel:
2599  _TaskParam->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
2600  break;
2601  case _Nothing:
2602  default:
2603  break;
2604  }
2605  }
2606 
2607  std::shared_ptr<details::_Task_completion_event_impl<_ResultType>> _M_Impl;
2608 };
2609 
2623 
2624 template<>
2626 {
2627 public:
2640 
2641  bool set() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2642  {
2643  return _M_unitEvent.set(details::_Unit_type());
2644  }
2645 
2646  template<typename _E>
2647  __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
2648  bool set_exception(_E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2649  {
2650  return _M_unitEvent._Cancel(std::make_exception_ptr(_Except), _CAPTURE_CALLSTACK());
2651  }
2652 
2659 
2660  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK intrinsic gives us the expected result
2661  bool set_exception(std::exception_ptr _ExceptionPtr) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2662  {
2663  // It is important that _CAPTURE_CALLSTACK() evaluates to the instruction after the call instruction for set_exception.
2664  return _M_unitEvent._Cancel(_ExceptionPtr, _CAPTURE_CALLSTACK());
2665  }
2666 
2671  void _Cancel() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2672  {
2673  _M_unitEvent._Cancel();
2674  }
2675 
2680  void _Cancel(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
2681  {
2682  _M_unitEvent._Cancel(_ExHolder);
2683  }
2684 
2690  bool _StoreException(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
2691  {
2692  return _M_unitEvent._StoreException(_ExHolder);
2693  }
2694 
2700  {
2701  _M_unitEvent._ClearStoredException();
2702  }
2703 
2707  bool _IsTriggered() const
2708  {
2709  return _M_unitEvent._IsTriggered();
2710  }
2711 
2712 private:
2713  template <typename _Ty> friend class task; // task can register itself with the event by calling the private _RegisterTask
2714 
2720  {
2721  _M_unitEvent._RegisterTask(_TaskParam);
2722  }
2723 
2724  // The void event contains an event a dummy type so common code can be used for events with void and non-void results.
2726 };
2727 
2728 namespace details
2729 {
2730  //
2731  // Compile-time validation helpers
2732  //
2733 
2734  // Task constructor validation: issue helpful diagnostics for common user errors. Do not attempt full validation here.
2735  //
2736  // Anything callable is fine
2737  template<typename _ReturnType, typename _Ty>
2738  auto _IsValidTaskCtor(_Ty _Param, int,int,int,int) -> decltype(_Param(), std::true_type());
2739 
2740 #if defined (__cplusplus_winrt)
2741  // Anything that has GetResults is fine: this covers all async operations
2742  template<typename _ReturnType, typename _Ty>
2743  auto _IsValidTaskCtor(_Ty _Param, int, int, int,...) -> decltype(_Param->GetResults(), std::true_type());
2744 #endif
2745 
2746  // Allow parameters with set: this covers task_completion_event
2747  template<typename _ReturnType, typename _Ty>
2748  auto _IsValidTaskCtor(_Ty _Param, int, int, ...) -> decltype(_Param.set(details::declval<_ReturnType>()), std::true_type());
2749 
2750  template<typename _ReturnType, typename _Ty>
2751  auto _IsValidTaskCtor(_Ty _Param, int, ...) -> decltype(_Param.set(), std::true_type());
2752 
2753  // All else is invalid
2754  template<typename _ReturnType, typename _Ty>
2755  std::false_type _IsValidTaskCtor(_Ty _Param, ...);
2756 
2757  template<typename _ReturnType, typename _Ty>
2758  void _ValidateTaskConstructorArgs(const _Ty& _Param)
2759  {
2760  static_assert(std::is_same<decltype(_IsValidTaskCtor<_ReturnType, _Ty>(_Param,0,0,0,0)),std::true_type>::value,
2761 #if defined (__cplusplus_winrt)
2762  "incorrect argument for task constructor; must be a callable object, an asynchronous operation or a task_completion_event"
2763 #else /* defined (__cplusplus_winrt) */
2764  "incorrect argument for task constructor; must be either a callable object or a task_completion_event"
2765 #endif /* defined (__cplusplus_winrt) */
2766  );
2767 #if defined (__cplusplus_winrt)
2768  static_assert(!(std::is_same<_Ty,_ReturnType>::value && details::_IsIAsyncInfo<_Ty>::_Value),
2769  "incorrect template argument for task; consider using the return type of the async operation");
2770 #endif /* defined (__cplusplus_winrt) */
2771  }
2772 
2774 
2775 #if defined (__cplusplus_winrt)
2776  // Helpers for create_async validation
2777  //
2778  // A parameter lambda taking no arguments is valid
2779  template<typename _Ty>
2780  static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int) -> decltype(_Param(), std::true_type());
2781 
2782  // A parameter lambda taking an cancellation_token argument is valid
2783  template<typename _Ty>
2784  static auto _IsValidCreateAsync(_Ty _Param, int, int, int, ...) -> decltype(_Param(cancellation_token::none()), std::true_type());
2785 
2786  // A parameter lambda taking a progress report argument is valid
2787  template<typename _Ty>
2788  static auto _IsValidCreateAsync(_Ty _Param, int, int, ...) -> decltype(_Param(details::_ProgressReporterCtorArgType()), std::true_type());
2789 
2790  // A parameter lambda taking a progress report and a cancellation_token argument is valid
2791  template<typename _Ty>
2792  static auto _IsValidCreateAsync(_Ty _Param, int, ...) -> decltype(_Param(details::_ProgressReporterCtorArgType(), cancellation_token::none()), std::true_type());
2793 
2794  // All else is invalid
2795  template<typename _Ty>
2796  static std::false_type _IsValidCreateAsync(_Ty _Param, ...);
2797 #endif /* defined (__cplusplus_winrt) */
2798 }
2803 template<typename _InpType, typename _OutType>
2805 {
2806 public:
2807  static auto _Perform(std::function<_OutType(_InpType)> _Func) -> decltype(_Func)
2808  {
2809  return _Func;
2810  }
2811 };
2812 
2813 template<typename _OutType>
2814 class _Continuation_func_transformer<void, _OutType>
2815 {
2816 public:
2817  static auto _Perform(std::function<_OutType(void)> _Func) -> decltype(details::_MakeUnitToTFunc<_OutType>(_Func))
2818  {
2819  return details::_MakeUnitToTFunc<_OutType>(_Func);
2820  }
2821 };
2822 
2823 template<typename _InType>
2825 {
2826 public:
2827  static auto _Perform(std::function<void(_InType)> _Func) -> decltype(details::_MakeTToUnitFunc<_InType>(_Func))
2828  {
2829  return details::_MakeTToUnitFunc<_InType>(_Func);
2830  }
2831 };
2832 
2833 template<>
2835 {
2836 public:
2837  static auto _Perform(std::function<void(void)> _Func) -> decltype(details::_MakeUnitToUnitFunc(_Func))
2838  {
2839  return details::_MakeUnitToUnitFunc(_Func);
2840  }
2841 };
2842 
2843 // A helper class template that transforms an initial task lambda returns void into a lambda that returns a non-void type (details::_Unit_type is used
2844 // to substitute for void). This is to minimize the special handling required for 'void'.
2845 template<typename _RetType>
2847 {
2848 public:
2849  static auto _Perform(std::function<_RetType(void)> _Func) -> decltype(_Func)
2850  {
2851  return _Func;
2852  }
2853 };
2854 
2855 template<>
2857 {
2858 public:
2859  static auto _Perform(std::function<void(void)> _Func) -> decltype(details::_MakeVoidToUnitFunc(_Func))
2860  {
2861  return details::_MakeVoidToUnitFunc(_Func);
2862  }
2863 };
2864 
2878 
2879 template<typename _ReturnType>
2880 class task
2881 {
2882 public:
2886 
2887  typedef _ReturnType result_type;
2888 
2910 
2911  task() : _M_Impl(nullptr)
2912  {
2913  // The default constructor should create a task with a nullptr impl. This is a signal that the
2914  // task is not usable and should throw if any wait(), get() or then() APIs are used.
2915  }
2916 
2951 
2952  template<typename _Ty>
2953  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
2954  explicit task(_Ty _Param)
2955  {
2956  task_options _TaskOptions;
2957  details::_ValidateTaskConstructorArgs<_ReturnType,_Ty>(_Param);
2958 
2959  _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
2960  // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluates to the call site of the task constructor.
2961  _SetTaskCreationCallstack(_CAPTURE_CALLSTACK());
2962 
2963  _TaskInitMaybeFunctor(_Param, decltype(details::_IsCallable(_Param,0))());
2964  }
2965 
2999 
3000  template<typename _Ty>
3001  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3002  explicit task(_Ty _Param, const task_options &_TaskOptions)
3003  {
3004  details::_ValidateTaskConstructorArgs<_ReturnType,_Ty>(_Param);
3005 
3006  _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
3007  // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluates to the call site of the task constructor.
3008  _SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK());
3009 
3010  _TaskInitMaybeFunctor(_Param, decltype(details::_IsCallable(_Param,0))());
3011  }
3012 
3037 
3038  task(const task& _Other): _M_Impl(_Other._M_Impl) {}
3039 
3064 
3065  task(task&& _Other): _M_Impl(std::move(_Other._M_Impl)) {}
3066 
3077 
3078  task& operator=(const task& _Other)
3079  {
3080  if (this != &_Other)
3081  {
3082  _M_Impl = _Other._M_Impl;
3083  }
3084  return *this;
3085  }
3086 
3097 
3098  task& operator=(task&& _Other)
3099  {
3100  if (this != &_Other)
3101  {
3102  _M_Impl = std::move(_Other._M_Impl);
3103  }
3104  return *this;
3105  }
3106 
3126 
3127  template<typename _Function>
3128  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3129  auto then(const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3130  {
3131  task_options _TaskOptions;
3133 
3134  // Note: _ThenImpl's implementation makes a copy of the continuation_context when it schedules the continuation.
3135  // The Continuation Context used to create the _ThenImplOptions must still exist when _ThenImpl executes.
3136  auto _ContinuationContext = _TaskOptions.get_continuation_context();
3137  auto _Options = details::_ThenImplOptions::_CreateOptions(_TaskOptions, _ContinuationContext, _ThenGetImpl()->_GetScheduler());
3138 
3139 #ifndef _PPLTASKS_NO_STDFUNC
3140  return _ThenImpl<_ReturnType>(typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_StdFuncT(_Func), _Options);
3141 #else
3142  return _ThenImpl<_ReturnType>(_Func, _Options);
3143 #endif
3144  }
3145 
3169 
3170  template<typename _Function>
3171  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3172  auto then(const _Function& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3173  {
3175 
3176  // Note: _ThenImpl's implementation makes a copy of the continuation_context when it schedules the continuation.
3177  // The Continuation Context used to create the _ThenImplOptions must still exist when _ThenImpl executes.
3178  auto _ContinuationContext = _TaskOptions.get_continuation_context();
3179  auto _Options = details::_ThenImplOptions::_CreateOptions(_TaskOptions, _ContinuationContext, _ThenGetImpl()->_GetScheduler());
3180 
3181 #ifndef _PPLTASKS_NO_STDFUNC
3182  return _ThenImpl<_ReturnType>(typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_StdFuncT(_Func), _Options);
3183 #else
3184  return _ThenImpl<_ReturnType>(_Func, _Options);
3185 #endif
3186  }
3187 
3215 
3216  template<typename _Function>
3217  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3218  auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3219  {
3220 
3221  task_options _TaskOptions(_CancellationToken, _ContinuationContext);
3223 
3224  auto _Options = details::_ThenImplOptions::_CreateOptions(_TaskOptions, _ContinuationContext, _ThenGetImpl()->_GetScheduler());
3225 
3226 #ifndef _PPLTASKS_NO_STDFUNC
3227  return _ThenImpl<_ReturnType>(typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_StdFuncT(_Func), _Options);
3228 #else
3229  return _ThenImpl<_ReturnType>(_Func, _Options);
3230 #endif
3231  }
3232 
3241 
3242  task_status wait() const
3243  {
3244  if (!_M_Impl)
3245  {
3246  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
3247  }
3248 
3249  return _M_Impl->_Wait();
3250  }
3251 
3263 
3264  _ReturnType get() const
3265  {
3266  if (!_M_Impl)
3267  {
3268  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
3269  }
3270 
3271  if (_M_Impl->_Wait() == canceled)
3272  {
3274  }
3275 
3276  return _M_Impl->_GetResult();
3277  }
3278 
3288  bool is_done() const
3289  {
3290  if (!_M_Impl)
3291  {
3292  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
3293  }
3294 
3295  return _M_Impl->_IsDone();
3296  }
3297 
3305  {
3306  if (!_M_Impl)
3307  {
3308  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
3309  }
3310 
3311  return _M_Impl->_GetScheduler();
3312  }
3313 
3320 
3321  bool is_apartment_aware() const
3322  {
3323  if (!_M_Impl)
3324  {
3325  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
3326  }
3327  return _M_Impl->_IsApartmentAware();
3328  }
3329 
3336 
3337  bool operator==(const task<_ReturnType>& _Rhs) const
3338  {
3339  return (_M_Impl == _Rhs._M_Impl);
3340  }
3341 
3348 
3349  bool operator!=(const task<_ReturnType>& _Rhs) const
3350  {
3351  return !operator==(_Rhs);
3352  }
3353 
3358  {
3359  _ASSERTE(_Ct != nullptr);
3360  _M_Impl = details::_Task_ptr<_ReturnType>::_Make(_Ct, _Scheduler);
3362  {
3363  _M_Impl->_RegisterCancellation(_M_Impl);
3364  }
3365  }
3366 
3371  {
3372  return _M_Impl;
3373  }
3374 
3376  {
3377  if (!_M_Impl)
3378  {
3379  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
3380  }
3381 
3382  return _M_Impl;
3383  }
3384 
3389  {
3390  _ASSERTE(!_M_Impl);
3391  _M_Impl = _Impl;
3392  }
3393 
3398  {
3399  _ASSERTE(!_M_Impl);
3400  _M_Impl = std::move(_Impl);
3401  }
3402 
3406  void _SetAsync(bool _Async = true)
3407  {
3408  _GetImpl()->_SetAsync(_Async);
3409  }
3410 
3415  {
3416  _GetImpl()->_SetTaskCreationCallstack(_callstack);
3417  }
3418 
3424  template<typename _Function>
3425  auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState,
3426  details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3427  {
3428  // inherit from antecedent
3429  auto _Scheduler = _GetImpl()->_GetScheduler();
3430 
3431  // Note: _ThenImpl's implementation makes a copy of the continuation_context when it schedules the continuation. '
3432  // The Continuation Context used to create the _ThenImplOptions must still exist when _ThenImpl executes.
3433  auto _Default_Context = task_continuation_context::use_default();
3434  details::_ThenImplOptions _Options (_PTokenState, &_Default_Context, _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
3435 
3436 #ifndef _PPLTASKS_NO_STDFUNC
3437  return _ThenImpl<_ReturnType>(typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_StdFuncT(_Func), _Options);
3438 #else
3439  return _ThenImpl<_ReturnType>(_Func, _Options);
3440 #endif
3441  }
3442 
3443 private:
3444  template <typename _Ty> friend class task;
3445 
3446 
3447  // The task handle type used to construct an 'initial task' - a task with no dependents.
3448  template <typename _InternalReturnType, typename _Function, typename _TypeSelection>
3450  details::_PPLTaskHandle<_ReturnType, _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>, details::_UnrealizedChore_t>
3451  {
3452  _Function _M_function;
3453  _InitialTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _TaskImpl, const _Function & _func)
3454  : details::_PPLTaskHandle<_ReturnType, _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>, details::_UnrealizedChore_t>::_PPLTaskHandle(_TaskImpl)
3455  , _M_function(_func)
3456  {
3457  }
3458 
3459  virtual ~_InitialTaskHandle() {}
3460 
3461  template <typename _Func>
3462  auto _LogWorkItemAndInvokeUserLambda(_Func _func) const -> decltype(_func())
3463  {
3464  details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
3465  return _func();
3466  }
3467 
3468  void _Perform() const
3469  {
3470  _Init(_TypeSelection());
3471  }
3472 
3474  {
3475  this->_M_pTask->_Cancel(true);
3476  }
3477 
3478  //
3479  // Overload 0: returns _InternalReturnType
3480  //
3481  // This is the most basic task with no unwrapping
3482  //
3484  {
3485  this->_M_pTask->_FinalizeAndRunContinuations(_LogWorkItemAndInvokeUserLambda(_Init_func_transformer<_InternalReturnType>::_Perform(_M_function)));
3486  }
3487 
3488  //
3489  // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only under /ZW)
3490  // or
3491  // returns task<_InternalReturnType>
3492  //
3493  // This is task whose functor returns an async operation or a task which will be unwrapped for continuation
3494  // Depending on the output type, the right _AsyncInit gets invoked
3495  //
3497  {
3498  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask, _LogWorkItemAndInvokeUserLambda(_M_function));
3499  }
3500 
3501 #if defined (__cplusplus_winrt)
3502  //
3503  // Overload 2: returns IAsyncAction^
3504  //
3505  // This is task whose functor returns an async action which will be unwrapped for continuation
3506  //
3507  void _Init(details::_TypeSelectorAsyncAction) const
3508  {
3509  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask, ref new details::_IAsyncActionToAsyncOperationConverter(_LogWorkItemAndInvokeUserLambda(_M_function)));
3510  }
3511 
3512  //
3513  // Overload 3: returns IAsyncOperationWithProgress<_InternalReturnType, _ProgressType>^
3514  //
3515  // This is task whose functor returns an async operation with progress which will be unwrapped for continuation
3516  //
3518  {
3520 
3521  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask,
3522  ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_InternalReturnType,_ProgressType>(_LogWorkItemAndInvokeUserLambda(_M_function)));
3523  }
3524 
3525  //
3526  // Overload 4: returns IAsyncActionWithProgress<_ProgressType>^
3527  //
3528  // This is task whose functor returns an async action with progress which will be unwrapped for continuation
3529  //
3530  void _Init(details::_TypeSelectorAsyncActionWithProgress) const
3531  {
3533 
3534  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask,
3535  ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(_LogWorkItemAndInvokeUserLambda(_M_function)));
3536  }
3537 #endif /* defined (__cplusplus_winrt) */
3538  };
3539 
3540 
3544  template <typename _InternalReturnType, typename _ContinuationReturnType, typename _Function, typename _IsTaskBased, typename _TypeSelection>
3546  details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3547  _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
3548  {
3550 
3552  _Function _M_function;
3553 
3555  const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type & _ContinuationImpl,
3556  const _Function & _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode)
3557  : details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3558  _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
3559  ::_PPLTaskHandle(_ContinuationImpl)
3560  , _M_ancestorTaskImpl(_AncestorImpl)
3561  , _M_function(_Func)
3562  {
3563  this->_M_isTaskBasedContinuation = _IsTaskBased::value;
3564  this->_M_continuationContext = _Context;
3565  this->_M_continuationContext._Resolve(_AncestorImpl->_IsApartmentAware());
3566  this->_M_inliningMode = _InliningMode;
3567  }
3568 
3570 
3571  template <typename _Func, typename _Arg>
3572  auto _LogWorkItemAndInvokeUserLambda(_Func && _func, _Arg && _value) const -> decltype(_func(std::forward<_Arg>(_value)))
3573  {
3574  details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
3575  return _func(std::forward<_Arg>(_value));
3576  }
3577 
3578  void _Perform() const
3579  {
3580  _Continue(_IsTaskBased(), _TypeSelection());
3581  }
3582 
3584  {
3585  if (_M_ancestorTaskImpl->_HasUserException())
3586  {
3587  // If the ancestor encountered an exception, transfer the exception to the continuation
3588  // This traverses down the tree to propagate the exception.
3589  this->_M_pTask->_CancelWithExceptionHolder(_M_ancestorTaskImpl->_GetExceptionHolder(), true);
3590  }
3591  else
3592  {
3593  // If the ancestor was canceled, then your own execution should be canceled.
3594  // This traverses down the tree to cancel it.
3595  this->_M_pTask->_Cancel(true);
3596  }
3597  }
3598 
3599  //
3600  // Overload 0-0: _InternalReturnType -> _TaskType
3601  //
3602  // This is a straight task continuation which simply invokes its target with the ancestor's completion argument
3603  //
3605  {
3606  this->_M_pTask->_FinalizeAndRunContinuations(
3607  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _ContinuationReturnType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult()));
3608  }
3609 
3610  //
3611  // Overload 0-1: _InternalReturnType -> IAsyncOperation<_TaskType>^ (only under /ZW)
3612  // or
3613  // _InternalReturnType -> task<_TaskType>
3614  //
3615  // This is a straight task continuation which returns an async operation or a task which will be unwrapped for continuation
3616  // Depending on the output type, the right _AsyncInit gets invoked
3617  //
3619  {
3621 
3622  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3623  this->_M_pTask,
3624  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult())
3625  );
3626  }
3627 
3628 #if defined (__cplusplus_winrt)
3629  //
3630  // Overload 0-2: _InternalReturnType -> IAsyncAction^
3631  //
3632  // This is a straight task continuation which returns an async action which will be unwrapped for continuation
3633  //
3634  void _Continue(std::false_type, details::_TypeSelectorAsyncAction) const
3635  {
3637 
3638  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3639  this->_M_pTask,
3640  ref new details::_IAsyncActionToAsyncOperationConverter(
3641  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult())));
3642  }
3643 
3644  //
3645  // Overload 0-3: _InternalReturnType -> IAsyncOperationWithProgress<_TaskType, _ProgressType>^
3646  //
3647  // This is a straight task continuation which returns an async operation with progress which will be unwrapped for continuation
3648  //
3650  {
3652 
3653  auto _OpWithProgress = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult());
3655 
3656  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3657  this->_M_pTask,
3658  ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType, _ProgressType>(_OpWithProgress));
3659  }
3660 
3661  //
3662  // Overload 0-4: _InternalReturnType -> IAsyncActionWithProgress<_ProgressType>^
3663  //
3664  // This is a straight task continuation which returns an async action with progress which will be unwrapped for continuation
3665  //
3666  void _Continue(std::false_type, details::_TypeSelectorAsyncActionWithProgress) const
3667  {
3668  typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
3669 
3670  auto _OpWithProgress = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult());
3672 
3673  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3674  this->_M_pTask,
3675  ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(_OpWithProgress));
3676  }
3677 
3678 #endif /* defined (__cplusplus_winrt) */
3679 
3680  //
3681  // Overload 1-0: task<_InternalReturnType> -> _TaskType
3682  //
3683  // This is an exception handling type of continuation which takes the task rather than the task's result.
3684  //
3686  {
3687  typedef task<_InternalReturnType> _FuncInputType;
3688  task<_InternalReturnType> _ResultTask;
3689  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3690  this->_M_pTask->_FinalizeAndRunContinuations(
3691  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_FuncInputType, _ContinuationReturnType>::_Perform(_M_function), std::move(_ResultTask)));
3692  }
3693 
3694  //
3695  // Overload 1-1: task<_InternalReturnType> -> IAsyncOperation<_TaskType>^
3696  // or
3697  // task<_TaskType>
3698  //
3699  // This is an exception handling type of continuation which takes the task rather than
3700  // the task's result. It also returns an async operation or a task which will be unwrapped
3701  // for continuation
3702  //
3704  {
3705  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3706  task<_InternalReturnType> _ResultTask;
3707  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3708  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3709  _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask)));
3710  }
3711 
3712 #if defined (__cplusplus_winrt)
3713 
3714  //
3715  // Overload 1-2: task<_InternalReturnType> -> IAsyncAction^
3716  //
3717  // This is an exception handling type of continuation which takes the task rather than
3718  // the task's result. It also returns an async action which will be unwrapped for continuation
3719  //
3720  void _Continue(std::true_type, details::_TypeSelectorAsyncAction) const
3721  {
3722  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3723  task<_InternalReturnType> _ResultTask;
3724  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3725  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3726  ref new details::_IAsyncActionToAsyncOperationConverter(_LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
3727  }
3728 
3729  //
3730  // Overload 1-3: task<_InternalReturnType> -> IAsyncOperationWithProgress<_TaskType, _ProgressType>^
3731  //
3732  // This is an exception handling type of continuation which takes the task rather than
3733  // the task's result. It also returns an async operation with progress which will be unwrapped
3734  // for continuation
3735  //
3737  {
3738  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3739  task<_InternalReturnType> _ResultTask;
3740  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3741 
3743 
3744  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3745  ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType, _ProgressType>(
3746  _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
3747  }
3748 
3749  //
3750  // Overload 1-4: task<_InternalReturnType> -> IAsyncActionWithProgress<_ProgressType>^
3751  //
3752  // This is an exception handling type of continuation which takes the task rather than
3753  // the task's result. It also returns an async operation with progress which will be unwrapped
3754  // for continuation
3755  //
3756  void _Continue(std::true_type, details::_TypeSelectorAsyncActionWithProgress) const
3757  {
3758  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3759  task<_InternalReturnType> _ResultTask;
3760  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3761 
3763 
3764  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3765  ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(
3766  _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
3767  }
3768 #endif /* defined (__cplusplus_winrt) */
3769  };
3770 
3774  template<typename _InternalReturnType, typename _Function>
3775  void _TaskInitWithFunctor(const _Function& _Func)
3776  {
3778 
3779  _M_Impl->_M_fFromAsync = _Async_type_traits::_IsAsyncTask;
3780  _M_Impl->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
3781  _M_Impl->_M_taskEventLogger._LogScheduleTask(false);
3782  _M_Impl->_ScheduleTask(new _InitialTaskHandle<_InternalReturnType, _Function, typename _Async_type_traits::_AsyncKind>(_GetImpl(), _Func), details::_NoInline);
3783  }
3784 
3789  {
3790  _Event._RegisterTask(_M_Impl);
3791  }
3792 
3793 #if defined (__cplusplus_winrt)
3794  void _TaskInitAsyncOp(Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
3798  {
3799  _M_Impl->_M_fFromAsync = true;
3800 
3801  // Pass the shared pointer into _AsyncInit for storage in the Async Callback.
3802  details::_Task_impl_base::_AsyncInit<_ReturnType, _ReturnType>(_M_Impl, _AsyncOp);
3803  }
3804 
3808  void _TaskInitNoFunctor(Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
3809  {
3810  _TaskInitAsyncOp(_AsyncOp);
3811  }
3812 
3816  template<typename _Progress>
3817  void _TaskInitNoFunctor(Windows::Foundation::IAsyncOperationWithProgress<typename details::_ValueTypeOrRefType<_ReturnType>::_Value, _Progress>^ _AsyncOp)
3818  {
3819  _TaskInitAsyncOp(ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<typename details::_ValueTypeOrRefType<_ReturnType>::_Value, _Progress>(_AsyncOp));
3820  }
3821 #endif /* defined (__cplusplus_winrt) */
3822 
3826  template<typename _Function>
3827  void _TaskInitMaybeFunctor(_Function& _Func, std::true_type)
3828  {
3829  _TaskInitWithFunctor<_ReturnType, _Function>(_Func);
3830  }
3831 
3835  template<typename _Ty>
3837  {
3838  _TaskInitNoFunctor(_Param);
3839  }
3840 
3844  template<typename _InternalReturnType, typename _Function>
3846  {
3847 
3850  typedef typename _Async_type_traits::_TaskRetType _TaskType;
3851 
3852  //
3853  // A **nullptr** token state indicates that it was not provided by the user. In this case, we inherit the antecedent's token UNLESS this is a
3854  // an exception handling continuation. In that case, we break the chain with a _None. That continuation is never canceled unless the user
3855  // explicitly passes the same token.
3856  //
3857  if (_Options._PTokenState == nullptr)
3858  {
3859  if (_Function_type_traits::_Takes_task::value)
3860  {
3861  _Options._PTokenState = details::_CancellationTokenState::_None();
3862  }
3863  else
3864  {
3865  _Options._PTokenState = _GetImpl()->_M_pTokenState;
3866  }
3867  }
3868 
3869  task<_TaskType> _ContinuationTask;
3870  _ContinuationTask._CreateImpl(_Options._PTokenState, _Options._Scheduler);
3871 
3872  _ContinuationTask._GetImpl()->_M_fFromAsync = (_GetImpl()->_M_fFromAsync || _Async_type_traits::_IsAsyncTask);
3873  _ContinuationTask._GetImpl()->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
3874  _ContinuationTask._SetTaskCreationCallstack(_Options._CreationStack);
3875 
3876  _GetImpl()->_ScheduleContinuation(new _ContinuationTaskHandle<_InternalReturnType, _TaskType, _Function, typename _Function_type_traits::_Takes_task, typename _Async_type_traits::_AsyncKind>(
3877  _GetImpl(), _ContinuationTask._GetImpl(), _Func, *_Options._PContinuationContext, _Options._InliningMode));
3878 
3879  return _ContinuationTask;
3880  }
3881 
3882  // The underlying implementation for this task
3884 };
3885 
3896 
3897 template<>
3898 class task<void>
3899 {
3900 public:
3904 
3905  typedef void result_type;
3906 
3928 
3929  task() : _M_unitTask()
3930  {
3931  // The default constructor should create a task with a nullptr impl. This is a signal that the
3932  // task is not usable and should throw if any wait(), get() or then() APIs are used.
3933  }
3934 
3965 
3966  template<typename _Ty>
3967  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3968  explicit task(_Ty _Param, const task_options& _TaskOptions = task_options())
3969  {
3970  details::_ValidateTaskConstructorArgs<void,_Ty>(_Param);
3971 
3972  _M_unitTask._CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
3973  // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluates to the call site of the task constructor.
3974  _M_unitTask._SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK());
3975 
3976  _TaskInitMaybeFunctor(_Param, decltype(details::_IsCallable(_Param,0))());
3977  }
3978 
4003 
4004  task(const task& _Other): _M_unitTask(_Other._M_unitTask){}
4005 
4030 
4031  task(task&& _Other) : _M_unitTask(std::move(_Other._M_unitTask)) {}
4032 
4043 
4044  task& operator=(const task& _Other)
4045  {
4046  if (this != &_Other)
4047  {
4048  _M_unitTask = _Other._M_unitTask;
4049  }
4050  return *this;
4051  }
4052 
4063 
4064  task& operator=(task&& _Other)
4065  {
4066  if (this != &_Other)
4067  {
4068  _M_unitTask = std::move(_Other._M_unitTask);
4069  }
4070  return *this;
4071  }
4072 
4096 
4097  template<typename _Function>
4098  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4099  auto then(const _Function& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4100  {
4102 
4103  // Note: _ThenImpl's implementation makes a copy of the continuation_context when it schedules the continuation. '
4104  // The Continuation Context used to create the _ThenImplOptions must still exist when _ThenImpl executes.
4105  auto _ContinuationContext = _TaskOptions.get_continuation_context();
4106  auto _Options = details::_ThenImplOptions::_CreateOptions(_TaskOptions, _ContinuationContext, _ThenGetImpl()->_GetScheduler());
4107 
4108 #ifndef _PPLTASKS_NO_STDFUNC
4109  return _M_unitTask._ThenImpl<void>(typename details::_ContinuationTypeTraits<_Function, void>::_StdFuncT(_Func), _Options);
4110 #else
4111  return _M_unitTask._ThenImpl<void>(_Func, _Options);
4112 #endif
4113  }
4114 
4142 
4143  template<typename _Function>
4144  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4145  auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4146  {
4147 
4148  task_options _TaskOptions(_CancellationToken, _ContinuationContext);
4150 
4151  auto _Options = details::_ThenImplOptions::_CreateOptions(_TaskOptions, _ContinuationContext, _ThenGetImpl()->_GetScheduler());
4152 
4153 #ifndef _PPLTASKS_NO_STDFUNC
4154  return _M_unitTask._ThenImpl<void>(typename details::_ContinuationTypeTraits<_Function, void>::_StdFuncT(_Func), _Options);
4155 #else
4156  return _M_unitTask._ThenImpl<void>(_Func, _Options);
4157 #endif
4158  }
4159 
4168 
4169  task_status wait() const
4170  {
4171  return _M_unitTask.wait();
4172  }
4173 
4182 
4183  void get() const
4184  {
4185  _M_unitTask.get();
4186  }
4187 
4197  bool is_done() const
4198  {
4199  return _M_unitTask.is_done();
4200  }
4201 
4209  {
4210  return _M_unitTask.scheduler();
4211  }
4212 
4219 
4220  bool is_apartment_aware() const
4221  {
4222  return _M_unitTask.is_apartment_aware();
4223  }
4224 
4231 
4232  bool operator==(const task<void>& _Rhs) const
4233  {
4234  return (_M_unitTask == _Rhs._M_unitTask);
4235  }
4236 
4243 
4244  bool operator!=(const task<void>& _Rhs) const
4245  {
4246  return !operator==(_Rhs);
4247  }
4248 
4253  {
4254  _M_unitTask._CreateImpl(_Ct, _Scheduler);
4255  }
4256 
4261  {
4262  return _M_unitTask._M_Impl;
4263  }
4264 
4266  {
4267  if (!_M_unitTask._M_Impl)
4268  {
4269  details::_DefaultTaskHelper::_NoCallOnDefaultTask_ErrorImpl();
4270  }
4271 
4272  return _M_unitTask._M_Impl;
4273  }
4274 
4279  {
4280  _M_unitTask._SetImpl(_Impl);
4281  }
4282 
4287  {
4288  _M_unitTask._SetImpl(std::move(_Impl));
4289  }
4290 
4294  void _SetAsync(bool _Async = true)
4295  {
4296  _M_unitTask._SetAsync(_Async);
4297  }
4298 
4303  {
4304  _M_unitTask._SetTaskCreationCallstack(_callstack);
4305  }
4306 
4310  template<typename _Function>
4311  auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState,
4312  details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4313  {
4314 
4315  // inherit from antecedent
4316  auto _Scheduler = _ThenGetImpl()->_GetScheduler();
4317 
4318  // Note: _ThenImpl's implementation makes a copy of the continuation_context when it schedules the continuation. '
4319  // The Continuation Context used to create the _ThenImplOptions must still exist when _ThenImpl executes.
4320  auto _Default_Context = task_continuation_context::use_default();
4321  details::_ThenImplOptions _Options{ _PTokenState, &_Default_Context, _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode };
4322 
4323 #ifndef _PPLTASKS_NO_STDFUNC
4324  return _M_unitTask._ThenImpl<void>(typename details::_ContinuationTypeTraits<_Function, void>::_StdFuncT(_Func), _Options);
4325 #else
4326  return _M_unitTask._ThenImpl<void>(_Func, _Options);
4327 #endif
4328  }
4329 
4330 private:
4331  template <typename _Ty> friend class task;
4332  template <typename _Ty> friend class task_completion_event;
4333 
4338  {
4339  _M_unitTask._TaskInitNoFunctor(_Event._M_unitEvent);
4340  }
4341 
4342 #if defined (__cplusplus_winrt)
4343  void _TaskInitNoFunctor(Windows::Foundation::IAsyncAction^ _AsyncAction)
4347  {
4348  _M_unitTask._TaskInitAsyncOp(ref new details::_IAsyncActionToAsyncOperationConverter(_AsyncAction));
4349  }
4350 
4354  template<typename _P>
4355  void _TaskInitNoFunctor(Windows::Foundation::IAsyncActionWithProgress<_P>^ _AsyncActionWithProgress)
4356  {
4357  _M_unitTask._TaskInitAsyncOp(ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_P>(_AsyncActionWithProgress));
4358  }
4359 #endif /* defined (__cplusplus_winrt) */
4360 
4364  template<typename _Function>
4365  void _TaskInitMaybeFunctor(_Function& _Func, std::true_type)
4366  {
4367  _M_unitTask._TaskInitWithFunctor<void, _Function>(_Func);
4368  }
4369 
4373  template<typename _Ty>
4375  {
4376  _TaskInitNoFunctor(_Param);
4377  }
4378 
4379  // The void task contains a task of a dummy type so common code can be used for tasks with void and non-void results.
4381 };
4382 
4383 namespace details
4384 {
4388 
4389 #if defined (__cplusplus_winrt)
4390  // Unwrap functions for asyncOperations
4391  template<typename _Ty>
4392  _Ty _GetUnwrappedType(Windows::Foundation::IAsyncOperation<_Ty>^);
4393 
4394  void _GetUnwrappedType(Windows::Foundation::IAsyncAction^);
4395 
4396  template<typename _Ty, typename _Progress>
4397  _Ty _GetUnwrappedType(Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress>^);
4398 
4399  template<typename _Progress>
4400  void _GetUnwrappedType(Windows::Foundation::IAsyncActionWithProgress<_Progress>^);
4401 #endif /* defined (__cplusplus_winrt) */
4402 
4403  // Unwrap task<T>
4404  template<typename _Ty>
4406 
4407  // Unwrap all supported types
4408  template<typename _Ty>
4409  auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg));
4410  // fallback
4411  template<typename _Ty>
4412  _Ty _GetUnwrappedReturnType(_Ty, ...);
4413 
4419 
4420  // Non-Callable
4421  template<typename _Ty>
4423 
4424  // Non-Callable
4425  template<typename _Ty>
4426  auto _GetTaskType(_Ty _NonFunc, std::false_type) -> decltype(_GetUnwrappedType(_NonFunc));
4427 
4428  // Callable
4429  template<typename _Ty>
4430  auto _GetTaskType(_Ty _Func, std::true_type) -> decltype(_GetUnwrappedReturnType(_Func(), 0));
4431 
4432  // Special callable returns void
4433  void _GetTaskType(std::function<void()>, std::true_type);
4434  struct _BadArgType{};
4435 
4436  template<typename _Ty>
4437  auto _FilterValidTaskType(_Ty _Param, int) -> decltype(_GetTaskType(_Param, _IsCallable(_Param, 0)));
4438 
4439  template<typename _Ty>
4440  _BadArgType _FilterValidTaskType(_Ty _Param, ...);
4441 
4442  template<typename _Ty>
4444  {
4445  typedef decltype(_FilterValidTaskType(details::declval<_Ty>(), 0)) _Type;
4446  };
4447 
4448  inline bool _IsHRCOMDisconnected(int __hr)
4449  {
4450  return __hr == 0x800706BA // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
4451  || __hr == 0x80010108 // RPC_E_DISCONNECTED
4452  || __hr == 0x89020001; // JSCRIPT_E_CANTEXECUTE
4453  }
4454 } // namespace details
4455 
4483 
4484 template<typename _Ty>
4485 __declspec(noinline)
4486 auto create_task(_Ty _Param, task_options _TaskOptions = task_options()) -> task<typename details::_TaskTypeFromParam<_Ty>::_Type>
4487 {
4488  static_assert(!std::is_same<typename details::_TaskTypeFromParam<_Ty>::_Type,details::_BadArgType>::value,
4489 #if defined (__cplusplus_winrt)
4490  "incorrect argument for create_task; can be a callable object, an asynchronous operation, or a task_completion_event"
4491 #else /* defined (__cplusplus_winrt) */
4492  "incorrect argument for create_task; must be either a callable object or a task_completion_event"
4493 #endif /* defined (__cplusplus_winrt) */
4494  );
4496  task<typename details::_TaskTypeFromParam<_Ty>::_Type> _CreatedTask(_Param, _TaskOptions);
4497  return _CreatedTask;
4498 }
4499 
4530 
4531 template<typename _ReturnType>
4532 __declspec(noinline)
4533 task<_ReturnType> create_task(const task<_ReturnType>& _Task)
4534 {
4535  task<_ReturnType> _CreatedTask(_Task);
4536  return _CreatedTask;
4537 }
4538 
4539 #if defined (__cplusplus_winrt)
4540 namespace details
4541 {
4542  template<typename _Ty>
4543  task<_Ty> _To_task_helper(Windows::Foundation::IAsyncOperation<_Ty>^ _Op)
4544  {
4545  return task<_Ty>(_Op);
4546  }
4547 
4548  template<typename _Ty, typename _Progress>
4549  task<_Ty> _To_task_helper(Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress>^ _Op)
4550  {
4551  return task<_Ty>(_Op);
4552  }
4553 
4554  inline task<void> _To_task_helper(Windows::Foundation::IAsyncAction^ _Op)
4555  {
4556  return task<void>(_Op);
4557  }
4558 
4559  template<typename _Progress>
4560  task<void> _To_task_helper(Windows::Foundation::IAsyncActionWithProgress<_Progress>^ _Op)
4561  {
4562  return task<void>(_Op);
4563  }
4564 
4565  template<typename _ProgressType>
4566  class _ProgressDispatcherBase
4567  {
4568  public:
4569 
4570  virtual ~_ProgressDispatcherBase()
4571  {
4572  }
4573 
4574  virtual void _Report(const _ProgressType& _Val) = 0;
4575  };
4576 
4577  template<typename _ProgressType, typename _ClassPtrType>
4578  class _ProgressDispatcher : public _ProgressDispatcherBase<_ProgressType>
4579  {
4580  public:
4581 
4582  virtual ~_ProgressDispatcher()
4583  {
4584  }
4585 
4586  _ProgressDispatcher(_ClassPtrType _Ptr) : _M_ptr(_Ptr)
4587  {
4588  }
4589 
4590  virtual void _Report(const _ProgressType& _Val)
4591  {
4592  _M_ptr->_FireProgress(_Val);
4593  }
4594 
4595  private:
4596 
4597  _ClassPtrType _M_ptr;
4598  };
4599 } // namespace details
4600 
4612 
4613 template<typename _ProgressType>
4614 class progress_reporter
4615 {
4616  typedef std::shared_ptr<details::_ProgressDispatcherBase<_ProgressType>> _PtrType;
4617 
4618 public:
4619 
4626 
4627  void report(const _ProgressType& _Val) const
4628  {
4629  _M_dispatcher->_Report(_Val);
4630  }
4631 
4632  template<typename _ClassPtrType>
4633  static progress_reporter _CreateReporter(_ClassPtrType _Ptr)
4634  {
4635  progress_reporter _Reporter;
4636  details::_ProgressDispatcherBase<_ProgressType> *_PDispatcher = new details::_ProgressDispatcher<_ProgressType, _ClassPtrType>(_Ptr);
4637  _Reporter._M_dispatcher = _PtrType(_PDispatcher);
4638  return _Reporter;
4639  }
4640  progress_reporter() {}
4641 
4642  // For validation type traits
4643  progress_reporter(details::_ProgressReporterCtorArgType);
4644 private:
4645 
4646  _PtrType _M_dispatcher;
4647 };
4648 
4649 namespace details
4650 {
4651  //
4652  // maps internal definitions for AsyncStatus and defines states that are not client visible
4653  //
4654  enum _AsyncStatusInternal
4655  {
4656  _AsyncCreated = -1, // externally invisible
4657  // client visible states (must match AsyncStatus exactly)
4658  _AsyncStarted = 0, // Windows::Foundation::AsyncStatus::Started,
4659  _AsyncCompleted = 1, // Windows::Foundation::AsyncStatus::Completed,
4660  _AsyncCanceled = 2, // Windows::Foundation::AsyncStatus::Canceled,
4661  _AsyncError = 3, // Windows::Foundation::AsyncStatus::Error,
4662  // non-client visible internal states
4663  _AsyncCancelPending,
4664  _AsyncClosed,
4665  _AsyncUndefined
4666  };
4667 
4668  //
4669  // designates whether the "GetResults" method returns a single result (after complete fires) or multiple results
4670  // (which are progressively consumable between Start state and before Close is called)
4671  //
4672  enum _AsyncResultType
4673  {
4674  SingleResult = 0x0001,
4675  MultipleResults = 0x0002
4676  };
4677 
4678  // ***************************************************************************
4679  // Template type traits and helpers for async production APIs:
4680  //
4681 
4682  struct _ZeroArgumentFunctor { };
4683  struct _OneArgumentFunctor { };
4684  struct _TwoArgumentFunctor { };
4685 
4686  // ****************************************
4687  // CLASS TYPES:
4688 
4689  // ********************
4690  // TWO ARGUMENTS:
4691 
4692  // non-void arg:
4693  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4694  _Arg1 _Arg1ClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4695 
4696  // non-void arg:
4697  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4698  _Arg2 _Arg2ClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4699 
4700  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4701  _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4702 
4703  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4704  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4705 
4706  // ********************
4707  // ONE ARGUMENT:
4708 
4709  // non-void arg:
4710  template<typename _Class, typename _ReturnType, typename _Arg1>
4711  _Arg1 _Arg1ClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
4712 
4713  // non-void arg:
4714  template<typename _Class, typename _ReturnType, typename _Arg1>
4715  void _Arg2ClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
4716 
4717  template<typename _Class, typename _ReturnType, typename _Arg1>
4718  _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
4719 
4720  template<typename _Class, typename _ReturnType, typename _Arg1>
4721  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)(_Arg1) const);
4722 
4723  // ********************
4724  // ZERO ARGUMENT:
4725 
4726  // void arg:
4727  template<typename _Class, typename _ReturnType>
4728  void _Arg1ClassHelperThunk(_ReturnType (_Class::*)() const);
4729 
4730  // void arg:
4731  template<typename _Class, typename _ReturnType>
4732  void _Arg2ClassHelperThunk(_ReturnType (_Class::*)() const);
4733 
4734  // void arg:
4735  template<typename _Class, typename _ReturnType>
4736  _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)() const);
4737 
4738  template<typename _Class, typename _ReturnType>
4739  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)() const);
4740 
4741  // ****************************************
4742  // POINTER TYPES:
4743 
4744  // ********************
4745  // TWO ARGUMENTS:
4746 
4747  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4748  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4749 
4750  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4751  _Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4752 
4753  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4754  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4755 
4756  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4757  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4758 
4759  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4760  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4761 
4762  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4763  _Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4764 
4765  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4766  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4767 
4768  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4769  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4770 
4771  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4772  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4773 
4774  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4775  _Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4776 
4777  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4778  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4779 
4780  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4781  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4782 
4783  // ********************
4784  // ONE ARGUMENT:
4785 
4786  template<typename _ReturnType, typename _Arg1>
4787  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
4788 
4789  template<typename _ReturnType, typename _Arg1>
4790  void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
4791 
4792  template<typename _ReturnType, typename _Arg1>
4793  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
4794 
4795  template<typename _ReturnType, typename _Arg1>
4796  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1));
4797 
4798  template<typename _ReturnType, typename _Arg1>
4799  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
4800 
4801  template<typename _ReturnType, typename _Arg1>
4802  void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
4803 
4804  template<typename _ReturnType, typename _Arg1>
4805  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
4806 
4807  template<typename _ReturnType, typename _Arg1>
4808  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1));
4809 
4810  template<typename _ReturnType, typename _Arg1>
4811  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
4812 
4813  template<typename _ReturnType, typename _Arg1>
4814  void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
4815 
4816  template<typename _ReturnType, typename _Arg1>
4817  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
4818 
4819  template<typename _ReturnType, typename _Arg1>
4820  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1));
4821 
4822  // ********************
4823  // ZERO ARGUMENT:
4824 
4825  template<typename _ReturnType>
4826  void _Arg1PFNHelperThunk(_ReturnType(__cdecl *)());
4827 
4828  template<typename _ReturnType>
4829  void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)());
4830 
4831  template<typename _ReturnType>
4832  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)());
4833 
4834  template<typename _ReturnType>
4835  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)());
4836 
4837  template<typename _ReturnType>
4838  void _Arg1PFNHelperThunk(_ReturnType(__stdcall *)());
4839 
4840  template<typename _ReturnType>
4841  void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)());
4842 
4843  template<typename _ReturnType>
4844  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)());
4845 
4846  template<typename _ReturnType>
4847  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)());
4848 
4849  template<typename _ReturnType>
4850  void _Arg1PFNHelperThunk(_ReturnType(__fastcall *)());
4851 
4852  template<typename _ReturnType>
4853  void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)());
4854 
4855  template<typename _ReturnType>
4856  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)());
4857 
4858  template<typename _ReturnType>
4859  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)());
4860 
4861  template<typename _Ty>
4862  struct _FunctorArguments
4863  {
4864  static const size_t _Count = 0;
4865  };
4866 
4867  template<>
4868  struct _FunctorArguments<_OneArgumentFunctor>
4869  {
4870  static const size_t _Count = 1;
4871  };
4872 
4873  template<>
4874  struct _FunctorArguments<_TwoArgumentFunctor>
4875  {
4876  static const size_t _Count = 2;
4877  };
4878 
4879  template<typename _Ty>
4880  struct _FunctorTypeTraits
4881  {
4882  typedef decltype(_ArgumentCountHelper(&(_Ty::operator()))) _ArgumentCountType;
4883  static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
4884 
4885  typedef decltype(_ReturnTypeClassHelperThunk(&(_Ty::operator()))) _ReturnType;
4886  typedef decltype(_Arg1ClassHelperThunk(&(_Ty::operator()))) _Argument1Type;
4887  typedef decltype(_Arg2ClassHelperThunk(&(_Ty::operator()))) _Argument2Type;
4888  };
4889 
4890  template<typename _Ty>
4891  struct _FunctorTypeTraits<_Ty *>
4892  {
4893  typedef decltype(_ArgumentCountHelper(details::declval<_Ty*>())) _ArgumentCountType;
4894  static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
4895 
4896  typedef decltype(_ReturnTypePFNHelperThunk(details::declval<_Ty*>())) _ReturnType;
4897  typedef decltype(_Arg1PFNHelperThunk(details::declval<_Ty*>())) _Argument1Type;
4898  typedef decltype(_Arg2PFNHelperThunk(details::declval<_Ty*>())) _Argument2Type;
4899  };
4900 
4901  template<typename _Ty>
4902  struct _ProgressTypeTraits
4903  {
4904  static const bool _TakesProgress = false;
4905  typedef void _ProgressType;
4906  };
4907 
4908  template<typename _Ty>
4909  struct _ProgressTypeTraits<progress_reporter<_Ty>>
4910  {
4911  static const bool _TakesProgress = true;
4912  typedef typename _Ty _ProgressType;
4913  };
4914 
4915 
4916  template<typename _Ty, size_t _Count = _FunctorTypeTraits<_Ty>::_ArgumentCount>
4917  struct _CAFunctorOptions
4918  {
4919  static const bool _TakesProgress = false;
4920  static const bool _TakesToken = false;
4921  typedef void _ProgressType;
4922  };
4923 
4924  template<typename _Ty>
4925  struct _CAFunctorOptions<_Ty, 1>
4926  {
4927  private:
4928 
4929  typedef typename _FunctorTypeTraits<_Ty>::_Argument1Type _Argument1Type;
4930 
4931  public:
4932 
4933  static const bool _TakesProgress = _ProgressTypeTraits<_Argument1Type>::_TakesProgress;
4934  static const bool _TakesToken = !_TakesProgress;
4935  typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
4936  };
4937 
4938  template<typename _Ty>
4939  struct _CAFunctorOptions<_Ty, 2>
4940  {
4941  private:
4942 
4943  typedef typename _FunctorTypeTraits<_Ty>::_Argument1Type _Argument1Type;
4944 
4945  public:
4946 
4947  static const bool _TakesProgress = true;
4948  static const bool _TakesToken = true;
4949  typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
4950  };
4951 
4952  ref class _Zip
4953  {
4954  };
4955 
4956  // ***************************************************************************
4957  // Async Operation Task Generators
4958  //
4959 
4960  //
4961  // Functor returns an IAsyncInfo - result needs to be wrapped in a task:
4962  //
4963  template<typename _AsyncSelector, typename _ReturnType>
4964  struct _SelectorTaskGenerator
4965  {
4966  template<typename _Function>
4967  static task<_ReturnType> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
4968  {
4969  task_options _taskOptinos(_Cts.get_token());
4971  return task<_ReturnType>(_Func(), _taskOptinos);
4972  }
4973 
4974  template<typename _Function>
4975  static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
4976  {
4977  task_options _taskOptinos(_Cts.get_token());
4979  return task<_ReturnType>(_Func(_Cts.get_token()), _taskOptinos);
4980  }
4981 
4982  template<typename _Function, typename _ProgressObject>
4983  static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
4984  {
4985  task_options _taskOptinos(_Cts.get_token());
4987  return task<_ReturnType>(_Func(_Progress), _taskOptinos);
4988  }
4989 
4990  template<typename _Function, typename _ProgressObject>
4991  static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
4992  {
4993  task_options _taskOptinos(_Cts.get_token());
4995  return task<_ReturnType>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
4996  }
4997  };
4998 
4999  template<typename _AsyncSelector>
5000  struct _SelectorTaskGenerator<_AsyncSelector, void>
5001  {
5002  template<typename _Function>
5003  static task<void> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5004  {
5005  task_options _taskOptinos(_Cts.get_token());
5007  return task<void>(_Func(), _taskOptinos);
5008  }
5009 
5010  template<typename _Function>
5011  static task<void> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5012  {
5013  task_options _taskOptinos(_Cts.get_token());
5015  return task<void>(_Func(_Cts.get_token()), _taskOptinos);
5016  }
5017 
5018  template<typename _Function, typename _ProgressObject>
5019  static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5020  {
5021  task_options _taskOptinos(_Cts.get_token());
5023  return task<void>(_Func(_Progress), _taskOptinos);
5024  }
5025 
5026  template<typename _Function, typename _ProgressObject>
5027  static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5028  {
5029  task_options _taskOptinos(_Cts.get_token());
5031  return task<void>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
5032  }
5033  };
5034 
5035  //
5036  // Functor returns a result - it needs to be wrapped in a task:
5037  //
5038  template<typename _ReturnType>
5039  struct _SelectorTaskGenerator<_TypeSelectorNoAsync, _ReturnType>
5040  {
5041 
5042 #pragma warning(push)
5043 #pragma warning(disable: 4702)
5044  template<typename _Function>
5045  static task<_ReturnType> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5046  {
5047  task_options _taskOptinos(_Cts.get_token());
5049  return task<_ReturnType>( [=]() -> _ReturnType {
5050  _Task_generator_oversubscriber_t _Oversubscriber;
5051  (_Oversubscriber);
5052  return _Func();
5053  }, _taskOptinos);
5054  }
5055 #pragma warning(pop)
5056 
5057  template<typename _Function>
5058  static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5059  {
5060  task_options _taskOptinos(_Cts.get_token());
5062  return task<_ReturnType>( [=]() -> _ReturnType {
5063  _Task_generator_oversubscriber_t _Oversubscriber;
5064  (_Oversubscriber);
5065  return _Func(_Cts.get_token());
5066  }, _taskOptinos);
5067  }
5068 
5069  template<typename _Function, typename _ProgressObject>
5070  static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5071  {
5072  task_options _taskOptinos(_Cts.get_token());
5074  return task<_ReturnType>( [=]() -> _ReturnType {
5075  _Task_generator_oversubscriber_t _Oversubscriber;
5076  (_Oversubscriber);
5077  return _Func(_Progress);
5078  }, _taskOptinos);
5079  }
5080 
5081  template<typename _Function, typename _ProgressObject>
5082  static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5083  {
5084  task_options _taskOptinos(_Cts.get_token());
5086  return task<_ReturnType>( [=]() -> _ReturnType {
5087  _Task_generator_oversubscriber_t _Oversubscriber;
5088  (_Oversubscriber);
5089  return _Func(_Progress, _Cts.get_token());
5090  }, _taskOptinos);
5091  }
5092  };
5093 
5094  template<>
5095  struct _SelectorTaskGenerator<_TypeSelectorNoAsync, void>
5096  {
5097  template<typename _Function>
5098  static task<void> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5099  {
5100  task_options _taskOptinos(_Cts.get_token());
5102  return task<void>( [=]() {
5103  _Task_generator_oversubscriber_t _Oversubscriber;
5104  (_Oversubscriber);
5105  _Func();
5106  }, _taskOptinos);
5107  }
5108 
5109  template<typename _Function>
5110  static task<void> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5111  {
5112  task_options _taskOptinos(_Cts.get_token());
5114  return task<void>( [=]() {
5115  _Task_generator_oversubscriber_t _Oversubscriber;
5116  (_Oversubscriber);
5117  _Func(_Cts.get_token());
5118  }, _taskOptinos);
5119  }
5120 
5121  template<typename _Function, typename _ProgressObject>
5122  static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5123  {
5124  task_options _taskOptinos(_Cts.get_token());
5126  return task<void>( [=]() {
5127  _Task_generator_oversubscriber_t _Oversubscriber;
5128  (_Oversubscriber);
5129  _Func(_Progress);
5130  }, _taskOptinos);
5131  }
5132 
5133  template<typename _Function, typename _ProgressObject>
5134  static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5135  {
5136  task_options _taskOptinos(_Cts.get_token());
5138  return task<void>( [=]() {
5139  _Task_generator_oversubscriber_t _Oversubscriber;
5140  (_Oversubscriber);
5141  _Func(_Progress, _Cts.get_token());
5142  }, _taskOptinos);
5143  }
5144  };
5145 
5146  //
5147  // Functor returns a task - the task can directly be returned:
5148  //
5149  template<typename _ReturnType>
5150  struct _SelectorTaskGenerator<_TypeSelectorAsyncTask, _ReturnType>
5151  {
5152  template<typename _Function>
5153  static task<_ReturnType> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5154  {
5155  return _Func();
5156  }
5157 
5158  template<typename _Function>
5159  static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5160  {
5161  return _Func(_Cts.get_token());
5162  }
5163 
5164  template<typename _Function, typename _ProgressObject>
5165  static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5166  {
5167  return _Func(_Progress);
5168  }
5169 
5170  template<typename _Function, typename _ProgressObject>
5171  static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5172  {
5173  return _Func(_Progress, _Cts.get_token());
5174  }
5175  };
5176 
5177  template<>
5178  struct _SelectorTaskGenerator<_TypeSelectorAsyncTask, void>
5179  {
5180  template<typename _Function>
5181  static task<void> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5182  {
5183  return _Func();
5184  }
5185 
5186  template<typename _Function>
5187  static task<void> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5188  {
5189  return _Func(_Cts.get_token());
5190  }
5191 
5192  template<typename _Function, typename _ProgressObject>
5193  static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5194  {
5195  return _Func(_Progress);
5196  }
5197 
5198  template<typename _Function, typename _ProgressObject>
5199  static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5200  {
5201  return _Func(_Progress, _Cts.get_token());
5202  }
5203  };
5204 
5205  template<typename _Generator, bool _TakesToken, bool TakesProgress>
5206  struct _TaskGenerator
5207  {
5208  };
5209 
5210  template<typename _Generator>
5211  struct _TaskGenerator<_Generator, false, false>
5212  {
5213  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5214  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5215  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5216  {
5217 #ifndef _PPLTASKS_NO_STDFUNC
5218  typedef decltype(_Func()) _ReturnType;
5219  typedef std::function<_ReturnType __cdecl()> _StdFunction;
5220  return _Generator::_GenerateTask_0(_StdFunction(_Func), _Cts, _callstack);
5221 #else
5222  return _Generator::_GenerateTask_0(_Func, _Cts, _callstack);
5223 #endif
5224  }
5225  };
5226 
5227  template<typename _Generator>
5228  struct _TaskGenerator<_Generator, true, false>
5229  {
5230  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5231  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5232  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5233  {
5234 #ifndef _PPLTASKS_NO_STDFUNC
5235  typedef decltype(_Func(details::declval<cancellation_token>())) _ReturnType;
5236  return _Generator::_GenerateTask_1C(std::function<_ReturnType __cdecl(cancellation_token)>(_Func), _Cts, _callstack);
5237 #else
5238  return _Generator::_GenerateTask_1C(_Func, _Cts, _callstack);
5239 #endif
5240  }
5241  };
5242 
5243  template<typename _Generator>
5244  struct _TaskGenerator<_Generator, false, true>
5245  {
5246  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5247  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5248  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5249  {
5250 #ifndef _PPLTASKS_NO_STDFUNC
5251  typedef decltype(_Func(details::declval<const progress_reporter<_ProgressType>&>())) _ReturnType;
5252  return _Generator::_GenerateTask_1P(std::function<_ReturnType __cdecl(const progress_reporter<_ProgressType>&)>(_Func), progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5253 #else
5254  return _Generator::_GenerateTask_1P(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5255 #endif
5256  }
5257  };
5258 
5259  template<typename _Generator>
5260  struct _TaskGenerator<_Generator, true, true>
5261  {
5262  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5263  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5264  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5265  {
5266 #ifndef _PPLTASKS_NO_STDFUNC
5267  typedef decltype(_Func(details::declval<const progress_reporter<_ProgressType>&>(), details::declval<cancellation_token>())) _ReturnType;
5268  return _Generator::_GenerateTask_2PC(std::function<_ReturnType __cdecl(const progress_reporter<_ProgressType>&, cancellation_token)>(_Func), progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5269 #else
5270  return _Generator::_GenerateTask_2PC(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5271 #endif
5272  }
5273  };
5274 
5275  // ***************************************************************************
5276  // Async Operation Attributes Classes
5277  //
5278  // These classes are passed through the hierarchy of async base classes in order to hold multiple attributes of a given async construct in
5279  // a single container. An attribute class must define:
5280  //
5281  // Mandatory:
5282  // -------------------------
5283  //
5284  // _AsyncBaseType : The Windows Runtime interface which is being implemented.
5285  // _CompletionDelegateType : The Windows Runtime completion delegate type for the interface.
5286  // _ProgressDelegateType : If _TakesProgress is true, the Windows Runtime progress delegate type for the interface. If it is false, an empty Windows Runtime type.
5287  // _ReturnType : The return type of the async construct (void for actions / non-void for operations)
5288  //
5289  // _TakesProgress : An indication as to whether or not
5290  //
5291  //
5292  // Optional:
5293  // -------------------------
5294  //
5295 
5296  template<typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken, bool _TakesProgress>
5297  struct _AsyncAttributes
5298  {
5299  };
5300 
5301  template<typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
5302  struct _AsyncAttributes<_ProgressType, _ReturnType, _TaskTraits, _TakesToken, true>
5303  {
5304  typedef Windows::Foundation::IAsyncOperationWithProgress<_ReturnType, _ProgressType> _AsyncBaseType;
5305  typedef Windows::Foundation::AsyncOperationProgressHandler<_ReturnType, _ProgressType> _ProgressDelegateType;
5306  typedef Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_ReturnType, _ProgressType> _CompletionDelegateType;
5307  typedef _ReturnType _ReturnType;
5308  typedef _ProgressType _ProgressType;
5309  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5310  typedef _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5311  typedef _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
5312 
5313  static const bool _TakesProgress = true;
5314  static const bool _TakesToken = _TakesToken;
5315  };
5316 
5317  template<typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
5318  struct _AsyncAttributes<_ProgressType, _ReturnType, _TaskTraits, _TakesToken, false>
5319  {
5320  typedef Windows::Foundation::IAsyncOperation<_ReturnType> _AsyncBaseType;
5321  typedef _Zip _ProgressDelegateType;
5322  typedef Windows::Foundation::AsyncOperationCompletedHandler<_ReturnType> _CompletionDelegateType;
5323  typedef _ReturnType _ReturnType;
5324  typedef _ProgressType _ProgressType;
5325  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5326  typedef _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5327  typedef _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
5328 
5329  static const bool _TakesProgress = false;
5330  static const bool _TakesToken = _TakesToken;
5331  };
5332 
5333  template<typename _ProgressType, typename _TaskTraits, bool _TakesToken>
5334  struct _AsyncAttributes<_ProgressType, void, _TaskTraits, _TakesToken, true>
5335  {
5336  typedef Windows::Foundation::IAsyncActionWithProgress<_ProgressType> _AsyncBaseType;
5337  typedef Windows::Foundation::AsyncActionProgressHandler<_ProgressType> _ProgressDelegateType;
5338  typedef Windows::Foundation::AsyncActionWithProgressCompletedHandler<_ProgressType> _CompletionDelegateType;
5339  typedef void _ReturnType;
5340  typedef _ProgressType _ProgressType;
5341  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5342  typedef _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5343  typedef _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
5344 
5345  static const bool _TakesProgress = true;
5346  static const bool _TakesToken = _TakesToken;
5347  };
5348 
5349  template<typename _ProgressType, typename _TaskTraits, bool _TakesToken>
5350  struct _AsyncAttributes<_ProgressType, void, _TaskTraits, _TakesToken, false>
5351  {
5352  typedef Windows::Foundation::IAsyncAction _AsyncBaseType;
5353  typedef _Zip _ProgressDelegateType;
5354  typedef Windows::Foundation::AsyncActionCompletedHandler _CompletionDelegateType;
5355  typedef void _ReturnType;
5356  typedef _ProgressType _ProgressType;
5357  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5358  typedef _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5359  typedef _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
5360 
5361  static const bool _TakesProgress = false;
5362  static const bool _TakesToken = _TakesToken;
5363  };
5364 
5365  template<typename _Function>
5366  struct _AsyncLambdaTypeTraits
5367  {
5368  typedef typename _FunctorTypeTraits<_Function>::_ReturnType _ReturnType;
5369  typedef typename _FunctorTypeTraits<_Function>::_Argument1Type _Argument1Type;
5370  typedef typename _CAFunctorOptions<_Function>::_ProgressType _ProgressType;
5371 
5372  static const bool _TakesProgress = _CAFunctorOptions<_Function>::_TakesProgress;
5373  static const bool _TakesToken = _CAFunctorOptions<_Function>::_TakesToken;
5374 
5375  typedef _TaskTypeTraits<_ReturnType> _TaskTraits;
5376  typedef _AsyncAttributes<_ProgressType, typename _TaskTraits::_TaskRetType, _TaskTraits, _TakesToken, _TakesProgress> _AsyncAttributes;
5377  };
5378 
5379  struct _AsyncAttributesTaskGenerator
5380  {
5381  // _Generate_Task : A function adapting the user's function into what's necessary to produce the appropriate task
5382  template<typename _Function, typename _ClassPtr, typename _AsyncAttributesT>
5383  static task<typename _AsyncAttributesT::_ReturnType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5384  {
5385  return _AsyncAttributesT::_TaskGenerator::_GenerateTask<_Function, _ClassPtr, _AsyncAttributesT::_ProgressType>(_Func, _Ptr, _Cts, _callstack);
5386  }
5387  };
5388 
5389  // ***************************************************************************
5390  // AsyncInfo (and completion) Layer:
5391  //
5392 
5393  //
5394  // Internal base class implementation for async operations (based on internal Windows representation for ABI level async operations)
5395  //
5396  template < typename _Attributes, _AsyncResultType _ResultType = SingleResult >
5397  ref class _AsyncInfoBase abstract : _Attributes::_AsyncBaseType
5398  {
5399  internal:
5400 
5401  _AsyncInfoBase() :
5402  _M_currentStatus(_AsyncStatusInternal::_AsyncCreated),
5403  _M_errorCode(S_OK),
5404  _M_completeDelegate(nullptr),
5405  _M_CompleteDelegateAssigned(0),
5406  _M_CallbackMade(0)
5407  {
5409  }
5410 
5411  public:
5412  virtual typename _Attributes::_ReturnType GetResults()
5413  {
5414  throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5415  }
5416 
5417  virtual property unsigned int Id
5418  {
5419  unsigned int get()
5420  {
5421  _CheckValidStateForAsyncInfoCall();
5422 
5423  return _M_id;
5424  }
5425 
5426  void set(unsigned int id)
5427  {
5428  _CheckValidStateForAsyncInfoCall();
5429 
5430  if (id == 0)
5431  {
5432  throw ::Platform::Exception::CreateException(E_INVALIDARG);
5433  }
5434  else if (_M_currentStatus != _AsyncStatusInternal::_AsyncCreated)
5435  {
5436  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5437  }
5438 
5439  _M_id = id;
5440  }
5441  }
5442 
5443  virtual property Windows::Foundation::AsyncStatus Status
5444  {
5445  Windows::Foundation::AsyncStatus get()
5446  {
5447  _CheckValidStateForAsyncInfoCall();
5448 
5449  _AsyncStatusInternal _Current = _M_currentStatus;
5450 
5451  //
5452  // Map our internal cancel pending to cancelled. This way "pending cancelled" looks to the outside as "cancelled" but
5453  // can still transition to "completed" if the operation completes without acknowledging the cancellation request
5454  //
5455  switch(_Current)
5456  {
5457  case _AsyncCancelPending:
5458  _Current = _AsyncCanceled;
5459  break;
5460  case _AsyncCreated:
5461  _Current = _AsyncStarted;
5462  break;
5463  default:
5464  break;
5465  }
5466 
5467  return static_cast<Windows::Foundation::AsyncStatus>(_Current);
5468  }
5469  }
5470 
5471  virtual property Windows::Foundation::HResult ErrorCode
5472  {
5473  Windows::Foundation::HResult get()
5474  {
5475  _CheckValidStateForAsyncInfoCall();
5476 
5477  Windows::Foundation::HResult _Hr;
5478  _Hr.Value = _M_errorCode;
5479  return _Hr;
5480  }
5481  }
5482 
5483  virtual property typename _Attributes::_ProgressDelegateType^ Progress
5484  {
5485  typename typename _Attributes::_ProgressDelegateType^ get()
5486  {
5487  return _GetOnProgress();
5488  }
5489 
5490  void set(typename _Attributes::_ProgressDelegateType^ _ProgressHandler)
5491  {
5492  _PutOnProgress(_ProgressHandler);
5493  }
5494  }
5495 
5496  virtual void Cancel()
5497  {
5498  if (_TransitionToState(_AsyncCancelPending))
5499  {
5500  _OnCancel();
5501  }
5502  }
5503 
5504  virtual void Close()
5505  {
5506  if (_TransitionToState(_AsyncClosed))
5507  {
5508  _OnClose();
5509  }
5510  else
5511  {
5512  if (_M_currentStatus != _AsyncClosed) // Closed => Closed transition is just ignored
5513  {
5514  throw ::Platform::Exception::CreateException(E_ILLEGAL_STATE_CHANGE);
5515  }
5516  }
5517  }
5518 
5519  virtual property typename _Attributes::_CompletionDelegateType^ Completed
5520  {
5521  typename _Attributes::_CompletionDelegateType^ get()
5522  {
5523  _CheckValidStateForDelegateCall();
5524  return _M_completeDelegate;
5525  }
5526 
5527  void set(typename _Attributes::_CompletionDelegateType^ _CompleteHandler)
5528  {
5529  _CheckValidStateForDelegateCall();
5530  // this delegate property is "write once"
5531  if (InterlockedIncrement(&_M_CompleteDelegateAssigned) == 1)
5532  {
5533  _M_completeDelegateContext = _ContextCallback::_CaptureCurrent();
5534  _M_completeDelegate = _CompleteHandler;
5535  // Guarantee that the write of _M_completeDelegate is ordered with respect to the read of state below
5536  // as perceived from _FireCompletion on another thread.
5537  MemoryBarrier();
5538  if (_IsTerminalState())
5539  {
5540  _FireCompletion();
5541  }
5542  }
5543  else
5544  {
5545  throw ::Platform::Exception::CreateException(E_ILLEGAL_DELEGATE_ASSIGNMENT);
5546  }
5547  }
5548  }
5549 
5550 
5551  protected private:
5552 
5553  // _Start - this is not externally visible since async operations "hot start" before returning to the caller
5554  void _Start()
5555  {
5556  if (_TransitionToState(_AsyncStarted))
5557  {
5558  _OnStart();
5559  }
5560  else
5561  {
5562  throw ::Platform::Exception::CreateException(E_ILLEGAL_STATE_CHANGE);
5563  }
5564  }
5565 
5566 
5567  void _FireCompletion()
5568  {
5569  _TryTransitionToCompleted();
5570 
5571  // we guarantee that completion can only ever be fired once
5572  if (_M_completeDelegate != nullptr && InterlockedIncrement(&_M_CallbackMade) == 1)
5573  {
5574  _M_completeDelegateContext._CallInContext([=] {
5575 
5576  try
5577  {
5578  _M_completeDelegate((_Attributes::_AsyncBaseType^)this, this->Status);
5579  _M_completeDelegate = nullptr;
5580  }
5581  catch(::Platform::Exception^ _ex)
5582  {
5583  // Null out the delegate since something went wrong when calling it
5584  _M_completeDelegate = nullptr;
5585  if (!_IsHRCOMDisconnected(_ex->HResult))
5586  {
5587  throw;
5588  }
5589  }
5590  }, true); // Ignore COM disconnection error
5591  }
5592  }
5593 
5594  virtual typename _Attributes::_ProgressDelegateType^ _GetOnProgress()
5595  {
5596  throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5597  }
5598 
5599  virtual void _PutOnProgress(typename _Attributes::_ProgressDelegateType^ _ProgressHandler)
5600  {
5601  throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5602  }
5603 
5604  bool _TryTransitionToCompleted()
5605  {
5606  return _TransitionToState(_AsyncStatusInternal::_AsyncCompleted);
5607  }
5608 
5609  bool _TryTransitionToCancelled()
5610  {
5611  return _TransitionToState(_AsyncStatusInternal::_AsyncCanceled);
5612  }
5613 
5614  bool _TryTransitionToError(const HRESULT error)
5615  {
5616  _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_errorCode), error, S_OK);
5617  return _TransitionToState(_AsyncStatusInternal::_AsyncError);
5618  }
5619 
5620  // This method checks to see if the delegate properties can be
5621  // modified in the current state and generates the appropriate
5622  // error hr in the case of violation.
5623  inline void _CheckValidStateForDelegateCall()
5624  {
5625  if (_M_currentStatus == _AsyncClosed)
5626  {
5627  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5628  }
5629  }
5630 
5631  // This method checks to see if results can be collected in the
5632  // current state and generates the appropriate error hr in
5633  // the case of a violation.
5634  inline void _CheckValidStateForResultsCall()
5635  {
5636  _AsyncStatusInternal _Current = _M_currentStatus;
5637 
5638  if (_Current == _AsyncError)
5639  {
5640  throw ::Platform::Exception::CreateException(_M_errorCode);
5641  }
5642 #pragma warning(push)
5643 #pragma warning(disable: 4127) // Conditional expression is constant
5644  // single result illegal before transition to Completed or Cancelled state
5645  if (_ResultType == SingleResult)
5646 #pragma warning(pop)
5647  {
5648  if (_Current != _AsyncCompleted)
5649  {
5650  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5651  }
5652  }
5653  // multiple results can be called after Start has been called and before/after Completed
5654  else if (_Current != _AsyncStarted &&
5655  _Current != _AsyncCancelPending &&
5656  _Current != _AsyncCanceled &&
5657  _Current != _AsyncCompleted)
5658  {
5659  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5660  }
5661  }
5662 
5663  // This method can be called by derived classes periodically to determine
5664  // whether the asynchronous operation should continue processing or should
5665  // be halted.
5666  inline bool _ContinueAsyncOperation()
5667  {
5668  return (_M_currentStatus == _AsyncStarted);
5669  }
5670 
5671  // These two methods are used to allow the async worker implementation do work on
5672  // state transitions. No real "work" should be done in these methods. In other words
5673  // they should not block for a long time on UI timescales.
5674  virtual void _OnStart() = 0;
5675  virtual void _OnClose() = 0;
5676  virtual void _OnCancel() = 0;
5677 
5678  private:
5679 
5680  // This method is used to check if calls to the AsyncInfo properties
5681  // (id, status, errorcode) are legal in the current state. It also
5682  // generates the appropriate error hr to return in the case of an
5683  // illegal call.
5684  inline void _CheckValidStateForAsyncInfoCall()
5685  {
5686  _AsyncStatusInternal _Current = _M_currentStatus;
5687  if (_Current == _AsyncClosed)
5688  {
5689  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5690  }
5691  else if (_Current == _AsyncCreated)
5692  {
5693  throw ::Platform::Exception::CreateException(E_ASYNC_OPERATION_NOT_STARTED);
5694  }
5695 
5696  }
5697 
5698  inline bool _TransitionToState(const _AsyncStatusInternal _NewState)
5699  {
5700  _AsyncStatusInternal _Current = _M_currentStatus;
5701 
5702  // This enforces the valid state transitions of the asynchronous worker object
5703  // state machine.
5704  switch(_NewState)
5705  {
5706  case _AsyncStatusInternal::_AsyncStarted:
5707  if (_Current != _AsyncCreated)
5708  {
5709  return false;
5710  }
5711  break;
5712  case _AsyncStatusInternal::_AsyncCompleted:
5713  if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
5714  {
5715  return false;
5716  }
5717  break;
5718  case _AsyncStatusInternal::_AsyncCancelPending:
5719  if (_Current != _AsyncStarted)
5720  {
5721  return false;
5722  }
5723  break;
5724  case _AsyncStatusInternal::_AsyncCanceled:
5725  if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
5726  {
5727  return false;
5728  }
5729  break;
5730  case _AsyncStatusInternal::_AsyncError:
5731  if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
5732  {
5733  return false;
5734  }
5735  break;
5736  case _AsyncStatusInternal::_AsyncClosed:
5737  if (!_IsTerminalState(_Current))
5738  {
5739  return false;
5740  }
5741  break;
5742  default:
5743  return false;
5744  break;
5745  }
5746 
5747  // attempt the transition to the new state
5748  // Note: if currentStatus_ == _Current, then there was no intervening write
5749  // by the async work object and the swap succeeded.
5750  _AsyncStatusInternal _RetState = static_cast<_AsyncStatusInternal>(
5751  _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_currentStatus),
5752  _NewState,
5753  static_cast<LONG>(_Current)));
5754 
5755  // ICE returns the former state, if the returned state and the
5756  // state we captured at the beginning of this method are the same,
5757  // the swap succeeded.
5758  return (_RetState == _Current);
5759  }
5760 
5761  inline bool _IsTerminalState()
5762  {
5763  return _IsTerminalState(_M_currentStatus);
5764  }
5765 
5766  inline bool _IsTerminalState(_AsyncStatusInternal status)
5767  {
5768  return (status == _AsyncError ||
5769  status == _AsyncCanceled ||
5770  status == _AsyncCompleted ||
5771  status == _AsyncClosed);
5772  }
5773 
5774  private:
5775 
5776  _ContextCallback _M_completeDelegateContext;
5777  typename _Attributes::_CompletionDelegateType^ volatile _M_completeDelegate;
5778  _AsyncStatusInternal volatile _M_currentStatus;
5779  HRESULT volatile _M_errorCode;
5780  unsigned int _M_id;
5781  long volatile _M_CompleteDelegateAssigned;
5782  long volatile _M_CallbackMade;
5783  };
5784 
5785  // ***************************************************************************
5786  // Progress Layer (optional):
5787  //
5788 
5789  // __declspec(no_empty_identity_interface) is used to suppress generation of WinRT
5790  // default functions (e.g. QueryInterface, AddRef, etc). _AsyncProgressBase is never
5791  // used directly, so generation of WinRT functions is not needed and unnecessarily
5792  // increases generated code size.
5793 
5794  template< typename _Attributes, bool _HasProgress, _AsyncResultType _ResultType = SingleResult >
5795  ref class __declspec(no_empty_identity_interface) _AsyncProgressBase abstract : _AsyncInfoBase<_Attributes, _ResultType>
5796  {
5797  };
5798 
5799  template< typename _Attributes, _AsyncResultType _ResultType>
5800  ref class __declspec(no_empty_identity_interface) _AsyncProgressBase<_Attributes, true, _ResultType> abstract : _AsyncInfoBase<_Attributes, _ResultType>
5801  {
5802  internal:
5803 
5804  _AsyncProgressBase() : _AsyncInfoBase<_Attributes, _ResultType>(),
5805  _M_progressDelegate(nullptr)
5806  {
5807  }
5808 
5809  virtual typename _Attributes::_ProgressDelegateType^ _GetOnProgress() override
5810  {
5811  _CheckValidStateForDelegateCall();
5812  return _M_progressDelegate;
5813  }
5814 
5815  virtual void _PutOnProgress(typename _Attributes::_ProgressDelegateType^ _ProgressHandler) override
5816  {
5817  _CheckValidStateForDelegateCall();
5818  _M_progressDelegate = _ProgressHandler;
5819  _M_progressDelegateContext = _ContextCallback::_CaptureCurrent();
5820  }
5821 
5822  void _FireProgress(const typename _Attributes::_ProgressType& _ProgressValue)
5823  {
5824  if (_M_progressDelegate != nullptr)
5825  {
5826  _M_progressDelegateContext._CallInContext([=] {
5827  try
5828  {
5829  _M_progressDelegate((_Attributes::_AsyncBaseType^)this, _ProgressValue);
5830  }
5831  catch(::Platform::Exception^ _ex)
5832  {
5833  // Null out the delegate since something went wrong when calling it
5834  _M_progressDelegate = nullptr;
5835  if (!_IsHRCOMDisconnected(_ex->HResult))
5836  {
5837  throw;
5838  }
5839  }
5840  }, true); // Ignore COM disconnection error
5841  }
5842  }
5843 
5844  private:
5845 
5846  _ContextCallback _M_progressDelegateContext;
5847  typename _Attributes::_ProgressDelegateType^ _M_progressDelegate;
5848  };
5849 
5850  // ***************************************************************************
5851  // Async Creation Layer:
5852  //
5853  template<typename _Function>
5854  ref class _AsyncTaskGeneratorThunk sealed : _AsyncProgressBase<typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes,
5855  _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes::_TakesProgress>
5856  {
5857  internal:
5858 
5859  typedef typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes _Attributes;
5860  typedef typename _Attributes::_AsyncBaseType _AsyncBaseType;
5861 
5862  _AsyncTaskGeneratorThunk(const _Function& _Func, const _TaskCreationCallstack &_callstack) : _M_func(_Func), _M_creationCallstack(_callstack)
5863  {
5864  // Virtual call here is safe as the class is declared 'sealed'
5865  _Start();
5866  }
5867 
5868  public:
5869 
5870  virtual typename _Attributes::_ReturnType GetResults() override
5871  {
5872  _CheckValidStateForResultsCall();
5873  return _M_task.get();
5874  }
5875 
5876  protected:
5877 
5878  //
5879  // The only thing we must do different from the base class is we must spin the hot task on transition from Created->Started. Otherwise,
5880  // let the base thunk handle everything.
5881  //
5882 
5883  virtual void _OnStart() override
5884  {
5885  //
5886  // Call the appropriate task generator to actually produce a task of the expected type. This might adapt the user lambda for progress reports,
5887  // wrap the return result in a task, or allow for direct return of a task depending on the form of the lambda.
5888  //
5889  _M_task = _AsyncAttributesTaskGenerator::_Generate_Task<_Function, _AsyncTaskGeneratorThunk<_Function>^, _Attributes>(_M_func, this, _M_cts, _M_creationCallstack);
5890  _M_task.then([=](task<typename _Attributes::_ReturnType> _Antecedent) {
5891  try
5892  {
5893  _Antecedent.get();
5894  }
5895  catch (task_canceled&)
5896  {
5897  _TryTransitionToCancelled();
5898  }
5899  catch (::Platform::Exception^ _Ex)
5900  {
5901  _TryTransitionToError(_Ex->HResult);
5902  }
5903  catch (...)
5904  {
5905  _TryTransitionToError(E_FAIL);
5906  }
5907  _FireCompletion();
5908  });
5909  }
5910 
5911  virtual void _OnCancel() override
5912  {
5913  _M_cts.cancel();
5914  }
5915 
5916  virtual void _OnClose() override
5917  {
5918  }
5919 
5920  private:
5921 
5922  task<typename _Attributes::_ReturnType> _M_task;
5923  cancellation_token_source _M_cts;
5924  _TaskCreationCallstack _M_creationCallstack;
5925  _Function _M_func;
5926  };
5927 } // namespace details
5928 
5968 
5969 template<typename _Function>
5970 __declspec(noinline)
5971 details::_AsyncTaskGeneratorThunk<_Function> ^create_async(const _Function& _Func)
5972 {
5973  static_assert(std::is_same<decltype(details::_IsValidCreateAsync(_Func,0,0,0,0)),std::true_type>::value,
5974  "argument to create_async must be a callable object taking zero, one or two arguments");
5975 
5976 
5977 
5978  return ref new details::_AsyncTaskGeneratorThunk<_Function>(_Func, _CAPTURE_CALLSTACK());
5979 }
5980 
5981 #endif /* defined (__cplusplus_winrt) */
5982 
5983 namespace details
5984 {
5985  // Helper struct for when_all operators to know when tasks have completed
5986  template<typename _Type>
5987  struct _RunAllParam
5988  {
5989  _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
5990  {
5991  }
5992 
5993  void _Resize(size_t _Len, bool _SkipVector = false)
5994  {
5995  _M_numTasks = _Len;
5996  if (!_SkipVector)
5997  {
5998  _M_vector._Result.resize(_Len);
5999  }
6000  }
6001 
6002  task_completion_event<_Unit_type> _M_completed;
6003  _ResultHolder<std::vector<_Type> > _M_vector;
6004  _ResultHolder<_Type> _M_mergeVal;
6005  atomic_size_t _M_completeCount;
6006  size_t _M_numTasks;
6007  };
6008 
6009  template<typename _Type>
6010  struct _RunAllParam<std::vector<_Type> >
6011  {
6012  _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
6013  {
6014  }
6015 
6016  void _Resize(size_t _Len, bool _SkipVector = false)
6017  {
6018  _M_numTasks = _Len;
6019 
6020  if (!_SkipVector)
6021  {
6022  _M_vector.resize(_Len);
6023  }
6024  }
6025 
6026  task_completion_event<_Unit_type> _M_completed;
6027  std::vector<_ResultHolder<std::vector<_Type> > > _M_vector;
6028  atomic_size_t _M_completeCount;
6029  size_t _M_numTasks;
6030  };
6031 
6032  // Helper struct specialization for void
6033  template<>
6034  struct _RunAllParam<_Unit_type>
6035  {
6036  _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
6037  {
6038  }
6039 
6040  void _Resize(size_t _Len)
6041  {
6042  _M_numTasks = _Len;
6043  }
6044 
6045  task_completion_event<_Unit_type> _M_completed;
6046  atomic_size_t _M_completeCount;
6047  size_t _M_numTasks;
6048  };
6049 
6050  inline void _JoinAllTokens_Add(const cancellation_token_source& _MergedSrc, _CancellationTokenState *_PJoinedTokenState)
6051  {
6052  if (_PJoinedTokenState != nullptr && _PJoinedTokenState != _CancellationTokenState::_None())
6053  {
6054  cancellation_token _T = cancellation_token::_FromImpl(_PJoinedTokenState);
6055  _T.register_callback( [=](){
6056  _MergedSrc.cancel();
6057  });
6058  }
6059  }
6060 
6061  template<typename _ElementType, typename _Function, typename _TaskType>
6062  void _WhenAllContinuationWrapper(_RunAllParam<_ElementType>* _PParam, _Function _Func, task<_TaskType>& _Task)
6063  {
6064  if (_Task._GetImpl()->_IsCompleted())
6065  {
6066  _Func();
6067  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6068  {
6069  // Inline execute its direct continuation, the _ReturnTask
6070  _PParam->_M_completed.set(_Unit_type());
6071  // It's safe to delete it since all usage of _PParam in _ReturnTask has been finished.
6072  delete _PParam;
6073  }
6074  }
6075  else
6076  {
6077  _ASSERTE(_Task._GetImpl()->_IsCanceled());
6078  if (_Task._GetImpl()->_HasUserException())
6079  {
6080  // _Cancel will return false if the TCE is already canceled with or without exception
6081  if (!_PParam->_M_completed._Cancel(_Task._GetImpl()->_GetExceptionHolder()))
6082  {
6083  atomic_exchange(_Task._GetImpl()->_GetExceptionHolder()->_M_exceptionObserved, 1l);
6084  }
6085  }
6086  else
6087  {
6088  _PParam->_M_completed._Cancel();
6089  }
6090 
6091  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6092  {
6093  delete _PParam;
6094  }
6095  }
6096  }
6097 
6098  template<typename _ElementType, typename _Iterator>
6099  struct _WhenAllImpl
6100  {
6101  static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6102  {
6103  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6104 
6105  auto _PParam = new _RunAllParam<_ElementType>();
6106  cancellation_token_source _MergedSource;
6107 
6108  // Step1: Create task completion event.
6109  task_options _Options(_TaskOptions);
6110  _Options.set_cancellation_token(_MergedSource.get_token());
6111  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6112  // The return task must be created before step 3 to enforce inline execution.
6113  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> std::vector<_ElementType> {
6114  return _PParam->_M_vector.Get();
6115  }, nullptr);
6116 
6117  // Step2: Combine and check tokens, and count elements in range.
6118  if (_PTokenState)
6119  {
6120  _JoinAllTokens_Add(_MergedSource, _PTokenState);
6121  _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6122  }
6123  else
6124  {
6125  size_t _TaskNum = 0;
6126  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6127  {
6128  _TaskNum++;
6129  _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6130  }
6131  _PParam->_Resize(_TaskNum);
6132  }
6133 
6134  // Step3: Check states of previous tasks.
6135  if( _Begin == _End )
6136  {
6137  _PParam->_M_completed.set(_Unit_type());
6138  delete _PParam;
6139  }
6140  else
6141  {
6142  size_t _Index = 0;
6143  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6144  {
6145  if (_PTask->is_apartment_aware())
6146  {
6147  _ReturnTask._SetAsync();
6148  }
6149 
6150  _PTask->_Then([_PParam, _Index](task<_ElementType> _ResultTask) {
6151 
6152  // Dev10 compiler bug
6153  typedef _ElementType _ElementTypeDev10;
6154  auto _PParamCopy = _PParam;
6155  auto _IndexCopy = _Index;
6156  auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask](){
6157  _PParamCopy->_M_vector._Result[_IndexCopy] = _ResultTask._GetImpl()->_GetResult();
6158  };
6159 
6160  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6162 
6163  _Index++;
6164  }
6165  }
6166 
6167  return _ReturnTask;
6168  }
6169  };
6170 
6171  template<typename _ElementType, typename _Iterator>
6172  struct _WhenAllImpl<std::vector<_ElementType>, _Iterator>
6173  {
6174  static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6175  {
6176  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6177 
6178  auto _PParam = new _RunAllParam<std::vector<_ElementType>>();
6179  cancellation_token_source _MergedSource;
6180 
6181  // Step1: Create task completion event.
6182  task_options _Options(_TaskOptions);
6183  _Options.set_cancellation_token(_MergedSource.get_token());
6184  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6185  // The return task must be created before step 3 to enforce inline execution.
6186  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> std::vector<_ElementType> {
6187  _ASSERTE(_PParam->_M_completeCount == _PParam->_M_numTasks);
6188  std::vector<_ElementType> _Result;
6189  for(size_t _I = 0; _I < _PParam->_M_numTasks; _I++)
6190  {
6191  const std::vector<_ElementType>& _Vec = _PParam->_M_vector[_I].Get();
6192  _Result.insert(_Result.end(), _Vec.begin(), _Vec.end());
6193  }
6194  return _Result;
6195  }, nullptr);
6196 
6197  // Step2: Combine and check tokens, and count elements in range.
6198  if (_PTokenState)
6199  {
6200  _JoinAllTokens_Add(_MergedSource, _PTokenState);
6201  _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6202  }
6203  else
6204  {
6205  size_t _TaskNum = 0;
6206  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6207  {
6208  _TaskNum++;
6209  _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6210  }
6211  _PParam->_Resize(_TaskNum);
6212  }
6213 
6214  // Step3: Check states of previous tasks.
6215  if( _Begin == _End )
6216  {
6217  _PParam->_M_completed.set(_Unit_type());
6218  delete _PParam;
6219  }
6220  else
6221  {
6222  size_t _Index = 0;
6223  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6224  {
6225  if (_PTask->is_apartment_aware())
6226  {
6227  _ReturnTask._SetAsync();
6228  }
6229 
6230  _PTask->_Then([_PParam, _Index](task<std::vector<_ElementType>> _ResultTask) {
6231  // Dev10 compiler bug
6232  typedef _ElementType _ElementTypeDev10;
6233  auto _PParamCopy = _PParam;
6234  auto _IndexCopy = _Index;
6235  auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask]() {
6236  _PParamCopy->_M_vector[_IndexCopy].Set(_ResultTask._GetImpl()->_GetResult());
6237  };
6238 
6239  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6241 
6242  _Index++;
6243  }
6244  }
6245 
6246  return _ReturnTask;
6247  }
6248  };
6249 
6250  template<typename _Iterator>
6251  struct _WhenAllImpl<void, _Iterator>
6252  {
6253  static task<void> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6254  {
6255  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6256 
6257  auto _PParam = new _RunAllParam<_Unit_type>();
6258  cancellation_token_source _MergedSource;
6259 
6260  // Step1: Create task completion event.
6261  task_options _Options(_TaskOptions);
6262  _Options.set_cancellation_token(_MergedSource.get_token());
6263  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6264  // The return task must be created before step 3 to enforce inline execution.
6265  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) {
6266  }, nullptr);
6267 
6268  // Step2: Combine and check tokens, and count elements in range.
6269  if (_PTokenState)
6270  {
6271  _JoinAllTokens_Add(_MergedSource, _PTokenState);
6272  _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6273  }
6274  else
6275  {
6276  size_t _TaskNum = 0;
6277  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6278  {
6279  _TaskNum++;
6280  _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6281  }
6282  _PParam->_Resize(_TaskNum);
6283  }
6284 
6285  // Step3: Check states of previous tasks.
6286  if( _Begin == _End )
6287  {
6288  _PParam->_M_completed.set(_Unit_type());
6289  delete _PParam;
6290  }
6291  else
6292  {
6293  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6294  {
6295  if (_PTask->is_apartment_aware())
6296  {
6297  _ReturnTask._SetAsync();
6298  }
6299 
6300  _PTask->_Then([_PParam](task<void> _ResultTask) {
6301  auto _Func = [](){};
6302  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6304  }
6305  }
6306 
6307  return _ReturnTask;
6308  }
6309  };
6310 
6311  template<typename _ReturnType>
6312  task<std::vector<_ReturnType>> _WhenAllVectorAndValue(const task<std::vector<_ReturnType>>& _VectorTask, const task<_ReturnType>& _ValueTask,
6313  bool _OutputVectorFirst)
6314  {
6315  auto _PParam = new _RunAllParam<_ReturnType>();
6316  cancellation_token_source _MergedSource;
6317 
6318  // Step1: Create task completion event.
6319  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
6320  // The return task must be created before step 3 to enforce inline execution.
6321  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> std::vector<_ReturnType> {
6322  _ASSERTE(_PParam->_M_completeCount == 2);
6323  auto _Result = _PParam->_M_vector.Get(); // copy by value
6324  auto _mergeVal = _PParam->_M_mergeVal.Get();
6325 
6326  if (_OutputVectorFirst == true)
6327  {
6328  _Result.push_back(_mergeVal);
6329  }
6330  else
6331  {
6332  _Result.insert(_Result.begin(), _mergeVal);
6333  }
6334  return _Result;
6335  }, nullptr);
6336 
6337  // Step2: Combine and check tokens.
6338  _JoinAllTokens_Add(_MergedSource, _VectorTask._GetImpl()->_M_pTokenState);
6339  _JoinAllTokens_Add(_MergedSource, _ValueTask._GetImpl()->_M_pTokenState);
6340 
6341  // Step3: Check states of previous tasks.
6342  _PParam->_Resize(2, true);
6343 
6344  if (_VectorTask.is_apartment_aware() || _ValueTask.is_apartment_aware())
6345  {
6346  _ReturnTask._SetAsync();
6347  }
6348  _VectorTask._Then([_PParam](task<std::vector<_ReturnType>> _ResultTask) {
6349  // Dev10 compiler bug
6350  typedef _ReturnType _ReturnTypeDev10;
6351  auto _PParamCopy = _PParam;
6352  auto _Func = [_PParamCopy, &_ResultTask]() {
6353  auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
6354  _PParamCopy->_M_vector.Set(_ResultLocal);
6355  };
6356 
6357  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6359  _ValueTask._Then([_PParam](task<_ReturnType> _ResultTask) {
6360  // Dev10 compiler bug
6361  typedef _ReturnType _ReturnTypeDev10;
6362  auto _PParamCopy = _PParam;
6363  auto _Func = [_PParamCopy, &_ResultTask]() {
6364  auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
6365  _PParamCopy->_M_mergeVal.Set(_ResultLocal);
6366  };
6367 
6368  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6370 
6371  return _ReturnTask;
6372  }
6373 } // namespace details
6374 
6397 
6398 template <typename _Iterator>
6399 auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
6400  -> decltype (details::_WhenAllImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End))
6401 {
6402  typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
6403  return details::_WhenAllImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
6404 }
6405 
6430 
6431 template<typename _ReturnType>
6432 task<std::vector<_ReturnType>> operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs)
6433 {
6434  task<_ReturnType> _PTasks[2] = {_Lhs, _Rhs};
6435  return when_all(_PTasks, _PTasks+2);
6436 }
6437 
6462 
6463 template<typename _ReturnType>
6464 task<std::vector<_ReturnType>> operator&&(const task<std::vector<_ReturnType>> & _Lhs, const task<_ReturnType> & _Rhs)
6465 {
6466  return details::_WhenAllVectorAndValue(_Lhs, _Rhs, true);
6467 }
6468 
6493 
6494 template<typename _ReturnType>
6495 task<std::vector<_ReturnType>> operator&&(const task<_ReturnType> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
6496 {
6497  return details::_WhenAllVectorAndValue(_Rhs, _Lhs, false);
6498 }
6499 
6524 
6525 template<typename _ReturnType>
6526 task<std::vector<_ReturnType>> operator&&(const task<std::vector<_ReturnType>> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
6527 {
6528  task<std::vector<_ReturnType>> _PTasks[2] = {_Lhs, _Rhs};
6529  return when_all(_PTasks, _PTasks+2);
6530 }
6531 
6556 
6557 inline task<void> operator&&(const task<void> & _Lhs, const task<void> & _Rhs)
6558 {
6559  task<void> _PTasks[2] = {_Lhs, _Rhs};
6560  return when_all(_PTasks, _PTasks+2);
6561 }
6562 
6563 namespace details
6564 {
6565  // Helper struct for when_any operators to know when tasks have completed
6566  template <typename _CompletionType>
6567  struct _RunAnyParam
6568  {
6569  _RunAnyParam() : _M_exceptionRelatedToken(nullptr), _M_completeCount(0), _M_numTasks(0), _M_fHasExplicitToken(false)
6570  {
6571  }
6572  ~_RunAnyParam()
6573  {
6574  if (_CancellationTokenState::_IsValid(_M_exceptionRelatedToken))
6575  _M_exceptionRelatedToken->_Release();
6576  }
6577  task_completion_event<_CompletionType> _M_Completed;
6578  cancellation_token_source _M_cancellationSource;
6579  _CancellationTokenState * _M_exceptionRelatedToken;
6580  atomic_size_t _M_completeCount;
6581  size_t _M_numTasks;
6582  bool _M_fHasExplicitToken;
6583  };
6584 
6585  template<typename _CompletionType, typename _Function, typename _TaskType>
6586  void _WhenAnyContinuationWrapper(_RunAnyParam<_CompletionType> * _PParam, const _Function & _Func, task<_TaskType>& _Task)
6587  {
6588  bool _IsTokenCanceled = !_PParam->_M_fHasExplicitToken && _Task._GetImpl()->_M_pTokenState != _CancellationTokenState::_None() && _Task._GetImpl()->_M_pTokenState->_IsCanceled();
6589  if (_Task._GetImpl()->_IsCompleted() && !_IsTokenCanceled)
6590  {
6591  _Func();
6592  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6593  {
6594  _PParam->_M_Completed._ClearStoredException();
6595  delete _PParam;
6596  }
6597  }
6598  else
6599  {
6600  _ASSERTE(_Task._GetImpl()->_IsCanceled() || _IsTokenCanceled);
6601  if (_Task._GetImpl()->_HasUserException())
6602  {
6603  if (!_IsTokenCanceled && _PParam->_M_Completed._StoreException(_Task._GetImpl()->_GetExceptionHolder()))
6604  {
6605  // This can only enter once.
6606  _PParam->_M_exceptionRelatedToken = _Task._GetImpl()->_M_pTokenState;
6607  _ASSERTE(_PParam->_M_exceptionRelatedToken);
6608  // Deref token will be done in the _PParam destructor.
6609  if (_PParam->_M_exceptionRelatedToken != _CancellationTokenState::_None())
6610  {
6611  _PParam->_M_exceptionRelatedToken->_Reference();
6612  }
6613  }
6614  else
6615  {
6616  // Observe exceptions that not picked
6617  atomic_exchange(_Task._GetImpl()->_GetExceptionHolder()->_M_exceptionObserved, 1l);
6618  }
6619  }
6620 
6621  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6622  {
6623  // If no one has be completed so far, we need to make some final cancellation decision.
6624  if (!_PParam->_M_Completed._IsTriggered())
6625  {
6626  // If we already explicit token, we can skip the token join part.
6627  if (!_PParam->_M_fHasExplicitToken)
6628  {
6629  if (_PParam->_M_exceptionRelatedToken)
6630  {
6631  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PParam->_M_exceptionRelatedToken);
6632  }
6633  else
6634  {
6635  // If haven't captured any exception token yet, there was no exception for all those tasks,
6636  // so just pick a random token (current one) for normal cancellation.
6637  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _Task._GetImpl()->_M_pTokenState);
6638  }
6639  }
6640  // Do exception cancellation or normal cancellation based on whether it has stored exception.
6641  _PParam->_M_Completed._Cancel();
6642  }
6643  else
6644  _PParam->_M_Completed._ClearStoredException();
6645  delete _PParam;
6646  }
6647  }
6648  }
6649 
6650  template<typename _ElementType, typename _Iterator>
6651  struct _WhenAnyImpl
6652  {
6653  static task<std::pair<_ElementType, size_t>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6654  {
6655  if( _Begin == _End )
6656  {
6657  _THROW_NCEE(invalid_operation, "when_any(begin, end) cannot be called on an empty container.");
6658  }
6659  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6660  auto _PParam = new _RunAnyParam<std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState *>>();
6661 
6662  if (_PTokenState)
6663  {
6664  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
6665  _PParam->_M_fHasExplicitToken = true;
6666  }
6667 
6668  task_options _Options(_TaskOptions);
6669  _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
6670  task<std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
6671 
6672  // Keep a copy ref to the token source
6673  auto _CancellationSource = _PParam->_M_cancellationSource;
6674 
6675  _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
6676  size_t _Index = 0;
6677  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6678  {
6679  if (_PTask->is_apartment_aware())
6680  {
6681  _Any_tasks_completed._SetAsync();
6682  }
6683 
6684  _PTask->_Then([_PParam, _Index](task<_ElementType> _ResultTask) {
6685  auto _PParamCopy = _PParam; // Dev10
6686  auto _IndexCopy = _Index; // Dev10
6687  auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
6688  _PParamCopy->_M_Completed.set(std::make_pair(std::make_pair(_ResultTask._GetImpl()->_GetResult(), _IndexCopy), _ResultTask._GetImpl()->_M_pTokenState));
6689  };
6690 
6691  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6693 
6694  _Index++;
6695  }
6696 
6697  // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
6698  return _Any_tasks_completed._Then([=](std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState *> _Result) -> std::pair<_ElementType, size_t> {
6699  _ASSERTE(_Result.second);
6700  if (!_PTokenState)
6701  {
6702  _JoinAllTokens_Add(_CancellationSource, _Result.second);
6703  }
6704  return _Result.first;
6705  }, nullptr);
6706  }
6707  };
6708 
6709  template<typename _Iterator>
6710  struct _WhenAnyImpl<void, _Iterator>
6711  {
6712  static task<size_t> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6713  {
6714  if( _Begin == _End )
6715  {
6716  _THROW_NCEE(invalid_operation, "when_any(begin, end) cannot be called on an empty container.");
6717  }
6718 
6719  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6720  auto _PParam = new _RunAnyParam<std::pair<size_t, _CancellationTokenState *>>();
6721 
6722  if (_PTokenState)
6723  {
6724  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
6725  _PParam->_M_fHasExplicitToken = true;
6726  }
6727 
6728  task_options _Options(_TaskOptions);
6729  _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
6730  task<std::pair<size_t, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
6731 
6732  // Keep a copy ref to the token source
6733  auto _CancellationSource = _PParam->_M_cancellationSource;
6734 
6735  _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
6736  size_t _Index = 0;
6737  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6738  {
6739  if (_PTask->is_apartment_aware())
6740  {
6741  _Any_tasks_completed._SetAsync();
6742  }
6743 
6744  _PTask->_Then([_PParam, _Index](task<void> _ResultTask) {
6745  auto _PParamCopy = _PParam; // Dev10
6746  auto _IndexCopy = _Index; // Dev10
6747  auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
6748  _PParamCopy->_M_Completed.set(std::make_pair(_IndexCopy, _ResultTask._GetImpl()->_M_pTokenState));
6749  };
6750  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6752 
6753  _Index++;
6754  }
6755 
6756  // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
6757  return _Any_tasks_completed._Then([=](std::pair<size_t, _CancellationTokenState *> _Result) -> size_t {
6758  _ASSERTE(_Result.second);
6759  if (!_PTokenState)
6760  {
6761  _JoinAllTokens_Add(_CancellationSource, _Result.second);
6762  }
6763  return _Result.first;
6764  }, nullptr);
6765  }
6766  };
6767 } // namespace details
6768 
6788 
6789 template<typename _Iterator>
6790 auto when_any(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
6791  -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End))
6792 {
6793  typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
6794  return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
6795 }
6796 
6820 
6821 template<typename _Iterator>
6822 auto when_any(_Iterator _Begin, _Iterator _End, cancellation_token _CancellationToken)
6823  -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End))
6824 {
6825  typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
6826  return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End);
6827 }
6828 
6854 
6855 template<typename _ReturnType>
6856 task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs)
6857 {
6858  auto _PParam = new details::_RunAnyParam<std::pair<_ReturnType, size_t>>();
6859 
6860  task<std::pair<_ReturnType, size_t>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
6861  // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
6862  // So that _PParam can be used before it getting deleted.
6863  auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<_ReturnType, size_t> _Ret) -> _ReturnType {
6864  _ASSERTE(_Ret.second);
6865  _JoinAllTokens_Add(_PParam->_M_cancellationSource, reinterpret_cast<details::_CancellationTokenState *>(_Ret.second));
6866  return _Ret.first;
6867  }, nullptr);
6868 
6869  if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
6870  {
6871  _ReturnTask._SetAsync();
6872  }
6873 
6874  _PParam->_M_numTasks = 2;
6875  auto _Continuation = [_PParam](task<_ReturnType> _ResultTask) {
6876  // Dev10 compiler bug
6877  auto _PParamCopy = _PParam;
6878  auto _Func = [&_ResultTask, _PParamCopy]() {
6879  _PParamCopy->_M_Completed.set(std::make_pair(_ResultTask._GetImpl()->_GetResult(), reinterpret_cast<size_t>(_ResultTask._GetImpl()->_M_pTokenState)));
6880  };
6881  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6882  };
6883 
6884  _Lhs._Then(_Continuation, details::_CancellationTokenState::_None());
6885  _Rhs._Then(_Continuation, details::_CancellationTokenState::_None());
6886 
6887  return _ReturnTask;
6888 }
6889 
6915 
6916 template<typename _ReturnType>
6917 task<std::vector<_ReturnType>> operator||(const task<std::vector<_ReturnType>> & _Lhs, const task<_ReturnType> & _Rhs)
6918 {
6919  auto _PParam = new details::_RunAnyParam<std::pair<std::vector<_ReturnType>, details::_CancellationTokenState *>>();
6920 
6921  task<std::pair<std::vector<_ReturnType>, details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
6922 
6923  // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
6924  // So that _PParam can be used before it getting deleted.
6925  auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<std::vector<_ReturnType>, details::_CancellationTokenState *> _Ret) -> std::vector<_ReturnType> {
6926  _ASSERTE(_Ret.second);
6927  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
6928  return _Ret.first;
6929  }, nullptr);
6930 
6931  if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
6932  {
6933  _ReturnTask._SetAsync();
6934  }
6935 
6936  _PParam->_M_numTasks = 2;
6937  _Lhs._Then([_PParam](task<std::vector<_ReturnType>> _ResultTask) {
6938  // Dev10 compiler bug
6939  auto _PParamCopy = _PParam;
6940  auto _Func = [&_ResultTask, _PParamCopy]() {
6941  auto _Result = _ResultTask._GetImpl()->_GetResult();
6942  _PParamCopy->_M_Completed.set(std::make_pair(_Result, _ResultTask._GetImpl()->_M_pTokenState));
6943  };
6944  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6946 
6947 
6948  _Rhs._Then([_PParam](task<_ReturnType> _ResultTask)
6949  {
6950  // Dev10 compiler bug
6951  typedef _ReturnType _ReturnTypeDev10;
6952  auto _PParamCopy = _PParam;
6953  auto _Func = [&_ResultTask, _PParamCopy]() {
6954  auto _Result = _ResultTask._GetImpl()->_GetResult();
6955 
6956  std::vector<_ReturnTypeDev10> _Vec;
6957  _Vec.push_back(_Result);
6958  _PParamCopy->_M_Completed.set(std::make_pair(_Vec, _ResultTask._GetImpl()->_M_pTokenState));
6959  };
6960  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6962 
6963  return _ReturnTask;
6964 }
6965 
6991 
6992 template<typename _ReturnType>
6993 task<std::vector<_ReturnType>> operator||(const task<_ReturnType> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
6994 {
6995  return _Rhs || _Lhs;
6996 }
6997 
7023 
7024 inline task<void> operator||(const task<void> & _Lhs, const task<void> & _Rhs)
7025 {
7026  auto _PParam = new details::_RunAnyParam<std::pair<details::_Unit_type, details::_CancellationTokenState *>>();
7027 
7028  task<std::pair<details::_Unit_type, details::_CancellationTokenState *>> _Any_task_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
7029  // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7030  // So that _PParam can be used before it getting deleted.
7031  auto _ReturnTask = _Any_task_completed._Then([=](std::pair<details::_Unit_type, details::_CancellationTokenState *> _Ret) {
7032  _ASSERTE(_Ret.second);
7033  details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
7034  }, nullptr);
7035 
7036  if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7037  {
7038  _ReturnTask._SetAsync();
7039  }
7040 
7041  _PParam->_M_numTasks = 2;
7042  auto _Continuation = [_PParam](task<void> _ResultTask) mutable {
7043  // Dev10 compiler needs this.
7044  auto _PParam1 = _PParam;
7045  auto _Func = [&_ResultTask, _PParam1]() {
7046  _PParam1->_M_Completed.set(std::make_pair(details::_Unit_type(), _ResultTask._GetImpl()->_M_pTokenState));
7047  };
7048  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7049  };
7050 
7051  _Lhs._Then(_Continuation, details::_CancellationTokenState::_None());
7052  _Rhs._Then(_Continuation, details::_CancellationTokenState::_None());
7053 
7054  return _ReturnTask;
7055 }
7056 
7057 template<typename _Ty>
7058 task<_Ty> task_from_result(_Ty _Param, const task_options& _TaskOptions = task_options())
7059 {
7060  task_completion_event<_Ty> _Tce;
7061  _Tce.set(_Param);
7062  return create_task(_Tce, _TaskOptions);
7063 }
7064 
7065 inline task<void> task_from_result(const task_options& _TaskOptions = task_options())
7066 {
7067  task_completion_event<void> _Tce;
7068  _Tce.set();
7069  return create_task(_Tce, _TaskOptions);
7070 }
7071 
7072 template<typename _TaskType, typename _ExType>
7073 task<_TaskType> task_from_exception(_ExType _Exception, const task_options& _TaskOptions = task_options())
7074 {
7075  task_completion_event<_TaskType> _Tce;
7076  _Tce.set_exception(_Exception);
7077  return create_task(_Tce, _TaskOptions);
7078 }
7079 
7080 namespace details
7081 {
7089  inline
7090  task<bool> do_while(std::function<task<bool>(void)> _Func)
7091  {
7092  task<bool> _First = _Func();
7093  return _First.then([=](bool _Guard) -> task<bool> {
7094  if (_Guard)
7095  return do_while(_Func);
7096  else
7097  return _First;
7098  });
7099  }
7100 
7101 } // namespace details
7102 
7103 } // namespace Concurrency
7104 
7105 #pragma pop_macro("new")
7106 #pragma warning(pop)
7107 #pragma pack(pop)
7108 
7109 #endif // _PPLTASKS_H
_InitialTaskHandle(const typename details::_Task_ptr< _ReturnType >::_Type &_TaskImpl, const _Function &_func)
Definition: ppltasks.h:3453
Definition: xtr1common:22
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2026
void _set_creation_callstack(const _TaskCreationCallstack &_callstack)
Definition: ppltasks.h:1042
void _RethrowUserException()
Definition: ppltasks.h:754
virtual ~_PPLTaskHandle()
Definition: ppltasks.h:1402
std::function< _Unit_type(void)> _MakeVoidToUnitFunc(const std::function< void(void)> &_Func)
Definition: ppltasks.h:2298
bool _IsCompleted()
Definition: ppltasks.h:1656
static auto _Perform(std::function< _RetType(void)> _Func) -> decltype(_Func)
Definition: ppltasks.h:2849
static _TaskCreationCallstack _CaptureSingleFrameCallstack(void *_SingleFrame)
Definition: ppltasks.h:169
_TaskCreationCallstack _M_presetCreationCallstack
Definition: ppltasks.h:1040
scheduler_ptr _M_Scheduler
Definition: ppltasks.h:1224
Definition: concrt.h:364
void _TaskInitMaybeFunctor(_Function &_Func, std::true_type)
Initializes a task using a callable object.
Definition: ppltasks.h:4365
static auto _Perform(std::function< _OutType(void)> _Func) -> decltype(details::_MakeUnitToTFunc< _OutType >(_Func))
Definition: ppltasks.h:2817
_T atomic_exchange(std::atomic< _T > &_Target, _T _Value)
Definition: pplinterface.h:246
Definition: functional:67
void _Continue(std::false_type, details::_TypeSelectorNoAsync) const
Definition: ppltasks.h:3604
void _SyncCancelAndPropagateException() const
Definition: ppltasks.h:3583
task_options()
Default list of task creation options
Definition: ppltasks.h:1067
bool _M_HasScheduler
Definition: ppltasks.h:1229
std::function< _Unit_type(_Unit_type)> _MakeUnitToUnitFunc(const std::function< void(void)> &_Func)
Definition: ppltasks.h:2315
_ThenImplOptions(_CancellationTokenState *_Token_state, const task_continuation_context *_Continuation_context, scheduler_ptr _PScheduler, _TaskCreationCallstack _Creation_stack, _TaskInliningMode_t _Inlining_mode=_NoInline)
Definition: ppltasks.h:1239
This class describes an exception thrown when an invalid operation is performed that is not more accu...
Definition: pplinterface.h:132
_CRTIMP2 void __thiscall _LogWorkItemStarted()
bool _HasUserException()
Definition: ppltasks.h:1666
reference_wrapper< _Ty > ref(_Ty &_Val) _NOEXCEPT
Definition: type_traits:1617
auto _Then(const _Function &_Func, details::_CancellationTokenState *_PTokenState, details::_TaskInliningMode_t _InliningMode=details::_ForceInline) const -> typename details::_ContinuationTypeTraits< _Function, void >::_TaskOfType
An internal version of then that takes additional flags and executes the continuation inline...
Definition: ppltasks.h:4311
bool _M_scheduled
Definition: ppltasks.h:1314
void Set(const std::vector< bool > &_type)
Definition: ppltasks.h:641
std::shared_ptr< _Task_impl_base > _Task_ptr_base
Definition: ppltasks.h:1286
~_TaskWorkItemRAIILogger()
Definition: ppltasks.h:1354
_Holder(_TaskProcThunk *_PThunk)
Definition: ppltasks.h:461
bool _ForceInline() const
Definition: ppltasks.h:1024
bool _M_RunInline
Definition: ppltasks.h:1031
#define S_OK
Definition: comutil.h:62
void _SetTaskCreationCallstack(const details::_TaskCreationCallstack &_callstack)
Sets a field in the task impl to the return callstack for calls to the task constructors and the then...
Definition: ppltasks.h:3414
std::function< _Type(_Unit_type)> _MakeUnitToTFunc(const std::function< _Type(void)> &_Func)
Definition: ppltasks.h:2304
_ContinuationList _M_Continuations
Definition: ppltasks.h:2031
Definition: concrt.h:376
details::_Task_ptr< _ReturnType >::_Type _M_ancestorTaskImpl
Definition: ppltasks.h:3551
Definition: ppltasks.h:1237
void _Perform() const
Definition: ppltasks.h:3468
unsigned int _Count
Definition: xcomplex:668
auto _IsCallable(_Function _Func, int) -> decltype(_Func(), std::true_type())
std::vector< void * > _M_frames
Definition: ppltasks.h:161
_TaskCreationCallstack _M_stackTrace
Definition: ppltasks.h:775
scheduler_ptr _GetScheduler() const
Definition: ppltasks.h:2010
void __cdecl ReportUnhandledError(::Platform::Exception^)
for(_CMPLX(_Ty) _Zv=_CMPLX(_Ty)(1);;_Tmp *=_Tmp)
Definition: xcomplex:673
const details::_Task_ptr< _ReturnType >::_Type & _ThenGetImpl() const
Definition: ppltasks.h:3375
~_Task_completion_event_impl()
Definition: ppltasks.h:2278
bool operator==(const _Concurrent_queue_iterator< _C, _Ty > &_I, const _Concurrent_queue_iterator< _C, _U > &_J)
Definition: concurrent_queue.h:318
Definition: concrt.h:4304
Definition: pplinterface.h:228
_TaskWorkItemRAIILogger(_TaskEventLogger &_taskHandleLogger)
Definition: ppltasks.h:1349
_ContextCallback(bool _DeferCapture=false)
Definition: ppltasks.h:514
bool operator==(const _ContextCallback &_Rhs) const
Definition: ppltasks.h:581
const ::std::shared_ptr< scheduler_interface > & get_ambient_scheduler()
Definition: pplwin.h:88
void _LogTaskExecutionStarted()
Definition: ppltasks.h:1327
_Task_ptr_base _GetTaskImplBase() const
Definition: ppltasks.h:1436
void _RunContinuation(_ContinuationTaskHandleBase *_PTaskHandle)
Function executes a continuation. This function is recorded by a parent task implementation when a co...
Definition: ppltasks.h:1742
std::mutex _M_taskListCritSec
Definition: ppltasks.h:2290
details::_NormalizeVoidToUnitType< _ContinuationReturnType >::_Type _NormalizedContinuationReturnType
Definition: ppltasks.h:3549
task_options(cancellation_token _Token)
Task option that specify a cancellation token
Definition: ppltasks.h:1079
__declspec(noinline) static _TaskCreationCallstack _CaptureMultiFramesCallstack(void *_SingleFrame
_PPLTaskHandle(const typename _Task_ptr< _ReturnType >::_Type &_PTask)
Definition: ppltasks.h:1398
static cancellation_token none()
Returns a cancellation token which can never be subject to cancellation.
Definition: pplcancellation_token.h:628
task_continuation_context * _PContinuationContext
Definition: ppltasks.h:1248
_ContinuationTaskHandleBase * _M_next
Definition: ppltasks.h:1291
auto _FilterValidTaskType(_Ty _Param, int) -> decltype(_GetTaskType(_Param, _IsCallable(_Param, 0)))
#define _TRY_BEGIN
Definition: xstddef:60
#define _CATCH(x)
Definition: xstddef:61
bool _IsCanceled()
Definition: ppltasks.h:1661
_CRTIMP2 size_t __cdecl CaptureCallstack(void **, size_t, size_t)
task(const task &_Other)
Constructs a task object.
Definition: ppltasks.h:3038
This class describes an exception thrown by the PPL tasks layer in order to force the current task to...
Definition: pplinterface.h:163
return _csc
Definition: ppltasks.h:188
_OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
Definition: algorithm:956
static auto _Perform(std::function< void(_InType)> _Func) -> decltype(details::_MakeTToUnitFunc< _InType >(_Func))
Definition: ppltasks.h:2827
auto _VoidIsTaskHelper(_Function _Func, int, int) -> decltype(_Func(std::declval< task< void >>()), std::true_type())
task< details::_Unit_type > _M_unitTask
Definition: ppltasks.h:4380
The task_completion_event class allows you to delay the execution of a task until a condition is sati...
Definition: ppltasks.h:2339
void _SetTaskCreationCallstack(const details::_TaskCreationCallstack &_callstack)
Sets a field in the task impl to the return callstack for calls to the task constructors and the then...
Definition: ppltasks.h:4302
Definition: exception:254
Definition: concrt.h:4305
#define _CATCH_END
Definition: xstddef:63
_Unit_type _Type
Definition: ppltasks.h:210
::Concurrency::details::_TaskCollection_t _M_TaskCollection
Definition: ppltasks.h:2040
task_completion_event()
Constructs a task_completion_event object.
Definition: ppltasks.h:2346
bool _M_fHasValue
Definition: ppltasks.h:2293
_Task_ptr< _ReturnType >::_Type _M_pTask
Definition: ppltasks.h:1441
__declspec(noinline) bool set_exception(std
Propagates an exception to all tasks associated with this event.
Definition: ppltasks.h:2427
_In_ int _Val
Definition: vcruntime_string.h:62
task< typename _TaskTypeTraits< typename _FunctionTypeTraits< _Function, _ReturnType >::_FuncRetType >::_TaskRetType > _TaskOfType
Definition: ppltasks.h:402
void _Init(details::_TypeSelectorNoAsync) const
Definition: ppltasks.h:3483
void _Resolve(bool _CaptureCurrent)
Definition: ppltasks.h:527
__declspec(noinline) explicit task(_Ty _Param)
Constructs a task object.
Definition: ppltasks.h:2953
cancellation_token _M_CancellationToken
Definition: ppltasks.h:1225
Definition: agile.h:114
static task_continuation_context get_current_winrt_context()
Returns a task continuation context object that represents the current winrt thread context...
Definition: ppltasks.h:955
file_status status(const path &)
Definition: filesystem:3137
void reserve(size_type _Count)
Definition: vector:1031
_Function _M_function
Definition: ppltasks.h:3452
STL namespace.
_CancellationTokenState * _PTokenState
Definition: ppltasks.h:1244
Definition: ppltasks.h:619
void _SetImpl(typename details::_Task_ptr< _ReturnType >::_Type &&_Impl)
Set the implementation of the task to be the supplied implementation using a move instead of a copy...
Definition: ppltasks.h:3397
bool operator==(const task< void > &_Rhs) const
Determines whether two task objects represent the same internal task.
Definition: ppltasks.h:4232
std::vector< typename _Task_ptr< _ResultType >::_Type > _TaskList
Definition: ppltasks.h:2266
void _Perform() const
Definition: ppltasks.h:3578
void _TaskInitNoFunctor(task_completion_event< _ReturnType > &_Event)
Initializes a task using a task completion event.
Definition: ppltasks.h:3788
_Internal_task_options & _get_internal_task_options(task_options &_Options)
Definition: ppltasks.h:1266
Represents the allowed options for creating a task
Definition: ppltasks.h:1059
task()
Constructs a task object.
Definition: ppltasks.h:3929
The Concurrency namespace provides classes and functions that provide access to the Concurrency Runti...
Definition: agents.h:43
Definition: ppltasks.h:3449
bool _M_isTaskBasedContinuation
Definition: ppltasks.h:1293
Definition: ppltasks.h:4434
bool _Cancel(bool _SynchronousCancel)
Definition: ppltasks.h:1596
The implementation of a first-class task. This structure contains the task group used to execute the ...
Definition: ppltasks.h:1276
void _TaskRetType
Definition: ppltasks.h:345
_TaskEventLogger(_Task_impl_base *_task)
Definition: ppltasks.h:1338
void _SetAsync(bool _Async=true)
Sets a property determining whether the task is apartment aware.
Definition: ppltasks.h:4294
cancellation_token get_cancellation_token() const
Returns the cancellation token
Definition: ppltasks.h:1189
_TaskEventLogger _M_taskEventLogger
Definition: ppltasks.h:2045
size_t _CaptureFrames
Definition: ppltasks.h:179
_ExceptionHolder(const std::exception_ptr &_E, const _TaskCreationCallstack &_stackTrace)
Definition: ppltasks.h:737
Definition: ppltasks.h:328
std::function< void __cdecl(void)> _CallbackFunction
Definition: ppltasks.h:498
static const bool _Value
Definition: ppltasks.h:216
_CancellationTokenState * _M_pTokenState
Definition: ppltasks.h:2034
_TaskInliningMode_t _M_inliningMode
Definition: ppltasks.h:1296
integral_constant< bool, false > false_type
Definition: xtr1common:41
bool _IsApartmentAware()
Definition: ppltasks.h:1677
void _Cancel() const
Cancel the task_completion_event. Any task created using this event will be marked as canceled if it ...
Definition: ppltasks.h:2671
scheduler_ptr scheduler() const
Returns the scheduler for this task
Definition: ppltasks.h:4208
_Task_impl_base * _M_task
Definition: ppltasks.h:1313
Definition: pplinterface.h:224
auto _LogWorkItemAndInvokeUserLambda(_Func &&_func, _Arg &&_value) const -> decltype(_func(std::forward< _Arg >(_value)))
Definition: ppltasks.h:3572
_CRTIMP2 void __thiscall _CallInContext(_CallbackFunction _Func, bool _IgnoreDisconnect) const
task_completion_event< details::_Unit_type > _M_unitEvent
Definition: ppltasks.h:2725
bool _IsHRCOMDisconnected(int __hr)
Definition: ppltasks.h:4448
The task_completion_event class allows you to delay the execution of a task until a condition is sati...
Definition: ppltasks.h:2625
_Internal_task_options()
Definition: ppltasks.h:1047
unsigned char _Unit_type
Definition: ppltasks.h:191
virtual ~_InitialTaskHandle()
Definition: ppltasks.h:3459
__declspec(noinline) bool set_exception(_E _Except) const
Definition: ppltasks.h:2647
bool _CancelWithException(const std::exception_ptr &_Exception)
Definition: ppltasks.h:1608
bool is_done() const
Determines if the task is completed.
Definition: ppltasks.h:3288
_Iter_diff_t< _InIt > distance(_InIt _First, _InIt _Last)
Definition: xutility:1124
Definition: ppltasks.h:322
_TaskProcThunk * _M_pThunk
Definition: ppltasks.h:470
bool has_scheduler() const
Indicates whether a scheduler n was specified by the user
Definition: ppltasks.h:1205
_TaskCreationCallstack()
Definition: ppltasks.h:163
bool _IsTriggered() const
Tests whether current event has been either Set, or Canceled.
Definition: ppltasks.h:2499
void _DeregisterCancellation()
Definition: ppltasks.h:1631
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION()
Definition: pplwin.h:125
const details::_Task_ptr< details::_Unit_type >::_Type & _ThenGetImpl() const
Definition: ppltasks.h:4265
void _ScheduleContinuationTask(_ContinuationTaskHandleBase *_PTaskHandle)
Definition: ppltasks.h:1774
Definition: pplinterface.h:226
static std::shared_ptr< details::_ExceptionHolder > _ToExceptionHolder(std::exception_ptr _ExceptionPtr, const details::_TaskCreationCallstack &_SetExceptionAddressHint)
Definition: ppltasks.h:2511
details::_Internal_task_options _M_InternalTaskOptions
Definition: ppltasks.h:1227
task_status _Wait()
Definition: ppltasks.h:1485
bool _StoreException(const std::shared_ptr< details::_ExceptionHolder > &_ExHolder) const
Method that stores an exception in the task completion event. This is used internally by when_any...
Definition: ppltasks.h:2690
void * _M_SingleFrame
Definition: ppltasks.h:160
void _SetImpl(details::_Task_ptr< details::_Unit_type >::_Type &&_Impl)
Set the implementation of the task to be the supplied implementation using a move instead of a copy...
Definition: ppltasks.h:4286
void _TaskInitMaybeFunctor(_Function &_Func, std::true_type)
Initializes a task using a callable object.
Definition: ppltasks.h:3827
_TaskInliningMode_t _InliningMode
Definition: ppltasks.h:1247
_CRTIMP2 void __thiscall _LogWorkItemCompleted()
static auto _Perform(std::function< void(void)> _Func) -> decltype(details::_MakeUnitToUnitFunc(_Func))
Definition: ppltasks.h:2837
task()
Constructs a task object.
Definition: ppltasks.h:2911
Definition: ppltasks.h:731
void _Continue(std::false_type, details::_TypeSelectorAsyncOperationOrTask) const
Definition: ppltasks.h:3618
virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr< _ExceptionHolder > &_ExceptionHolder_arg)
Requests cancellation on the task and schedules continuations if the task can be transitioned to a te...
Definition: ppltasks.h:2076
shared_ptr< _Ty > make_shared(_Types &&..._Args)
Definition: memory:968
void _Init(details::_TypeSelectorAsyncOperationOrTask) const
Definition: ppltasks.h:3496
details::_Task_ptr< _ReturnType >::_Type _M_Impl
Definition: ppltasks.h:3883
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
std::vector< char > _Result
Definition: ppltasks.h:654
_UnwrapTaskType< _Type >::_Type _TaskRetType
Definition: ppltasks.h:330
void _ClearStoredException() const
Internal method that observe and clear the exception stored in the task completion event...
Definition: ppltasks.h:2699
Definition: vccorlib.h:117
_TaskInliningMode
The enum defines inlining scheduling policy for ppltasks. Scheduling a chore or a functor with _TaskI...
Definition: pplinterface.h:221
virtual ~_Task_impl_base()
Definition: ppltasks.h:1476
auto _LogWorkItemAndInvokeUserLambda(_Func _func) const -> decltype(_func())
Definition: ppltasks.h:3462
_TaskCreationCallstack _CreationStack
Definition: ppltasks.h:1246
constexpr pair< typename _Unrefwrap< _Ty1 >::type, typename _Unrefwrap< _Ty2 >::type > make_pair(_Ty1 &&_Val1, _Ty2 &&_Val2)
Definition: utility:323
_ResultHolder< _ResultType > _M_value
Definition: ppltasks.h:2291
auto _ThenImpl(const _Function &_Func, details::_ThenImplOptions &_Options) const -> typename details::_ContinuationTypeTraits< _Function, _InternalReturnType >::_TaskOfType
The one and only implementation of then for void and non-void tasks.
Definition: ppltasks.h:3845
bool has_cancellation_token() const
Indicates whether a cancellation token was specified by the user
Definition: ppltasks.h:1181
#define bool
Definition: stdbool.h:15
task_continuation_context get_continuation_context() const
Returns the continuation context
Definition: ppltasks.h:1197
_ContinuationTaskHandleBase * _ContinuationList
Definition: ppltasks.h:2028
union Concurrency::details::_ContextCallback::@91 _M_context
_Boolarray operator&&(const valarray< _Ty > &_Left, const _Ty &_Right)
Definition: valarray:656
bool operator!=(const task< _ReturnType > &_Rhs) const
Determines whether two task objects represent different internal tasks.
Definition: ppltasks.h:3349
_TaskList _M_tasks
Definition: ppltasks.h:2289
__declspec(deprecated("Concurrency::EnableTracing is a deprecated function.")) _CONCRTIMP HRESULT __cdecl EnableTracing()
Enables tracing in the Concurrency Runtime. This function is deprecated because ETW tracing is now on...
static _CancellationTokenState * _None()
Definition: pplcancellation_token.h:332
std::shared_ptr< _Task_impl< _ReturnType > > _Type
Definition: ppltasks.h:1281
#define _THROW_NCEE(x, y)
Definition: xstddef:78
auto _IsValidTaskCtor(_Ty _Param, int, int, int, int) -> decltype(_Param(), std::true_type())
atomic_long _M_exceptionObserved
Definition: ppltasks.h:766
_Ty _GetTaskType(task_completion_event< _Ty >, std::false_type)
_GetTaskType functions will retrieve task type T in task[T](Arg), for given constructor argument Arg ...
static std::shared_ptr< details::_ExceptionHolder > _ToExceptionHolder(const std::shared_ptr< details::_ExceptionHolder > &_ExHolder, const details::_TaskCreationCallstack &)
Definition: ppltasks.h:2506
_TaskTypeTraits< _FuncRetType >::_AsyncKind _AsyncKind
Definition: ppltasks.h:427
bool _IsCreated()
Definition: ppltasks.h:1641
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: ppltasks.h:3898
task_status wait() const
Waits for this task to reach a terminal state. It is possible for wait to execute the task inline...
Definition: ppltasks.h:3242
The tasks queued to the task_group or structured_task_group object completed successfully.
Definition: pplinterface.h:115
bool _IsTriggered() const
Test whether current event has been either Set, or Canceled.
Definition: ppltasks.h:2707
bool operator!=(const task< void > &_Rhs) const
Determines whether two task objects represent different internal tasks.
Definition: ppltasks.h:4244
The task_group or structured_task_group object was canceled. One or more tasks may not have executed...
Definition: pplinterface.h:121
_TypeSelectorNoAsync _AsyncKind
Definition: ppltasks.h:435
Definition: pplcancellation_token.h:106
_ContextCallback(const _ContextCallback &_Src)
Definition: ppltasks.h:542
Definition: ppltasks.h:1279
void _ScheduleContinuation(_ContinuationTaskHandleBase *_PTaskHandle)
Schedule the actual continuation. This will either schedule the function on the continuation task's i...
Definition: ppltasks.h:1834
task_options(task_continuation_context _ContinuationContext)
Task option that specify a continuation context. This is valid only for continuations (then) ...
Definition: ppltasks.h:1091
Definition: ppltasks.h:2846
std::mutex _M_ContinuationsCritSec
Definition: ppltasks.h:2030
Definition: ppltasks.h:1311
bool _CancelWithExceptionHolder(const std::shared_ptr< _ExceptionHolder > &_ExHolder, bool _PropagatedFromAncestor)
Definition: ppltasks.h:1602
_TaskInternalState
Definition: ppltasks.h:1453
bool _StoreException(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint=details::_TaskCreationCallstack()) const
Internal method that stores an exception in the task completion event. This is used internally by whe...
Definition: ppltasks.h:2470
__declspec(noinline) auto then(const _Function &_Func) const -> typename details::_ContinuationTypeTraits< _Function, _ReturnType >::_TaskOfType
Adds a continuation task to this task.
Definition: ppltasks.h:3128
details::_Task_completion_event_impl< _Ty >::_TaskList _TaskList
Definition: ppltasks.h:2520
std::exception_ptr _M_stdException
Definition: ppltasks.h:769
std::function< _Unit_type(_Type)> _MakeTToUnitFunc(const std::function< void(_Type)> &_Func)
Definition: ppltasks.h:2310
#define false
Definition: stdbool.h:16
void Set(const _Type &_type)
Definition: ppltasks.h:623
bool is_apartment_aware() const
Determines whether the task unwraps a Windows Runtime IAsyncInfo interface or is descended from such ...
Definition: ppltasks.h:3321
_CRTIMP2 unsigned int __cdecl GetNextAsyncId()
_ContextCallback(_ContextCallback &&_Src)
Definition: ppltasks.h:547
#define or
Definition: iso646.h:15
auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg))
_TaskCollection_t::_TaskProcHandle_t _UnrealizedChore_t
Definition: ppltasks.h:1285
static _ContextCallback _CaptureCurrent()
Definition: ppltasks.h:502
Definition: vector:678
size_t _M_captureMethod
Definition: ppltasks.h:611
static _ThenImplOptions _CreateOptions(const task_options &_Task_Options, const task_continuation_context &_ContinuationContext, const scheduler_ptr &impl_scheduler)
Definition: ppltasks.h:1250
_TypeSelectorAsyncTask _AsyncOperationKindSelector(task< _Ty >)
void _RegisterTask(details::_Task_ptr< details::_Unit_type >::_Type _TaskParam)
Register a task with this event. This function is called when a task is constructed using a task_comp...
Definition: ppltasks.h:2719
exception_ptr make_exception_ptr(_Ex _Except) _NOEXCEPT
Definition: exception:371
_Task_impl_base(_CancellationTokenState *_PTokenState, scheduler_ptr _Scheduler_arg)
Definition: ppltasks.h:1463
bool _IsPendingCancel()
Definition: ppltasks.h:1651
task & operator=(task &&_Other)
Replaces the contents of one task object with another.
Definition: ppltasks.h:3098
The task_continuation_context class allows you to specify where you would like a continuation to be e...
Definition: ppltasks.h:915
task(task &&_Other)
Constructs a task object.
Definition: ppltasks.h:3065
void _SetImpl(const typename details::_Task_ptr< _ReturnType >::_Type &_Impl)
Set the implementation of the task to be the supplied implementation.
Definition: ppltasks.h:3388
Represents a pointer to a scheduler. This class exists to allow the the specification of a shared lif...
Definition: pplinterface.h:47
bool _M_hasPresetCreationCallstack
Definition: ppltasks.h:1039
#define _CATCH_ALL
Definition: xstddef:62
_TaskCreationCallstack _M_pTaskCreationCallstack
Definition: ppltasks.h:2043
virtual ~_ContinuationTaskHandle()
Definition: ppltasks.h:3569
void _SetAsync(bool _Async=true)
Sets a property determining whether the task is apartment aware.
Definition: ppltasks.h:3406
_CancellationTokenRegistration * _M_pRegistration
Definition: ppltasks.h:2037
void _ScheduleTask(_UnrealizedChore_t *_PTaskHandle, _TaskInliningMode_t _InliningMode)
Helper function to schedule the task on the Task Collection.
Definition: ppltasks.h:1706
_Task_generator_oversubscriber _Task_generator_oversubscriber_t
Definition: pplwin.h:268
void set_continuation_context(task_continuation_context _ContinuationContext)
Sets the given continuation context in the options
Definition: ppltasks.h:1173
bool _CancelInternal() const
Cancels the task_completion_event.
Definition: ppltasks.h:2525
task_options(const task_options &_TaskOptions)
Task option copy constructor
Definition: ppltasks.h:1152
_Task_impl(_CancellationTokenState *_Ct, scheduler_ptr _Scheduler_arg)
Definition: ppltasks.h:2064
bool operator==(const task< _ReturnType > &_Rhs) const
Determines whether two task objects represent the same internal task.
Definition: ppltasks.h:3337
std::vector< bool > Get()
Definition: ppltasks.h:647
_Function _M_function
Definition: ppltasks.h:3552
auto _VoidReturnTypeHelper(_Function _Func, int, int) -> decltype(_Func(std::declval< task< void >>()))
bool _M_fUnwrappedTask
Definition: ppltasks.h:2021
void rethrow_exception(_In_ exception_ptr _Ptr)
Definition: exception:364
bool _IsDone()
Definition: ppltasks.h:2243
bool _M_fFromAsync
Definition: ppltasks.h:2019
virtual _Task_ptr_base _GetTaskImplBase() const =0
_T atomic_increment(std::atomic< _T > &_Target)
Definition: pplinterface.h:252
void _RegisterTask(const typename details::_Task_ptr< _ResultType >::_Type &_TaskParam)
Register a task with this event. This function is called when a task is constructed using a task_comp...
Definition: ppltasks.h:2572
static bool _IsValid(_In_opt_ _CancellationTokenState *_PToken)
Definition: pplcancellation_token.h:337
static auto _Perform(std::function< void(void)> _Func) -> decltype(details::_MakeVoidToUnitFunc(_Func))
Definition: ppltasks.h:2859
task_options(scheduler_ptr _Scheduler)
Task option that specify a scheduler
Definition: ppltasks.h:1140
_CRTIMP2 void __thiscall _Capture()
static task_continuation_context use_synchronous_execution()
Returns a task continuation context object that represents the synchronous execution context...
Definition: ppltasks.h:1016
#define _EMPTY_ARGUMENT
Definition: xstddef:82
_Boolarray operator||(const valarray< _Ty > &_Left, const _Ty &_Right)
Definition: valarray:670
void * _M_pContextCallback
Definition: ppltasks.h:610
void _CreateImpl(details::_CancellationTokenState *_Ct, scheduler_ptr _Scheduler)
Create an underlying task implementation.
Definition: ppltasks.h:3357
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2292
task_options(std::shared_ptr< _SchedType > _Scheduler)
Task option that specify a scheduler with shared lifetime
Definition: ppltasks.h:1116
_FunctionTypeTraits< _Function, _ReturnType >::_FuncRetType _RetTypeT
Definition: ppltasks.h:405
void _Cancel(const std::shared_ptr< details::_ExceptionHolder > &_ExHolder) const
Cancel the task_completion_event with the exception holder provided. Any task created using this even...
Definition: ppltasks.h:2680
scheduler_ptr _Scheduler
Definition: ppltasks.h:1245
void _TaskInitWithFunctor(const _Function &_Func)
Initializes a task using a lambda, function pointer or function object.
Definition: ppltasks.h:3775
task_group_status
Describes the execution status of a task_group or structured_task_group object. A value of this type ...
Definition: pplinterface.h:102
__declspec(noinline) bool set_exception(std
Propagates an exception to all tasks associated with this event.
Definition: ppltasks.h:2660
bool _IsStarted()
Definition: ppltasks.h:1646
void _TaskInitMaybeFunctor(_Ty &_Param, std::false_type)
Initializes a task using a non-callable object.
Definition: ppltasks.h:4374
auto _ReturnTypeHelper(_Type _Obj, _Function _Func, int, int) -> decltype(_Func(std::declval< task< _Type >>()))
constexpr _Ty && forward(typename remove_reference< _Ty >::type &_Arg) _NOEXCEPT
Definition: type_traits:1273
void _ValidateTaskConstructorArgs(const _Ty &_Param)
Definition: ppltasks.h:2758
#define _CAPTURE_CALLSTACK()
Helper macro to determine how many stack frames need to be saved. When any number less or equal to 1 ...
Definition: ppltasks.h:117
#define _CRTIMP2
Definition: crtdefs.h:36
Definition: ppltasks.h:496
void _Continue(std::true_type, details::_TypeSelectorNoAsync) const
Definition: ppltasks.h:3685
_ReturnType result_type
The type of the result an object of this class produces.
Definition: ppltasks.h:2887
static _Type _Make(_CancellationTokenState *_Ct, scheduler_ptr _Scheduler_arg)
Definition: ppltasks.h:1282
return(_PAIR_TYPE(_FwdIt)(_First, _First))
bool set(_ResultType _Result) const
Sets the task completion event.
Definition: ppltasks.h:2367
Definition: pplcancellation_token.h:221
task_continuation_context _M_continuationContext
Definition: ppltasks.h:1292
std::function< void()> _M_InternalCancellation
Definition: ppltasks.h:2254
_Task_completion_event_impl()
Definition: ppltasks.h:2268
std::shared_ptr< details::_Task_completion_event_impl< _ResultType > > _M_Impl
Definition: ppltasks.h:2607
void set_cancellation_token(cancellation_token _Token)
Sets the given token in the options
Definition: ppltasks.h:1164
void _ClearStoredException() const
Internal method that observe and clear the exception stored in the task completion event...
Definition: ppltasks.h:2486
void _SetImpl(const details::_Task_ptr< details::_Unit_type >::_Type &_Impl)
Set the implementation of the task to be the supplied implementation.
Definition: ppltasks.h:4278
static void __cdecl _Bridge(void *_PData)
Definition: ppltasks.h:450
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: ppltasks.h:85
__declspec(noinline) bool set_exception(_E _Except) const
Definition: ppltasks.h:2413
bool _M_fIsCanceled
Definition: ppltasks.h:2294
_FS_DLL int __CLRCALL_PURE_OR_CDECL _Resize(const wchar_t *, uintmax_t)
scheduler_ptr scheduler() const
Returns the scheduler for this task
Definition: ppltasks.h:3304
_TaskEventLogger & _M_logger
Definition: ppltasks.h:1348
_ContextCallback & operator=(_ContextCallback &&_Src)
Definition: ppltasks.h:563
Definition: utility:75
Definition: pplinterface.h:194
add_rvalue_reference< _Ty >::type declval() _NOEXCEPT
_ResultHolder< _ReturnType > _M_Result
Definition: ppltasks.h:2253
_ImplType _GetImplValue() const
Definition: pplcancellation_token.h:748
integral_constant< bool, true > true_type
Definition: xtr1common:40
bool _Cancel() const
Internal method to cancel the task_completion_event. Any task created using this event will be marked...
Definition: ppltasks.h:2438
constexpr remove_reference< _Ty >::type && move(_Ty &&_Arg) _NOEXCEPT
Definition: type_traits:1290
Definition: ppltasks.h:226
static void __declspec(noreturn) __cdecl _NoCallOnDefaultTask_ErrorImpl()
Helper function for throwing an error for task functions that cannot be called from a default constru...
Definition: ppltasks.h:144
static void _AsyncInit(const typename _Task_ptr< _ReturnType >::_Type &_OuterTask, const task< _InternalReturnType > &_UnwrappedTask)
Definition: ppltasks.h:1975
_CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler())
_Type Get()
Definition: ppltasks.h:628
exception_ptr current_exception() _NOEXCEPT
Definition: exception:359
bool _HasCapturedContext() const
Definition: ppltasks.h:573
Helper object used for LWT invocation.
Definition: ppltasks.h:443
task_continuation_context _M_ContinuationContext
Definition: ppltasks.h:1226
TypeT Get() const
Definition: agile.h:191
std::atomic< long > atomic_long
Atomics
Definition: pplinterface.h:234
A helper class template that transforms a continuation lambda that either takes or returns void...
Definition: ppltasks.h:2804
The task handle type used to create a 'continuation task'.
Definition: ppltasks.h:3545
void _Continue(std::true_type, details::_TypeSelectorAsyncOperationOrTask) const
Definition: ppltasks.h:3703
Definition: xtr1common:86
task_options(cancellation_token _Token, task_continuation_context _ContinuationContext)
Task option that specify a cancellation token and a continuation context. This is valid only for cont...
Definition: ppltasks.h:1103
void _SetTaskCreationCallstack(const _TaskCreationCallstack &_Callstack)
Definition: ppltasks.h:1692
_TypeSelectorNoAsync _AsyncKind
Definition: ppltasks.h:346
_Ty _Type
Definition: ppltasks.h:228
_CRT_BEGIN_C_HEADER typedef void(__CRTDECL *unexpected_handler)()
auto _IsTaskHelper(_Type _Obj, _Function _Func, int, int) -> decltype(_Func(std::declval< task< _Type >>()), std::true_type())
Definition: atomic:56
bool _M_taskPostEventStarted
Definition: ppltasks.h:1315
const std::shared_ptr< _ExceptionHolder > & _GetExceptionHolder()
Definition: ppltasks.h:1671
bool is_apartment_aware() const
Determines whether the task unwraps a Windows Runtime IAsyncInfo interface or is descended from such ...
Definition: ppltasks.h:4220
_Ty _GetUnwrappedType(task< _Ty >)
The following type traits are used for the create_task function.
void _RunTaskContinuations()
Definition: ppltasks.h:1900
task & operator=(const task &_Other)
Replaces the contents of one task object with another.
Definition: ppltasks.h:3078
static void _RunTask(TaskProc_t _Proc, void *_Parameter, _TaskInliningMode _InliningMode)
Definition: pplwin.h:235
_Unit_type _NormalizedTaskRetType
Definition: ppltasks.h:347
bool _M_HasCancellationToken
Definition: ppltasks.h:1228
bool _HasUserException()
Definition: ppltasks.h:2273
void result_type
The type of the result an object of this class produces.
Definition: ppltasks.h:3905
~_ContextCallback()
Definition: ppltasks.h:509
static task_continuation_context use_default()
Creates the default task continuation context.
Definition: ppltasks.h:936
The base implementation of a first-class task. This class contains all the non-type specific implemen...
Definition: ppltasks.h:1451
void _FinalizeAndRunContinuations(_ReturnType _Result)
Definition: ppltasks.h:2173
_TaskCreationCallstack _GetTaskCreationCallstack()
Definition: ppltasks.h:1687
bool operator!=(const _Concurrent_queue_iterator< _C, _Ty > &_I, const _Concurrent_queue_iterator< _C, _U > &_J)
Definition: concurrent_queue.h:324
void _CreateImpl(details::_CancellationTokenState *_Ct, scheduler_ptr _Scheduler)
Create an underlying task implementation.
Definition: ppltasks.h:4252
void _SyncCancelAndPropagateException() const
Definition: ppltasks.h:3473
task_options(scheduler_interface &_Scheduler)
Task option that specify a scheduler reference
Definition: ppltasks.h:1128
const details::_Task_ptr< details::_Unit_type >::_Type & _GetImpl() const
Return the underlying implementation for this task.
Definition: ppltasks.h:4260
auto _Then(const _Function &_Func, details::_CancellationTokenState *_PTokenState, details::_TaskInliningMode_t _InliningMode=details::_ForceInline) const -> typename details::_ContinuationTypeTraits< _Function, _ReturnType >::_TaskOfType
An internal version of then that takes additional flags and always execute the continuation inline by...
Definition: ppltasks.h:3425
Definition: ppltasks.h:4443
virtual ~_ContinuationTaskHandleBase()
Definition: ppltasks.h:1305
Definition: pplcancellation_token.h:176
bool set() const
Sets the task completion event.
Definition: ppltasks.h:2641
virtual void invoke() const
Definition: ppltasks.h:1408
void _CallInContext(_CallbackFunction _Func) const
Definition: ppltasks.h:593
std::function< void()> _M_func
Definition: ppltasks.h:476
const details::_Task_ptr< _ReturnType >::_Type & _GetImpl() const
Return the underlying implementation for this task.
Definition: ppltasks.h:3370
task_status wait() const
Waits for this task to reach a terminal state. It is possible for wait to execute the task inline...
Definition: ppltasks.h:4169
_ContinuationTaskHandleBase()
Definition: ppltasks.h:1300
_ContextCallback & operator=(const _ContextCallback &_Src)
Definition: ppltasks.h:553
_In_ int _Value
Definition: setjmp.h:173
void _RegisterCancellation(std::weak_ptr< _Task_impl_base > _WeakPtr)
Definition: ppltasks.h:1615
virtual ~_Task_impl()
Definition: ppltasks.h:2069
_TaskProcThunk(const std::function< void()> &_Callback)
Definition: ppltasks.h:445
Definition: set:42
static cancellation_token _FromImpl(_ImplType _Impl)
Definition: pplcancellation_token.h:753
_ContinuationTaskHandle(const typename details::_Task_ptr< _ReturnType >::_Type &_AncestorImpl, const typename details::_Task_ptr< _NormalizedContinuationReturnType >::_Type &_ContinuationImpl, const _Function &_Func, const task_continuation_context &_Context, details::_TaskInliningMode_t _InliningMode)
Definition: ppltasks.h:3554
long __cdecl _InterlockedCompareExchange(long volatile *, long, long)
static void _ScheduleFuncWithAutoInline(const std::function< void()> &_Func, _TaskInliningMode_t _InliningMode)
Schedule a functor with automatic inlining. Note that this is "fire and forget" scheduling, which cannot be waited on or canceled after scheduling. This schedule method will perform automatic inlining base on .
Definition: ppltasks.h:491
bool _TransitionedToStarted()
Definition: ppltasks.h:2202
#define true
Definition: stdbool.h:17
std::function< _RetTypeT __cdecl(_ArgTypeT)> _StdFuncT
Definition: ppltasks.h:406
The _PPLTaskHandle is the strong-typed task handle base. All user task functions need to be wrapped i...
Definition: ppltasks.h:1396
task_group_status task_status
A type that represents the terminal state of a task. Valid values are completed and canceled...
Definition: ppltasks.h:83
bool is_done() const
Determines if the task is completed.
Definition: ppltasks.h:4197
scheduler_ptr get_scheduler() const
Returns the scheduler
Definition: ppltasks.h:1213
constexpr const _Ty &() _Right
Definition: algorithm:3591
_Type _Result
Definition: ppltasks.h:633
bool _Cancel(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint=details::_TaskCreationCallstack()) const
Internal method to cancel the task_completion_event with the exception provided. Any task created usi...
Definition: ppltasks.h:2449
void _SetAsync(bool _Async=true)
Definition: ppltasks.h:1682
void _TaskInitNoFunctor(task_completion_event< void > &_Event)
Initializes a task using a task completion event.
Definition: ppltasks.h:4337
void _TaskInitMaybeFunctor(_Ty &_Param, std::false_type)
Initializes a task using a non-callable object.
Definition: ppltasks.h:3836
The cancellation_token class represents the ability to determine whether some operation has been requ...
Definition: pplcancellation_token.h:616
Callstack container, which is used to capture and preserve callstacks in ppltasks. Members of this class is examined by vc debugger, thus there will be no public access methods. Please note that names of this class should be kept stable for debugger examining.
Definition: ppltasks.h:155
_ReturnType _GetResult()
Definition: ppltasks.h:2248
__declspec(noinline)~_ExceptionHolder()
Definition: ppltasks.h:742
_ContinuationArgTypeHelper< _ReturnType, typename details::_FunctionTypeTraits< _Function, _ReturnType >::_Takes_task >::_ArgType _ArgTypeT
Definition: ppltasks.h:404
static auto _Perform(std::function< _OutType(_InpType)> _Func) -> decltype(_Func)
Definition: ppltasks.h:2807