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 
16 #pragma once
17 
18 #ifndef _PPLTASKS_H
19 #define _PPLTASKS_H
20 
21 #include <pplconcrt.h>
22 
23 // Cannot build using a compiler that is older than dev10 SP1
24 #ifdef _MSC_VER
25 #if _MSC_FULL_VER < 160040219 /*IFSTRIP=IGN*/
26 #error ERROR: Visual Studio 2010 SP1 or later is required to build ppltasks
27 #endif /*IFSTRIP=IGN*/
28 #endif
29 
30 #include <functional>
31 #include <vector>
32 #include <utility>
33 #include <exception>
34 #include <algorithm>
35 
36 #if defined (__cplusplus_winrt)
37 #include <windows.h>
38 #include <ctxtcall.h>
39 #include <agile.h>
40 #include <winapifamily.h>
41 #ifndef _UITHREADCTXT_SUPPORT
42 
43 #ifdef WINAPI_FAMILY /*IFSTRIP=IGN*/
44 
45 // It is safe to include winapifamily as WINAPI_FAMILY was defined by the user
46 #include <winapifamily.h>
47 
48 #if WINAPI_FAMILY == WINAPI_FAMILY_APP
49  // UI thread context support is not required for desktop and Windows Store apps
50  #define _UITHREADCTXT_SUPPORT 0
51 #elif WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
52  // UI thread context support is not required for desktop and Windows Store apps
53  #define _UITHREADCTXT_SUPPORT 0
54 #else /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */
55  #define _UITHREADCTXT_SUPPORT 1
56 #endif /* WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP */
57 
58 #else /* WINAPI_FAMILY */
59  // Not supported without a WINAPI_FAMILY setting.
60  #define _UITHREADCTXT_SUPPORT 0
61 #endif /* WINAPI_FAMILY */
62 
63 #endif /* _UITHREADCTXT_SUPPORT */
64 
65 #if _UITHREADCTXT_SUPPORT
66 #include <uithreadctxt.h>
67 #endif /* _UITHREADCTXT_SUPPORT */
68 
69 #pragma detect_mismatch("_PPLTASKS_WITH_WINRT", "1")
70 #else /* (__cplusplus_winrt) */
71 #pragma detect_mismatch("_PPLTASKS_WITH_WINRT", "0")
72 #endif /* #if defined(__cplusplus_winrt) */
73 
74 #ifdef _DEBUG
75  #define _DBG_ONLY(X) X
76 #else
77  #define _DBG_ONLY(X)
78 #endif // #ifdef _DEBUG
79 
80 // std::copy_exception changed to std::make_exception_ptr from VS 2010 to VS 11.
81 #ifdef _MSC_VER
82 #if _MSC_VER < 1700 /*IFSTRIP=IGN*/
83 namespace std
84 {
85  template<class _E> exception_ptr make_exception_ptr(_E _Except)
86  {
87  return copy_exception(_Except);
88  }
89 }
90 #endif
91 #ifndef _PPLTASK_ASYNC_LOGGING
92  #if _MSC_VER >= 1800 && defined(__cplusplus_winrt)
93  #define _PPLTASK_ASYNC_LOGGING 1 // Only enable async logging under dev12 winrt
94  #else
95  #define _PPLTASK_ASYNC_LOGGING 0
96  #endif
97 #endif
98 #endif
99 
100 #pragma pack(push,_CRT_PACKING)
101 
102 #pragma warning(push)
103 #pragma warning(disable: 28197)
104 #pragma warning(disable: 4100) // Unreferenced formal parameter - needed for document generation
105 #pragma warning(disable: 4127) // constant express in if condition - we use it for meta programming
106 
107 // All CRT public header files are required to be protected from the macro new
108 #pragma push_macro("new")
109 #undef new
110 
111 // stuff ported from Dev11 CRT
112 // NOTE: this doesn't actually match std::declval. it behaves differently for void!
113 // so don't blindly change it to std::declval.
114 namespace stdx
115 {
116  template<class _T>
117  _T&& declval();
118 }
119 
124 
125 namespace Concurrency
126 {
131 
133 
134 template <typename _Type> class task;
135 template <> class task<void>;
136 
137 // In debug builds, default to 10 frames, unless this is overridden prior to #includ'ing ppltasks.h. In retail builds, default to only one frame.
138 #ifndef PPL_TASK_SAVE_FRAME_COUNT
139 #ifdef _DEBUG
140 #define PPL_TASK_SAVE_FRAME_COUNT 10
141 #else
142 #define PPL_TASK_SAVE_FRAME_COUNT 1
143 #endif
144 #endif
145 
154 #if PPL_TASK_SAVE_FRAME_COUNT > 1
155 #if defined(__cplusplus_winrt) && !defined(_DEBUG)
156 #pragma message ("WARNING: Redefinning PPL_TASK_SAVE_FRAME_COUNT under Release build for non-desktop applications is not supported; only one frame will be captured!")
157 #define _CAPTURE_CALLSTACK() ::Concurrency::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
158 #else
159 #define _CAPTURE_CALLSTACK() ::Concurrency::details::_TaskCreationCallstack::_CaptureMultiFramesCallstack(PPL_TASK_SAVE_FRAME_COUNT)
160 #endif
161 #else
162 #define _CAPTURE_CALLSTACK() ::Concurrency::details::_TaskCreationCallstack::_CaptureSingleFrameCallstack(_ReturnAddress())
163 #endif
164 
165 
187 
188 inline bool __cdecl is_task_cancellation_requested()
189 {
190  return ::Concurrency::details::_TaskCollection_t::_Is_cancellation_requested();
191 }
192 
202 
203 inline __declspec(noreturn) void __cdecl cancel_current_task()
204 {
205  throw task_canceled();
206 }
207 
208 namespace details
209 {
216  {
217  private:
218  // If _M_SingleFrame != nullptr, there will be only one frame of callstacks, which is stored in _M_SingleFrame;
219  // otherwise, _M_Frame will store all the callstack frames.
221  std::vector<void *> _M_frames;
222  public:
224  {
225  _M_SingleFrame = nullptr;
226  }
227 
228  // Store one frame of callstack. This function works for both Debug / Release CRT.
230  {
232  _csc._M_SingleFrame = _SingleFrame;
233  return _csc;
234  }
235 
236  // Capture _CaptureFrames number of callstack frames. This function only work properly for Desktop or Debug CRT.
237  __declspec(noinline)
238  static _TaskCreationCallstack _CaptureMultiFramesCallstack(size_t _CaptureFrames)
239  {
241  _csc._M_frames.resize(_CaptureFrames);
242  // skip 2 frames to make sure callstack starts from user code
243  _csc._M_frames.resize(::Concurrency::details::platform::CaptureCallstack(&_csc._M_frames[0], 2, _CaptureFrames));
244  return _csc;
245  }
246  };
247  typedef unsigned char _Unit_type;
248 
256 
257  template<typename _Ty>
259  {
260  typedef _Ty _Type;
261  };
262 
263  template<>
265  {
266  typedef _Unit_type _Type;
267  };
268 
269  template<typename _T>
271  {
272  static const bool _Value = true;
273  };
274 
275  template<>
277  {
278  static const bool _Value = false;
279  };
280 
281  template <typename _Ty>
283  {
284  typedef _Ty _Type;
285  };
286 
287  template <typename _Ty>
288  struct _UnwrapTaskType<task<_Ty>>
289  {
290  typedef _Ty _Type;
291  };
292 
293  template <typename _T>
295 
297 
298 #if defined(__cplusplus_winrt)
299  template <typename _Type>
300  struct _Unhat
301  {
302  typedef _Type _Value;
303  };
304 
305  template <typename _Type>
306  struct _Unhat<_Type^>
307  {
308  typedef _Type _Value;
309  };
310 
311  value struct _NonUserType { public: int _Dummy; };
312 
313  template <typename _Type, bool _IsValueTypeOrRefType = __is_valid_winrt_type(_Type)>
314  struct _ValueTypeOrRefType
315  {
316  typedef _NonUserType _Value;
317  };
318 
319  template <typename _Type>
320  struct _ValueTypeOrRefType<_Type, true>
321  {
322  typedef _Type _Value;
323  };
324 
325  template <typename _T1, typename _T2>
326  _T2 _ProgressTypeSelector(Windows::Foundation::IAsyncOperationWithProgress<_T1,_T2>^);
327 
328  template <typename _T1>
329  _T1 _ProgressTypeSelector(Windows::Foundation::IAsyncActionWithProgress<_T1>^);
330 
331  template <typename _Type>
332  struct _GetProgressType
333  {
334  typedef decltype(_ProgressTypeSelector(stdx::declval<_Type>())) _Value;
335  };
336 
337  template <typename _Type>
338  struct _IsIAsyncInfo
339  {
340  static const bool _Value = __is_base_of(Windows::Foundation::IAsyncInfo, typename _Unhat<_Type>::_Value);
341  };
342 
343  template <typename _T>
344  _TypeSelectorAsyncOperation _AsyncOperationKindSelector(Windows::Foundation::IAsyncOperation<_T>^);
345 
346  _TypeSelectorAsyncAction _AsyncOperationKindSelector(Windows::Foundation::IAsyncAction^);
347 
348  template <typename _T1, typename _T2>
349  _TypeSelectorAsyncOperationWithProgress _AsyncOperationKindSelector(Windows::Foundation::IAsyncOperationWithProgress<_T1, _T2>^);
350 
351  template <typename _T>
352  _TypeSelectorAsyncActionWithProgress _AsyncOperationKindSelector(Windows::Foundation::IAsyncActionWithProgress<_T>^);
353 
355  struct _TaskTypeTraits
356  {
357  typedef typename _UnwrapTaskType<_Type>::_Type _TaskRetType;
358  typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind;
359  typedef typename _NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
360 
361  static const bool _IsAsyncTask = _IsAsync;
362  static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
363  };
364 
365  template<typename _Type>
366  struct _TaskTypeTraits<_Type, true >
367  {
368  typedef decltype(((_Type)nullptr)->GetResults()) _TaskRetType;
369  typedef _TaskRetType _NormalizedTaskRetType;
370  typedef decltype(_AsyncOperationKindSelector((_Type)nullptr)) _AsyncKind;
371 
372  static const bool _IsAsyncTask = true;
373  static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
374  };
375 
376 #else /* defined (__cplusplus_winrt) */
377  template <typename _Type>
379  {
380  static const bool _Value = false;
381  };
382 
383  template <typename _Type, bool _IsAsync = false>
385  {
387  typedef decltype(_AsyncOperationKindSelector(stdx::declval<_Type>())) _AsyncKind;
388  typedef typename _NormalizeVoidToUnitType<_TaskRetType>::_Type _NormalizedTaskRetType;
389 
390  static const bool _IsAsyncTask = false;
391  static const bool _IsUnwrappedTaskOrAsync = _IsUnwrappedAsyncSelector<_AsyncKind>::_Value;
392  };
393 #endif /* defined (__cplusplus_winrt) */
394 
395  template <typename _Function> auto _IsCallable(_Function _Func, int) -> decltype(_Func(), std::true_type()) { (_Func); return std::true_type(); }
396  template <typename _Function> std::false_type _IsCallable(_Function, ...) { return std::false_type(); }
397 
398  template <>
400  {
401  typedef void _TaskRetType;
403  typedef _Unit_type _NormalizedTaskRetType;
404 
405  static const bool _IsAsyncTask = false;
406  static const bool _IsUnwrappedTaskOrAsync = false;
407  };
408 
409  template<typename _Type>
410  task<_Type> _To_task(_Type t);
411 
413 
415 
416  template <typename _Function, typename _Type> auto _ReturnTypeHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t)));
417  template <typename _Function, typename _Type> auto _ReturnTypeHelper(_Type t, _Function _Func, int, ...) -> decltype(_Func(t));
418  template <typename _Function, typename _Type> auto _ReturnTypeHelper(_Type t, _Function _Func, ...) -> _BadContinuationParamType;
419 
420  template <typename _Function, typename _Type> auto _IsTaskHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t)), std::true_type());
421  template <typename _Function, typename _Type> std::false_type _IsTaskHelper(_Type t, _Function _Func, int, ...);
422 
423  template <typename _Function> auto _VoidReturnTypeHelper(_Function _Func, int, int) -> decltype(_Func(_To_task()));
424  template <typename _Function> auto _VoidReturnTypeHelper(_Function _Func, int, ...) -> decltype(_Func());
425 
426  template <typename _Function> auto _VoidIsTaskHelper(_Function _Func, int, int) -> decltype(_Func(_To_task()), std::true_type());
427  template <typename _Function> std::false_type _VoidIsTaskHelper(_Function _Func, int, ...);
428 
429  template<typename _Function, typename _ExpectedParameterType>
431  {
432  typedef decltype(_ReturnTypeHelper(stdx::declval<_ExpectedParameterType>(),stdx::declval<_Function>(), 0, 0)) _FuncRetType;
433  static_assert(!std::is_same<_FuncRetType,_BadContinuationParamType>::value, "incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below)");
434 
435  typedef decltype(_IsTaskHelper(stdx::declval<_ExpectedParameterType>(),stdx::declval<_Function>(), 0, 0)) _Takes_task;
436  };
437 
438  template<typename _Function>
439  struct _FunctionTypeTraits<_Function, void>
440  {
441  typedef decltype(_VoidReturnTypeHelper(stdx::declval<_Function>(), 0, 0)) _FuncRetType;
442  typedef decltype(_VoidIsTaskHelper(stdx::declval<_Function>(), 0, 0)) _Takes_task;
443  };
444 
445  template<typename _Function, typename _ReturnType>
447  {
449  };
450 
451  // _InitFunctorTypeTraits is used to decide whether a task constructed with a lambda should be unwrapped. Depending on how the variable is
452  // declared, the constructor may or may not perform unwrapping. For eg.
453  //
454  // This declaration SHOULD NOT cause unwrapping
455  // task<task<void>> t1([]() -> task<void> {
456  // task<void> t2([]() {});
457  // return t2;
458  // });
459  //
460  // This declaration SHOULD cause unwrapping
461  // task<void>> t1([]() -> task<void> {
462  // task<void> t2([]() {});
463  // return t2;
464  // });
465  // 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.
466  template <typename _TaskType, typename _FuncRetType>
468  {
470  static const bool _IsAsyncTask = _TaskTypeTraits<_FuncRetType>::_IsAsyncTask;
471  static const bool _IsUnwrappedTaskOrAsync = _TaskTypeTraits<_FuncRetType>::_IsUnwrappedTaskOrAsync;
472  };
473 
474  template<typename T>
476  {
478  static const bool _IsAsyncTask = false;
479  static const bool _IsUnwrappedTaskOrAsync = false;
480  };
481 
486  {
487  _TaskProcThunk(const std::function<void ()> & _Callback) :
488  _M_func(_Callback)
489  {
490  }
491 
492  static void __cdecl _Bridge(void *_PData)
493  {
494  _TaskProcThunk *_PThunk = reinterpret_cast<_TaskProcThunk *>(_PData);
495  _Holder _ThunkHolder(_PThunk);
496  _PThunk->_M_func();
497  }
498  private:
499 
500  // RAII holder
501  struct _Holder
502  {
503  _Holder(_TaskProcThunk * _PThunk) : _M_pThunk(_PThunk)
504  {
505  }
506 
508  {
509  delete _M_pThunk;
510  }
511 
513 
514  private:
515  _Holder& operator=(const _Holder&);
516  };
517 
518  std::function<void()> _M_func;
519  _TaskProcThunk& operator=(const _TaskProcThunk&);
520  };
521 
533  static void _ScheduleFuncWithAutoInline(const std::function<void ()> & _Func, _TaskInliningMode_t _InliningMode)
534  {
536  }
537 
539  {
540  typedef std::function<void(void)> _CallbackFunction;
541 
542 #if defined (__cplusplus_winrt)
543 
544  public:
545 
546  static _ContextCallback _CaptureCurrent()
547  {
549  _Context._Capture();
550  return _Context;
551  }
552 
554  {
555  _Reset();
556  }
557 
558  _ContextCallback(bool _DeferCapture = false)
559  {
560  if (_DeferCapture)
561  {
562  _M_context._M_captureMethod = _S_captureDeferred;
563  }
564  else
565  {
566  _M_context._M_pContextCallback = nullptr;
567  }
568  }
569 
570  // Resolves a context that was created as _S_captureDeferred based on the environment (ancestor, current context).
571  void _Resolve(bool _CaptureCurrent)
572  {
573  if(_M_context._M_captureMethod == _S_captureDeferred)
574  {
575  _M_context._M_pContextCallback = nullptr;
576 
577  if (_CaptureCurrent)
578  {
579  if (_IsCurrentOriginSTA())
580  {
581  _Capture();
582  }
583 #if _UITHREADCTXT_SUPPORT
584  else
585  {
586  // This method will fail if not called from the UI thread.
587  HRESULT _Hr = CaptureUiThreadContext(&_M_context._M_pContextCallback);
588  if (FAILED(_Hr))
589  {
590  _M_context._M_pContextCallback = nullptr;
591  }
592  }
593 #endif /* _UITHREADCTXT_SUPPORT */
594  }
595  }
596  }
597 
598  void _Capture()
599  {
600  HRESULT _Hr = CoGetObjectContext(IID_IContextCallback, reinterpret_cast<void **>(&_M_context._M_pContextCallback));
601  if (FAILED(_Hr))
602  {
603  _M_context._M_pContextCallback = nullptr;
604  }
605  }
606 
607  _ContextCallback(const _ContextCallback& _Src)
608  {
609  _Assign(_Src._M_context._M_pContextCallback);
610  }
611 
612  _ContextCallback(_ContextCallback&& _Src)
613  {
614  _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
615  _Src._M_context._M_pContextCallback = nullptr;
616  }
617 
618  _ContextCallback& operator=(const _ContextCallback& _Src)
619  {
620  if (this != &_Src)
621  {
622  _Reset();
623  _Assign(_Src._M_context._M_pContextCallback);
624  }
625  return *this;
626  }
627 
628  _ContextCallback& operator=(_ContextCallback&& _Src)
629  {
630  if (this != &_Src)
631  {
632  _M_context._M_pContextCallback = _Src._M_context._M_pContextCallback;
633  _Src._M_context._M_pContextCallback = nullptr;
634  }
635  return *this;
636  }
637 
638  bool _HasCapturedContext() const
639  {
640  _ASSERTE(_M_context._M_captureMethod != _S_captureDeferred);
641  return (_M_context._M_pContextCallback != nullptr);
642  }
643 
644  void _CallInContext(_CallbackFunction _Func) const
645  {
646  if (!_HasCapturedContext())
647  {
648  _Func();
649  }
650  else
651  {
652  ComCallData callData;
653  ZeroMemory(&callData, sizeof(callData));
654  callData.pUserDefined = reinterpret_cast<void *>(&_Func);
655 
656  HRESULT _Hr = _M_context._M_pContextCallback->ContextCallback(&_Bridge, &callData, IID_ICallbackWithNoReentrancyToApplicationSTA, 5, nullptr);
657  if (FAILED(_Hr))
658  {
659  throw ::Platform::Exception::CreateException(_Hr);
660  }
661  }
662  }
663 
664  bool operator==(const _ContextCallback& _Rhs) const
665  {
666  return (_M_context._M_pContextCallback == _Rhs._M_context._M_pContextCallback);
667  }
668 
669  bool operator!=(const _ContextCallback& _Rhs) const
670  {
671  return !(operator==(_Rhs));
672  }
673 
674  private:
675  void _Reset()
676  {
677  if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr)
678  {
679  _M_context._M_pContextCallback->Release();
680  }
681  }
682 
683  void _Assign(IContextCallback *_PContextCallback)
684  {
685  _M_context._M_pContextCallback = _PContextCallback;
686  if (_M_context._M_captureMethod != _S_captureDeferred && _M_context._M_pContextCallback != nullptr)
687  {
688  _M_context._M_pContextCallback->AddRef();
689  }
690  }
691 
692  static HRESULT __stdcall _Bridge(ComCallData *_PParam)
693  {
694  _CallbackFunction *pFunc = reinterpret_cast<_CallbackFunction *>(_PParam->pUserDefined);
695  (*pFunc)();
696  return S_OK;
697  }
698 
699  // Returns the origin information for the caller (runtime / Windows Runtime apartment as far as task continuations need know)
700  static bool _IsCurrentOriginSTA()
701  {
702  APTTYPE _AptType;
703  APTTYPEQUALIFIER _AptTypeQualifier;
704 
705  HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier);
706  if (SUCCEEDED(hr))
707  {
708  // We determine the origin of a task continuation by looking at where .then is called, so we can tell whether
709  // to need to marshal the continuation back to the originating apartment. If an STA thread is in executing in
710  // a neutral aparment when it schedules a continuation, we will not marshal continuations back to the STA,
711  // since variables used within a neutral apartment are expected to be apartment neutral.
712  switch(_AptType)
713  {
714  case APTTYPE_MAINSTA:
715  case APTTYPE_STA:
716  return true;
717  default:
718  break;
719  }
720  }
721  return false;
722  }
723 
724  union
725  {
726  IContextCallback *_M_pContextCallback;
727  size_t _M_captureMethod;
728  } _M_context;
729 
730  static const size_t _S_captureDeferred = 1;
731 #else /* defined (__cplusplus_winrt) */
732  public:
733 
735  {
736  return _ContextCallback();
737  }
738 
739  _ContextCallback(bool = false)
740  {
741  }
742 
744  {
745  }
746 
748  {
749  }
750 
752  {
753  return *this;
754  }
755 
757  {
758  return *this;
759  }
760 
761  bool _HasCapturedContext() const
762  {
763  return false;
764  }
765 
766  void _Resolve(bool) const
767  {
768  }
769 
770  void _CallInContext(_CallbackFunction _Func) const
771  {
772  _Func();
773  }
774 
775  bool operator==(const _ContextCallback&) const
776  {
777  return true;
778  }
779 
780  bool operator!=(const _ContextCallback&) const
781  {
782  return false;
783  }
784 
785 #endif /* defined (__cplusplus_winrt) */
786  };
787 
788  template<typename _Type>
790  {
791  void Set(const _Type& _type)
792  {
793  _Result = _type;
794  }
795 
796  _Type Get()
797  {
798  return _Result;
799  }
800 
801  _Type _Result;
802  };
803 
804 #if defined (__cplusplus_winrt)
805 
806  template<typename _Type>
807  struct _ResultHolder<_Type^>
808  {
809  void Set(_Type^ const & _type)
810  {
811  _M_Result = _type;
812  }
813 
814  _Type^ Get()
815  {
816  return _M_Result.Get();
817  }
818  private:
819  // ::Platform::Agile handle specialization of all hats
820  // including ::Platform::String and ::Platform::Array
821  ::Platform::Agile<_Type^> _M_Result;
822  };
823 
824  //
825  // The below are for composability with tasks auto-created from when_any / when_all / && / || constructs.
826  //
827  template<typename _Type>
828  struct _ResultHolder<std::vector<_Type^>>
829  {
830  void Set(const std::vector<_Type^>& _type)
831  {
832  _Result.reserve(_type.size());
833 
834  for (auto _PTask = _type.begin(); _PTask != _type.end(); ++_PTask)
835  {
836  _Result.emplace_back(*_PTask);
837  }
838  }
839 
840  std::vector<_Type^> Get()
841  {
842  // Return vectory<T^> with the objects that are marshaled in the proper appartment
843  std::vector<_Type^> _Return;
844  _Return.reserve(_Result.size());
845 
846  for (auto _PTask = _Result.begin(); _PTask != _Result.end(); ++_PTask)
847  {
848  _Return.push_back(_PTask->Get()); // Platform::Agile will marshal the object to appropriate appartment if neccessary
849  }
850 
851  return _Return;
852  }
853 
854  std::vector< ::Platform::Agile<_Type^> > _Result;
855  };
856 
857  template<typename _Type>
858  struct _ResultHolder<std::pair<_Type^, void*> >
859  {
860  void Set(const std::pair<_Type^, size_t>& _type)
861  {
862  _M_Result = _type;
863  }
864 
865  std::pair<_Type^, size_t> Get()
866  {
867  return std::make_pair(_M_Result.first.Get(), _M_Result.second);
868  }
869  private:
870  std::pair< ::Platform::Agile<_Type^>, size_t> _M_Result;
871  };
872 
873 #endif /* defined (__cplusplus_winrt) */
874 
875  // 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.
876  // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception
877  // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast.
879  {
880  private:
882  {
883 #if defined (__cplusplus_winrt)
884  if (_M_winRTException != nullptr)
885  {
887  }
888 #endif /* defined (__cplusplus_winrt) */
889  }
890  public:
891  explicit _ExceptionHolder(const std::exception_ptr& _E, const _TaskCreationCallstack &_stackTrace) :
892  _M_exceptionObserved(0), _M_stdException(_E), _M_stackTrace(_stackTrace)
893 #if defined (__cplusplus_winrt)
894  , _M_winRTException(nullptr)
895 #endif /* defined (__cplusplus_winrt) */
896  {
897  }
898 
899 #if defined (__cplusplus_winrt)
900  explicit _ExceptionHolder(::Platform::Exception^ _E, const _TaskCreationCallstack &_stackTrace) :
901  _M_exceptionObserved(0), _M_winRTException(_E), _M_stackTrace(_stackTrace)
902  {
903  }
904 #endif /* defined (__cplusplus_winrt) */
905 
906  __declspec(noinline)
908  {
909  if (_M_exceptionObserved == 0)
910  {
911  // If you are trapped here, it means an exception thrown in task chain didn't get handled.
912  // Please add task-based continuation to handle all exceptions coming from tasks.
913  // this->_M_stackTrace keeps the creation callstack of the task generates this exception.
915  }
916  }
917 
919  {
920  if (_M_exceptionObserved == 0)
921  {
922  atomic_exchange(_M_exceptionObserved, 1l);
923  }
924 
925 #if defined (__cplusplus_winrt)
926  if (_M_winRTException != nullptr)
927  {
928  throw _M_winRTException;
929  }
930 #endif /* defined (__cplusplus_winrt) */
931  std::rethrow_exception(_M_stdException);
932  }
933 
934  // A variable that remembers if this exception was every rethrown into user code (and hence handled by the user). Exceptions that
935  // are unobserved when the exception holder is destructed will terminate the process.
937 
938  // Either _M_stdException or _M_winRTException is populated based on the type of exception encountered.
939  std::exception_ptr _M_stdException;
940 #if defined (__cplusplus_winrt)
941  ::Platform::Exception^ _M_winRTException;
942 #endif /* defined (__cplusplus_winrt) */
943 
944  // Disassembling this value will point to a source instruction right after a call instruction. If the call is to create_task,
945  // a task constructor or the then method, the task created by that method is the one that encountered this exception. If the call
946  // is to task_completion_event::set_exception, the set_exception method was the source of the exception.
947  // DO NOT REMOVE THIS VARIABLE. It is extremely helpful for debugging.
949 
950  };
951 
952 #if defined (__cplusplus_winrt)
953  template<typename _AsyncOperationType, typename _CompletionHandlerType, typename _Result>
957  ref struct _AsyncInfoImpl abstract : Windows::Foundation::IAsyncOperation<_Result>
958  {
959  internal:
960  // The async action, action with progress or operation with progress that this stub forwards to.
962 
963  Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ _M_CompletedHandler;
964 
965  _AsyncInfoImpl( _AsyncOperationType _AsyncInfo ) : _M_asyncInfo(_AsyncInfo) {}
966 
967  public:
968  virtual void Cancel() { _M_asyncInfo.Get()->Cancel(); }
969  virtual void Close() { _M_asyncInfo.Get()->Close(); }
970 
971  virtual property Windows::Foundation::HResult ErrorCode
972  {
973  Windows::Foundation::HResult get()
974  {
975  return _M_asyncInfo.Get()->ErrorCode;
976  }
977  }
978 
979  virtual property UINT Id
980  {
981  UINT get()
982  {
983  return _M_asyncInfo.Get()->Id;
984  }
985  }
986 
987  virtual property Windows::Foundation::AsyncStatus Status
988  {
989  Windows::Foundation::AsyncStatus get()
990  {
991  return _M_asyncInfo.Get()->Status;
992  }
993  }
994 
995  virtual _Result GetResults() { throw std::runtime_error("derived class must implement"); }
996 
997  virtual property Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ Completed
998  {
999  Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ get()
1000  {
1001  return _M_CompletedHandler;
1002  }
1003 
1004  void set(Windows::Foundation::AsyncOperationCompletedHandler<_Result>^ value)
1005  {
1006  _M_CompletedHandler = value;
1007  _M_asyncInfo.Get()->Completed = ref new _CompletionHandlerType([&](_AsyncOperationType, Windows::Foundation::AsyncStatus status) {
1008  _M_CompletedHandler->Invoke(this, status);
1009  });
1010  }
1011  }
1012  };
1013 
1017  template<typename _Result, typename _Progress>
1018  ref struct _IAsyncOperationWithProgressToAsyncOperationConverter sealed :
1019  _AsyncInfoImpl<Windows::Foundation::IAsyncOperationWithProgress<_Result,_Progress>^,
1020  Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_Result,_Progress>,
1021  _Result>
1022  {
1023  internal:
1024  _IAsyncOperationWithProgressToAsyncOperationConverter(Windows::Foundation::IAsyncOperationWithProgress<_Result,_Progress>^ _Operation) :
1025  _AsyncInfoImpl<Windows::Foundation::IAsyncOperationWithProgress<_Result,_Progress>^,
1026  Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_Result,_Progress>,
1027  _Result>(_Operation) {}
1028 
1029  public:
1030  virtual _Result GetResults() override { return _M_asyncInfo.Get()->GetResults(); }
1031  };
1032 
1036  ref struct _IAsyncActionToAsyncOperationConverter sealed :
1037  _AsyncInfoImpl<Windows::Foundation::IAsyncAction^,
1038  Windows::Foundation::AsyncActionCompletedHandler,
1039  details::_Unit_type>
1040  {
1041  internal:
1042  _IAsyncActionToAsyncOperationConverter(Windows::Foundation::IAsyncAction^ _Operation) :
1043  _AsyncInfoImpl<Windows::Foundation::IAsyncAction^,
1044  Windows::Foundation::AsyncActionCompletedHandler,
1045  details::_Unit_type>(_Operation) {}
1046 
1047  public:
1048  virtual details::_Unit_type GetResults() override
1049  {
1050  // Invoke GetResults on the IAsyncAction to allow exceptions to be thrown to higher layers before returning a dummy value.
1051  _M_asyncInfo.Get()->GetResults();
1052  return details::_Unit_type();
1053  }
1054  };
1055 
1059  template<typename _Progress>
1060  ref struct _IAsyncActionWithProgressToAsyncOperationConverter sealed :
1061  _AsyncInfoImpl<Windows::Foundation::IAsyncActionWithProgress<_Progress>^,
1062  Windows::Foundation::AsyncActionWithProgressCompletedHandler<_Progress>,
1063  details::_Unit_type>
1064  {
1065  internal:
1066  _IAsyncActionWithProgressToAsyncOperationConverter(Windows::Foundation::IAsyncActionWithProgress<_Progress>^ _Action) :
1067  _AsyncInfoImpl<Windows::Foundation::IAsyncActionWithProgress<_Progress>^,
1068  Windows::Foundation::AsyncActionWithProgressCompletedHandler<_Progress>,
1069  details::_Unit_type>(_Action) {}
1070  public:
1071  virtual details::_Unit_type GetResults() override
1072  {
1073  // Invoke GetResults on the IAsyncActionWithProgress to allow exceptions to be thrown before returning a dummy value.
1074  _M_asyncInfo.Get()->GetResults();
1075  return details::_Unit_type();
1076  }
1077  };
1078 #endif /* defined (__cplusplus_winrt) */
1079 } // namespace details
1080 
1087 
1089 {
1090 public:
1091 
1108 
1110  {
1111 #if defined (__cplusplus_winrt)
1112  // The callback context is created with the context set to CaptureDeferred and resolved when it is used in .then()
1113  return task_continuation_context(true); // sets it to deferred, is resolved in the constructor of _ContinuationTaskHandle
1114 #else /* defined (__cplusplus_winrt) */
1115  return task_continuation_context();
1116 #endif /* defined (__cplusplus_winrt) */
1117  }
1118 
1119 #if defined (__cplusplus_winrt)
1120 
1134  static task_continuation_context use_arbitrary()
1135  {
1136  task_continuation_context _Arbitrary(true);
1137  _Arbitrary._Resolve(false);
1138  return _Arbitrary;
1139  }
1140 
1154 
1155  static task_continuation_context use_current()
1156  {
1157  task_continuation_context _Current(true);
1158  _Current._Resolve(true);
1159  return _Current;
1160  }
1161 #endif /* defined (__cplusplus_winrt) */
1162 
1163 private:
1164 
1165  task_continuation_context(bool _DeferCapture = false) : details::_ContextCallback(_DeferCapture)
1166  {
1167  }
1168 };
1169 
1170 class task_options;
1171 namespace details
1172 {
1174  {
1177 
1179  {
1180  _M_hasPresetCreationCallstack = true;
1181  _M_presetCreationCallstack = _callstack;
1182  }
1184  {
1185  _M_hasPresetCreationCallstack = false;
1186  }
1187  };
1188 
1189  inline _Internal_task_options &_get_internal_task_options(task_options &options);
1190  inline const _Internal_task_options &_get_internal_task_options(const task_options &options);
1191 }
1196 {
1197 public:
1198 
1199 
1204  : _M_Scheduler(get_ambient_scheduler()),
1205  _M_CancellationToken(cancellation_token::none()),
1206  _M_ContinuationContext(task_continuation_context::use_default()),
1207  _M_HasCancellationToken(false),
1208  _M_HasScheduler(false)
1209  {
1210  }
1211 
1216  : _M_Scheduler(get_ambient_scheduler()),
1217  _M_CancellationToken(_Token),
1218  _M_ContinuationContext(task_continuation_context::use_default()),
1219  _M_HasCancellationToken(true),
1220  _M_HasScheduler(false)
1221  {
1222  }
1223 
1228  : _M_Scheduler(get_ambient_scheduler()),
1229  _M_CancellationToken(cancellation_token::none()),
1230  _M_ContinuationContext(_ContinuationContext),
1231  _M_HasCancellationToken(false),
1232  _M_HasScheduler(false)
1233  {
1234  }
1235 
1240  : _M_Scheduler(get_ambient_scheduler()),
1241  _M_CancellationToken(_Token),
1242  _M_ContinuationContext(_ContinuationContext),
1243  _M_HasCancellationToken(false),
1244  _M_HasScheduler(false)
1245  {
1246  }
1247 
1251  template<typename _SchedType>
1252  task_options(std::shared_ptr<_SchedType> _Scheduler)
1253  : _M_Scheduler(std::move(_Scheduler)),
1254  _M_CancellationToken(cancellation_token::none()),
1255  _M_ContinuationContext(task_continuation_context::use_default()),
1256  _M_HasCancellationToken(false),
1257  _M_HasScheduler(true)
1258  {
1259  }
1260 
1264  task_options(scheduler_interface& _Scheduler)
1265  : _M_Scheduler(&_Scheduler),
1266  _M_CancellationToken(cancellation_token::none()),
1267  _M_ContinuationContext(task_continuation_context::use_default()),
1268  _M_HasCancellationToken(false),
1269  _M_HasScheduler(true)
1270  {
1271  }
1272 
1277  : _M_Scheduler(std::move(_Scheduler)),
1278  _M_CancellationToken(cancellation_token::none()),
1279  _M_ContinuationContext(task_continuation_context::use_default()),
1280  _M_HasCancellationToken(false),
1281  _M_HasScheduler(true)
1282  {
1283  }
1284 
1288  task_options(const task_options& _TaskOptions)
1289  : _M_Scheduler(_TaskOptions.get_scheduler()),
1290  _M_CancellationToken(_TaskOptions.get_cancellation_token()),
1291  _M_ContinuationContext(_TaskOptions.get_continuation_context()),
1292  _M_HasCancellationToken(_TaskOptions.has_cancellation_token()),
1293  _M_HasScheduler(_TaskOptions.has_scheduler())
1294  {
1295  }
1296 
1301  {
1302  _M_CancellationToken = _Token;
1303  _M_HasCancellationToken = true;
1304  }
1305 
1310  {
1311  _M_ContinuationContext = _ContinuationContext;
1312  }
1313 
1318  {
1319  return _M_HasCancellationToken;
1320  }
1321 
1326  {
1327  return _M_CancellationToken;
1328  }
1329 
1334  {
1335  return _M_ContinuationContext;
1336  }
1337 
1341  bool has_scheduler() const
1342  {
1343  return _M_HasScheduler;
1344  }
1345 
1350  {
1351  return _M_Scheduler;
1352  }
1353 
1354 private:
1355 
1356  task_options const& operator=(task_options const& _Right);
1359 
1366 };
1367 
1368 namespace details
1369 {
1371  {
1372  return options._M_InternalTaskOptions;
1373  }
1375  {
1376  return options._M_InternalTaskOptions;
1377  }
1378 
1379  struct _Task_impl_base;
1380  template<typename _ReturnType> struct _Task_impl;
1381 
1382  template<typename _ReturnType>
1383  struct _Task_ptr
1384  {
1385  typedef std::shared_ptr<_Task_impl<_ReturnType>> _Type;
1386  static _Type _Make(_CancellationTokenState * _Ct, scheduler_ptr _Scheduler_arg) { return std::make_shared<_Task_impl<_ReturnType>>(_Ct, _Scheduler_arg); }
1387  };
1388 
1390  typedef std::shared_ptr<_Task_impl_base> _Task_ptr_base;
1391 
1392  // The weak-typed base task handler for continuation tasks.
1393  struct _ContinuationTaskHandleBase : _UnrealizedChore_t
1394  {
1398 
1399  // This field gives inlining scheduling policy for current chore.
1401 
1402  virtual _Task_ptr_base _GetTaskImplBase() const = 0;
1403 
1405  _M_next(nullptr), _M_continuationContext(task_continuation_context::use_default()), _M_isTaskBasedContinuation(false), _M_inliningMode(details::_NoInline)
1406  {
1407  }
1408 
1410  };
1411 
1412 #if _PPLTASK_ASYNC_LOGGING
1413  // GUID used for identifying causality logs from PPLTask
1414  const ::Platform::Guid _PPLTaskCausalityPlatformID(0x7A76B220, 0xA758, 0x4E6E, 0xB0, 0xE0, 0xD7, 0xC6, 0xD7, 0x4A, 0x88, 0xFE);
1415 
1416  __declspec(selectany) volatile long _isCausalitySupported = 0;
1417 
1418  inline bool _IsCausalitySupported()
1419  {
1420 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
1421  if (_isCausalitySupported == 0)
1422  {
1423  long _causality = 1;
1424  OSVERSIONINFOEX _osvi = {};
1425  _osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
1426 
1427  // The Causality is supported on Windows version higher than Windows 8
1428  _osvi.dwMajorVersion = 6;
1429  _osvi.dwMinorVersion = 3;
1430 
1431  DWORDLONG _conditionMask = 0;
1432  VER_SET_CONDITION( _conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
1433  VER_SET_CONDITION( _conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL );
1434 
1435  if ( ::VerifyVersionInfo(&_osvi, VER_MAJORVERSION | VER_MINORVERSION, _conditionMask))
1436  {
1437  _causality = 2;
1438  }
1439 
1440  _isCausalitySupported = _causality;
1441  return _causality == 2;
1442  }
1443 
1444  return _isCausalitySupported == 2 ? true : false;
1445 #else
1446  return true;
1447 #endif
1448  }
1449 
1450  // Stateful logger rests inside task_impl_base.
1451  struct _TaskEventLogger
1452  {
1453  _Task_impl_base *_M_task;
1454  bool _M_scheduled;
1455  bool _M_taskPostEventStarted;
1456 
1457  // Log before scheduling task
1458  void _LogScheduleTask(bool _isContinuation)
1459  {
1460  if (details::_IsCausalitySupported())
1461  {
1462  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCreation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1463  _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task),
1464  _isContinuation ? "Concurrency::PPLTask::ScheduleContinuationTask" : "Concurrency::PPLTask::ScheduleTask", 0);
1465  _M_scheduled = true;
1466  }
1467  }
1468 
1469  // It will log the cancel event but not canceled state. _LogTaskCompleted will log the terminal state, which includes cancel state.
1470  void _LogCancelTask()
1471  {
1472  if (details::_IsCausalitySupported())
1473  {
1474  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationRelation(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Important, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1475  _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), ::Windows::Foundation::Diagnostics::CausalityRelation::Cancel);
1476 
1477  }
1478  }
1479 
1480  // Log when task reaches terminal state. Note: the task can reach a terminal state (by cancellation or exception) without having run
1481  void _LogTaskCompleted();
1482 
1483  // Log when task body (which includes user lambda and other scheduling code) begin to run
1484  void _LogTaskExecutionStarted() { }
1485 
1486  // Log when task body finish executing
1487  void _LogTaskExecutionCompleted()
1488  {
1489  if (_M_taskPostEventStarted && details::_IsCausalitySupported())
1490  {
1491  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkCompletion(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1492  ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::CompletionNotification);
1493  }
1494  }
1495 
1496  // Log right before user lambda being invoked
1497  void _LogWorkItemStarted()
1498  {
1499  if (details::_IsCausalitySupported())
1500  {
1501  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkStart(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1502  _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::Execution);
1503  }
1504  }
1505 
1506  // Log right after user lambda being invoked
1507  void _LogWorkItemCompleted()
1508  {
1509  if (details::_IsCausalitySupported())
1510  {
1511  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkCompletion(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1512  ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::Execution);
1513 
1514  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceSynchronousWorkStart(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
1515  _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), ::Windows::Foundation::Diagnostics::CausalitySynchronousWork::CompletionNotification);
1516  _M_taskPostEventStarted = true;
1517  }
1518  }
1519 
1520  _TaskEventLogger(_Task_impl_base *_task): _M_task(_task)
1521  {
1522  _M_scheduled = false;
1523  _M_taskPostEventStarted = false;
1524  }
1525  };
1526 
1527  // Exception safe logger for user lambda
1528  struct _TaskWorkItemRAIILogger
1529  {
1530  _TaskEventLogger &_M_logger;
1531  _TaskWorkItemRAIILogger(_TaskEventLogger &_taskHandleLogger): _M_logger(_taskHandleLogger)
1532  {
1533  _M_logger._LogWorkItemStarted();
1534  }
1535 
1536  ~_TaskWorkItemRAIILogger()
1537  {
1538  _M_logger._LogWorkItemCompleted();
1539  }
1540  _TaskWorkItemRAIILogger &operator =(const _TaskWorkItemRAIILogger &); // cannot be assigned
1541  };
1542 
1543 #else
1546  {
1547  void _LogScheduleTask(bool) {}
1548  void _LogCancelTask() {}
1555  };
1557  {
1559  };
1560 #endif
1561 
1577  template<typename _ReturnType, typename _DerivedTaskHandle, typename _BaseTaskHandle>
1578  struct _PPLTaskHandle : _BaseTaskHandle
1579  {
1580  _PPLTaskHandle(const typename _Task_ptr<_ReturnType>::_Type & _PTask) : _M_pTask(_PTask)
1581  {
1582  }
1583 
1584  virtual ~_PPLTaskHandle()
1585  {
1586  // Here is the sink of all task completion code paths
1587  _M_pTask->_M_taskEventLogger._LogTaskCompleted();
1588  }
1589 
1590  virtual void invoke() const
1591  {
1592  // All exceptions should be rethrown to finish cleanup of the task collection. They will be caught and handled
1593  // by the runtime.
1594  _ASSERTE((bool)_M_pTask);
1595  if (!_M_pTask->_TransitionedToStarted())
1596  {
1597  static_cast<const _DerivedTaskHandle *>(this)->_SyncCancelAndPropagateException();
1598  return;
1599  }
1600 
1601  _M_pTask->_M_taskEventLogger._LogTaskExecutionStarted();
1602  try
1603  {
1604  // All derived task handle must implement this contract function.
1605  static_cast<const _DerivedTaskHandle *>(this)->_Perform();
1606  }
1607  catch(const task_canceled &)
1608  {
1609  _M_pTask->_Cancel(true);
1610  }
1611  catch(const _Interruption_exception &)
1612  {
1613  _M_pTask->_Cancel(true);
1614  }
1615 #if defined (__cplusplus_winrt)
1616  catch(::Platform::Exception^ _E)
1617  {
1618  _M_pTask->_CancelWithException(_E);
1619  }
1620 #endif /* defined (__cplusplus_winrt) */
1621  catch(...)
1622  {
1623  _M_pTask->_CancelWithException(std::current_exception());
1624  }
1625  _M_pTask->_M_taskEventLogger._LogTaskExecutionCompleted();
1626  }
1627 
1628  // Cast _M_pTask pointer to "type-less" _Task_impl_base pointer, which can be used in _ContinuationTaskHandleBase.
1629  // The return value should be automatically optimized by R-value ref.
1630  _Task_ptr_base _GetTaskImplBase() const
1631  {
1632  return _M_pTask;
1633  }
1634 
1636  private:
1637  _PPLTaskHandle const & operator=(_PPLTaskHandle const&); // no assignment operator
1638  };
1639 
1644 
1646  {
1648  {
1649  // Tracks the state of the task, rather than the task collection on which the task is scheduled
1655  };
1656 
1657  _Task_impl_base(_CancellationTokenState * _PTokenState, scheduler_ptr _Scheduler_arg)
1658  : _M_TaskState(_Created),
1659  _M_fFromAsync(false), _M_fUnwrappedTask(false),
1660  _M_pRegistration(nullptr), _M_Continuations(nullptr), _M_TaskCollection(_Scheduler_arg),
1661  _M_taskEventLogger(this)
1662  {
1663  // Set cancelation token
1664  _M_pTokenState = _PTokenState;
1665  _ASSERTE(_M_pTokenState != nullptr);
1666  if (_M_pTokenState != _CancellationTokenState::_None())
1667  _M_pTokenState->_Reference();
1668  }
1669 
1671  {
1672  _ASSERTE(_M_pTokenState != nullptr);
1673  if (_M_pTokenState != _CancellationTokenState::_None())
1674  {
1675  _M_pTokenState->_Release();
1676  }
1677  }
1678 
1679  task_status _Wait()
1680  {
1681  bool _DoWait = true;
1682 
1683 #if defined (__cplusplus_winrt)
1684  if (_IsNonBlockingThread())
1685  {
1686  // In order to prevent Windows Runtime STA threads from blocking the UI, calling task.wait() task.get() is illegal
1687  // if task has not been completed.
1688  if (!_IsCompleted() && !_IsCanceled())
1689  {
1690  throw invalid_operation("Illegal to wait on a task in a Windows Runtime STA");
1691  }
1692  else
1693  {
1694  // Task Continuations are 'scheduled' *inside* the chore that is executing on the ancestors's task group. If a continuation
1695  // needs to be marshalled to a different apartment, instead of scheduling, we make a synchronous cross apartment COM
1696  // call to execute the continuation. If it then happens to do something which waits on the ancestor (say it calls .get(), which
1697  // task based continuations are wont to do), waiting on the task group results in on the chore that is making this
1698  // synchronous callback, which causes a deadlock. To avoid this, we test the state ancestor's event , and we will NOT wait on
1699  // if it has finished execution (which means now we are on the inline synchronous callback).
1700  _DoWait = false;
1701  }
1702  }
1703 #endif /* defined (__cplusplus_winrt) */
1704  if (_DoWait)
1705  {
1706  // If this task was created from a Windows Runtime async operation, do not attempt to inline it. The
1707  // async operation will take place on a thread in the appropriate apartment Simply wait for the completed
1708  // event to be set.
1709  if (_M_fFromAsync)
1710  {
1711  _M_TaskCollection._Wait();
1712  }
1713  else
1714  {
1715  // Wait on the task collection to complete. The task collection is guaranteed to still be
1716  // valid since the task must be still within scope so that the _Task_impl_base destructor
1717  // has not yet been called. This call to _Wait potentially inlines execution of work.
1718  try
1719  {
1720  // Invoking wait on a task collection resets the state of the task collection. This means that
1721  // if the task collection itself were canceled, or had encountered an exception, only the first
1722  // call to wait will receive this status. However, both cancellation and exceptions flowing through
1723  // tasks set state in the task impl itself.
1724 
1725  // When it returns cancelled, either work chore or the cancel thread should already have set task's state
1726  // properly -- cancelled state or completed state (because there was no interruption point).
1727  // For tasks with unwrapped tasks, we should not change the state of current task, since the unwrapped task are still running.
1728  _M_TaskCollection._RunAndWait();
1729  }
1731  {
1732  // The _TaskCollection will never be an interruption point since it has a none token.
1733  _ASSERTE(false);
1734  }
1735  catch(task_canceled&)
1736  {
1737  // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
1738  // must be called from code that is executed within the task (throwing it from parallel work created by and waited
1739  // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
1740  // the exception and canceled the task. Swallow the exception here.
1741  _ASSERTE(_IsCanceled());
1742  }
1743 #if defined (__cplusplus_winrt)
1744  catch(::Platform::Exception^ _E)
1745  {
1746  // Its possible the task body hasn't seen the exception, if so we need to cancel with exception here.
1747  if(!_HasUserException())
1748  {
1749  _CancelWithException(_E);
1750  }
1751  // Rethrow will mark the exception as observed.
1752  _M_exceptionHolder->_RethrowUserException();
1753  }
1754 #endif /* defined (__cplusplus_winrt) */
1755  catch(...)
1756  {
1757  // Its possible the task body hasn't seen the exception, if so we need to cancel with exception here.
1758  if(!_HasUserException())
1759  {
1760  _CancelWithException(std::current_exception());
1761  }
1762  // Rethrow will mark the exception as observed.
1763  _M_exceptionHolder->_RethrowUserException();
1764  }
1765 
1766  // If the lambda body for this task (executed or waited upon in _RunAndWait above) happened to return a task
1767  // which is to be unwrapped and plumbed to the output of this task, we must not only wait on the lambda body, we must
1768  // wait on the **INNER** body. It is in theory possible that we could inline such if we plumb a series of things through;
1769  // however, this takes the tact of simply waiting upon the completion signal.
1770  if (_M_fUnwrappedTask)
1771  {
1772  _M_TaskCollection._Wait();
1773  }
1774  }
1775  }
1776 
1777  if (_HasUserException())
1778  {
1779  _M_exceptionHolder->_RethrowUserException();
1780  }
1781  else if (_IsCanceled())
1782  {
1783  return canceled;
1784  }
1785  _ASSERTE(_IsCompleted());
1786  return completed;
1787  }
1788 
1808  virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr<_ExceptionHolder>& _ExHolder) = 0;
1809 
1810  bool _Cancel(bool _SynchronousCancel)
1811  {
1812  // Send in a dummy value for exception. It is not used when the first parameter is false.
1813  return _CancelAndRunContinuations(_SynchronousCancel, false, false, _M_exceptionHolder);
1814  }
1815 
1816  bool _CancelWithExceptionHolder(const std::shared_ptr<_ExceptionHolder>& _ExHolder, bool _PropagatedFromAncestor)
1817  {
1818  // This task was canceled because an ancestor task encountered an exception.
1819  return _CancelAndRunContinuations(true, true, _PropagatedFromAncestor, _ExHolder);
1820  }
1821 
1822 #if defined (__cplusplus_winrt)
1823  bool _CancelWithException(::Platform::Exception^ _Exception)
1824  {
1825  // This task was canceled because the task body encountered an exception.
1826  _ASSERTE(!_HasUserException());
1827  return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
1828  }
1829 #endif /* defined (__cplusplus_winrt) */
1830 
1831  bool _CancelWithException(const std::exception_ptr& _Exception)
1832  {
1833  // This task was canceled because the task body encountered an exception.
1834  _ASSERTE(!_HasUserException());
1835  return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
1836  }
1837 
1838  void _RegisterCancellation(std::weak_ptr<_Task_impl_base> _WeakPtr)
1839  {
1841 
1842  auto _CancellationCallback = [_WeakPtr](){
1843  // Taking ownership of the task prevents dead lock during destruction
1844  // if the destructor waits for the cancellations to be finished
1845  auto _task = _WeakPtr.lock();
1846  if (_task != nullptr)
1847  _task->_Cancel(false);
1848  };
1849 
1850  _M_pRegistration = new details::_CancellationTokenCallback<decltype(_CancellationCallback)>(_CancellationCallback);
1851  _M_pTokenState->_RegisterCallback(_M_pRegistration);
1852  }
1853 
1855  {
1856  if (_M_pRegistration != nullptr)
1857  {
1858  _M_pTokenState->_DeregisterCallback(_M_pRegistration);
1859  _M_pRegistration->_Release();
1860  _M_pRegistration = nullptr;
1861  }
1862  }
1863 
1864  bool _IsCreated()
1865  {
1866  return (_M_TaskState == _Created);
1867  }
1868 
1869  bool _IsStarted()
1870  {
1871  return (_M_TaskState == _Started);
1872  }
1873 
1875  {
1876  return (_M_TaskState == _PendingCancel);
1877  }
1878 
1880  {
1881  return (_M_TaskState == _Completed);
1882  }
1883 
1885  {
1886  return (_M_TaskState == _Canceled);
1887  }
1888 
1890  {
1891  return static_cast<bool>(_M_exceptionHolder);
1892  }
1893 
1894  const std::shared_ptr<_ExceptionHolder>& _GetExceptionHolder()
1895  {
1896  _ASSERTE(_HasUserException());
1897  return _M_exceptionHolder;
1898  }
1899 
1901  {
1902  return _M_fFromAsync;
1903  }
1904 
1905  void _SetAsync(bool _Async = true)
1906  {
1907  _M_fFromAsync = _Async;
1908  }
1909 
1911  {
1912  return _M_pTaskCreationCallstack;
1913  }
1914 
1916  {
1917  _M_pTaskCreationCallstack = _Callstack;
1918  }
1919 
1929  void _ScheduleTask(_UnrealizedChore_t * _PTaskHandle, _TaskInliningMode_t _InliningMode)
1930  {
1931  try
1932  {
1933  _M_TaskCollection._ScheduleTask(_PTaskHandle, _InliningMode);
1934  }
1935  catch(const task_canceled &)
1936  {
1937  // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
1938  // must be called from code that is executed within the task (throwing it from parallel work created by and waited
1939  // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
1940  // the exception and canceled the task. Swallow the exception here.
1941  _ASSERTE(_IsCanceled());
1942  }
1943  catch(const _Interruption_exception &)
1944  {
1945  // The _TaskCollection will never be an interruption point since it has a none token.
1946  _ASSERTE(false);
1947  }
1948  catch(...)
1949  {
1950  // This exception could only have come from within the chore body. It should've been caught
1951  // and the task should be canceled with exception. Swallow the exception here.
1952  _ASSERTE(_HasUserException());
1953  }
1954  }
1955 
1963 
1965  {
1966  _Task_ptr_base _ImplBase = _PTaskHandle->_GetTaskImplBase();
1967  if (_IsCanceled() && !_PTaskHandle->_M_isTaskBasedContinuation)
1968  {
1969  if (_HasUserException())
1970  {
1971  // If the ancestor encountered an exception, transfer the exception to the continuation
1972  // This traverses down the tree to propagate the exception.
1973  _ImplBase->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
1974  }
1975  else
1976  {
1977  // If the ancestor was canceled, then your own execution should be canceled.
1978  // This traverses down the tree to cancel it.
1979  _ImplBase->_Cancel(true);
1980  }
1981  }
1982  else
1983  {
1984  // This can only run when the ancestor has completed or it's a task based continuation that fires when a task is canceled
1985  // (with or without a user exception).
1986  _ASSERTE(_IsCompleted() || _PTaskHandle->_M_isTaskBasedContinuation);
1987  _ASSERTE(!_ImplBase->_IsCanceled());
1988  return _ImplBase->_ScheduleContinuationTask(_PTaskHandle);
1989  }
1990 
1991  // If the handle is not scheduled, we need to manually delete it.
1992  delete _PTaskHandle;
1993  }
1994 
1995  // Schedule a continuation to run
1997  {
1998 
1999  _M_taskEventLogger._LogScheduleTask(true);
2000  // Ensure that the continuation runs in proper context (this might be on a Concurrency Runtime thread or in a different Windows Runtime apartment)
2001  if (_PTaskHandle->_M_continuationContext._HasCapturedContext())
2002  {
2003  // For those continuations need to be scheduled inside captured context, we will try to apply automatic inlining to their inline modes,
2004  // if they haven't been specified as _ForceInline yet. This change will encourage those continuations to be executed inline so that reduce
2005  // the cost of marshaling.
2006  // For normal continuations we won't do any change here, and their inline policies are completely decided by ._ThenImpl method.
2007  if (_PTaskHandle->_M_inliningMode != details::_ForceInline)
2008  {
2010  }
2011  _ScheduleFuncWithAutoInline([_PTaskHandle]() {
2012  // Note that we cannot directly capture "this" pointer, instead, we should use _TaskImplPtr, a shared_ptr to the _Task_impl_base.
2013  // Because "this" pointer will be invalid as soon as _PTaskHandle get deleted. _PTaskHandle will be deleted after being scheduled.
2014  auto _TaskImplPtr = _PTaskHandle->_GetTaskImplBase();
2016  {
2017  _TaskImplPtr->_ScheduleTask(_PTaskHandle, details::_ForceInline);
2018  }
2019  else
2020  {
2021  //
2022  // It's entirely possible that the attempt to marshal the call into a differing context will fail. In this case, we need to handle
2023  // the exception and mark the continuation as canceled with the appropriate exception. There is one slight hitch to this:
2024  //
2025  // NOTE: COM's legacy behavior is to swallow SEH exceptions and marshal them back as HRESULTS. This will in effect turn an SEH into
2026  // a C++ exception that gets tagged on the task. One unfortunate result of this is that various pieces of the task infrastructure will
2027  // not be in a valid state after this in /EHsc (due to the lack of destructors running, etc...).
2028  //
2029  try
2030  {
2031  // Dev10 compiler needs this!
2032  auto _PTaskHandle1 = _PTaskHandle;
2033  _PTaskHandle->_M_continuationContext._CallInContext( [_PTaskHandle1, _TaskImplPtr](){
2034  _TaskImplPtr->_ScheduleTask(_PTaskHandle1, details::_ForceInline);
2035  });
2036  }
2037 #if defined (__cplusplus_winrt)
2038  catch(::Platform::Exception^ _E)
2039  {
2040  _TaskImplPtr->_CancelWithException(_E);
2041  }
2042 #endif /* defined (__cplusplus_winrt) */
2043  catch(...)
2044  {
2045  _TaskImplPtr->_CancelWithException(std::current_exception());
2046  }
2047  }
2048  }, _PTaskHandle->_M_inliningMode);
2049  }
2050  else
2051  {
2052  _ScheduleTask(_PTaskHandle, _PTaskHandle->_M_inliningMode);
2053  }
2054  }
2055 
2066 
2068  {
2069  enum { _Nothing, _Schedule, _Cancel, _CancelWithException } _Do = _Nothing;
2070 
2071  // If the task has canceled, cancel the continuation. If the task has completed, execute the continuation right away.
2072  // Otherwise, add it to the list of pending continuations
2073  {
2074  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2075  if (_IsCompleted() || (_IsCanceled() && _PTaskHandle->_M_isTaskBasedContinuation))
2076  {
2077  _Do = _Schedule;
2078  }
2079  else if (_IsCanceled())
2080  {
2081  if (_HasUserException())
2082  {
2083  _Do = _CancelWithException;
2084  }
2085  else
2086  {
2087  _Do = _Cancel;
2088  }
2089  }
2090  else
2091  {
2092  // chain itself on the continuation chain.
2093  _PTaskHandle->_M_next = _M_Continuations;
2094  _M_Continuations = _PTaskHandle;
2095  }
2096  }
2097 
2098  // Cancellation and execution of continuations should be performed after releasing the lock. Continuations off of
2099  // async tasks may execute inline.
2100  switch (_Do)
2101  {
2102  case _Schedule:
2103  {
2104  _PTaskHandle->_GetTaskImplBase()->_ScheduleContinuationTask(_PTaskHandle);
2105  break;
2106  }
2107  case _Cancel:
2108  {
2109  // If the ancestor was canceled, then your own execution should be canceled.
2110  // This traverses down the tree to cancel it.
2111  _PTaskHandle->_GetTaskImplBase()->_Cancel(true);
2112 
2113  delete _PTaskHandle;
2114  break;
2115  }
2116  case _CancelWithException:
2117  {
2118  // If the ancestor encountered an exception, transfer the exception to the continuation
2119  // This traverses down the tree to propagate the exception.
2120  _PTaskHandle->_GetTaskImplBase()->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
2121 
2122  delete _PTaskHandle;
2123  break;
2124  }
2125  case _Nothing:
2126  default:
2127  // In this case, we have inserted continuation to continuation chain,
2128  // nothing more need to be done, just leave.
2129  break;
2130  }
2131  }
2132 
2134  {
2135  // The link list can no longer be modified at this point,
2136  // since all following up continuations will be scheduled by themselves.
2137  _ContinuationList _Cur = _M_Continuations, _Next;
2138  _M_Continuations = nullptr;
2139  while (_Cur)
2140  {
2141  // Current node might be deleted after running,
2142  // so we must fetch the next first.
2143  _Next = _Cur->_M_next;
2144  _RunContinuation(_Cur);
2145  _Cur = _Next;
2146  }
2147  }
2148 
2149 #if defined (__cplusplus_winrt)
2150  static bool _IsNonBlockingThread()
2151  {
2152  APTTYPE _AptType;
2153  APTTYPEQUALIFIER _AptTypeQualifier;
2154 
2155  HRESULT hr = CoGetApartmentType(&_AptType, &_AptTypeQualifier);
2156  //
2157  // If it failed, it's not a Windows Runtime/COM initialized thread. This is not a failure.
2158  //
2159  if (SUCCEEDED(hr))
2160  {
2161  switch(_AptType)
2162  {
2163  case APTTYPE_STA:
2164  case APTTYPE_MAINSTA:
2165  return true;
2166  break;
2167  case APTTYPE_NA:
2168  switch(_AptTypeQualifier)
2169  {
2170  // A thread executing in a neutral apartment is either STA or MTA. To find out if this thread is allowed
2171  // to wait, we check the app qualifier. If it is an STA thread executing in a neutral apartment, waiting
2172  // is illegal, because the thread is responsible for pumping messages and waiting on a task could take the
2173  // thread out of circulation for a while.
2174  case APTTYPEQUALIFIER_NA_ON_STA:
2175  case APTTYPEQUALIFIER_NA_ON_MAINSTA:
2176  return true;
2177  break;
2178  }
2179  break;
2180  }
2181  }
2182 
2183 #if _UITHREADCTXT_SUPPORT
2184  // This method is used to throw an exepection in _Wait() if called within STA. We
2185  // want the same behavior if _Wait is called on the UI thread.
2186  if (SUCCEEDED(CaptureUiThreadContext(nullptr)))
2187  {
2188  return true;
2189  }
2190 #endif /* _UITHREADCTXT_SUPPORT */
2191 
2192  return false;
2193  }
2194 
2195  template<typename _ReturnType, typename>
2196  static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type & _OuterTask,
2197  Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
2198  {
2199  // This method is invoked either when a task is created from an existing async operation or
2200  // when a lambda that creates an async operation executes.
2201 
2202  // If the outer task is pending cancel, cancel the async operation before setting the completed handler. The COM reference on
2203  // the IAsyncInfo object will be released when all ^references to the operation go out of scope.
2204 
2205  // This assertion uses the existence of taskcollection to determine if the task was created from an event.
2206  // That is no longer valid as even tasks created from a user lambda could have no underlying taskcollection
2207  // when a custom scheduler is used.
2208  // _ASSERTE((!_OuterTask->_M_TaskCollection._IsCreated() || _OuterTask->_M_fUnwrappedTask) && !_OuterTask->_IsCanceled());
2209 
2210  // Pass the shared_ptr by value into the lambda instead of using 'this'.
2211  _AsyncOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<_ReturnType>(
2212  [_OuterTask](Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _Operation, Windows::Foundation::AsyncStatus _Status) mutable
2213  {
2214  if (_Status == Windows::Foundation::AsyncStatus::Canceled)
2215  {
2216  _OuterTask->_Cancel(true);
2217  }
2218  else if (_Status == Windows::Foundation::AsyncStatus::Error)
2219  {
2220  _OuterTask->_CancelWithException(::Platform::Exception::ReCreateException(static_cast<int>(_Operation->ErrorCode.Value)));
2221  }
2222  else
2223  {
2224  _ASSERTE(_Status == Windows::Foundation::AsyncStatus::Completed);
2225  _OuterTask->_FinalizeAndRunContinuations(_Operation->GetResults());
2226  }
2227 
2228  // Take away this shared pointers reference on the task instead of waiting for the delegate to be released. It could
2229  // be released on a different thread after a delay, and not releasing the reference here could cause the tasks to hold
2230  // on to resources longer than they should. As an example, without this reset, writing to a file followed by reading from
2231  // it using the Windows Runtime Async APIs causes a sharing violation.
2232  // Using const_cast is the workaround for failed mutable keywords
2233  const_cast<_Task_ptr<_ReturnType>::_Type &>(_OuterTask).reset();
2234  });
2235  _OuterTask->_SetUnwrappedAsyncOp(_AsyncOp);
2236  }
2237 #endif /* defined (__cplusplus_winrt) */
2238 
2239  template<typename _ReturnType, typename _InternalReturnType>
2240  static void _AsyncInit(const typename _Task_ptr<_ReturnType>::_Type& _OuterTask, const task<_InternalReturnType> & _UnwrappedTask)
2241  {
2242  _ASSERTE(_OuterTask->_M_fUnwrappedTask && !_OuterTask->_IsCanceled());
2243 
2244  //
2245  // We must ensure that continuations off _OuterTask (especially exception handling ones) continue to function in the
2246  // presence of an exception flowing out of the inner task _UnwrappedTask. This requires an exception handling continuation
2247  // off the inner task which does the appropriate funnelling to the outer one. We use _Then instead of then to prevent
2248  // the exception from being marked as observed by our internal continuation. This continuation must be scheduled regardless
2249  // of whether or not the _OuterTask task is canceled.
2250  //
2251  _UnwrappedTask._Then([_OuterTask] (task<_InternalReturnType> _AncestorTask) {
2252 
2253  if (_AncestorTask._GetImpl()->_IsCompleted())
2254  {
2255  _OuterTask->_FinalizeAndRunContinuations(_AncestorTask._GetImpl()->_GetResult());
2256  }
2257  else
2258  {
2259  _ASSERTE(_AncestorTask._GetImpl()->_IsCanceled());
2260  if (_AncestorTask._GetImpl()->_HasUserException())
2261  {
2262  // Set _PropagatedFromAncestor to false, since _AncestorTask is not an ancestor of _UnwrappedTask.
2263  // Instead, it is the enclosing task.
2264  _OuterTask->_CancelWithExceptionHolder(_AncestorTask._GetImpl()->_GetExceptionHolder(), false);
2265  }
2266  else
2267  {
2268  _OuterTask->_Cancel(true);
2269  }
2270  }
2271  }, nullptr, details::_DefaultAutoInline);
2272 
2273  }
2274 
2276  {
2277  return _M_TaskCollection._GetScheduler();
2278  }
2279 
2280  // Tracks the internal state of the task
2282  // 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
2283  // async operation or async action that is unwrapped by the runtime.
2285  // Set to true when a continuation unwraps a task or async operation.
2287 
2288  // 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.
2289  // The exception is 'observed' if the user invokes get()/wait() on any of the tasks that are sharing this exception holder. If the exception
2290  // is not observed by the time the internal object owned by the shared pointer destructs, the process will fail fast.
2291  std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
2292 
2294 
2296  _ContinuationList _M_Continuations;
2297 
2298  // The cancellation token state.
2300 
2301  // The registration on the token.
2303 
2304  // The async task collection wrapper
2306 
2307  // Callstack for function call (constructor or .then) that created this task impl.
2309 
2311  private:
2312  // Must not be copied by value:
2314  _Task_impl_base const & operator=(_Task_impl_base const&);
2315  };
2316 
2317 #if _PPLTASK_ASYNC_LOGGING
2319  {
2320  if (_M_scheduled)
2321  {
2322  ::Windows::Foundation::AsyncStatus _State;
2323  if (_M_task->_IsCompleted())
2324  _State = ::Windows::Foundation::AsyncStatus::Completed;
2325  else if (_M_task->_HasUserException())
2326  _State = ::Windows::Foundation::AsyncStatus::Error;
2327  else
2328  _State = ::Windows::Foundation::AsyncStatus::Canceled;
2329 
2330  if (details::_IsCausalitySupported())
2331  {
2332  ::Windows::Foundation::Diagnostics::AsyncCausalityTracer::TraceOperationCompletion(::Windows::Foundation::Diagnostics::CausalityTraceLevel::Required, ::Windows::Foundation::Diagnostics::CausalitySource::Library,
2333  _PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task), _State);
2334  }
2335  }
2336  }
2337 #endif
2338 
2347 
2348  template<typename _ReturnType>
2349  struct _Task_impl : public _Task_impl_base
2350  {
2351 #if defined (__cplusplus_winrt)
2353 #endif // defined(__cplusplus_winrt)
2355  : _Task_impl_base(_Ct, _Scheduler_arg)
2356  {
2357 #if defined (__cplusplus_winrt)
2358  _M_unwrapped_async_op = nullptr;
2359 #endif /* defined (__cplusplus_winrt) */
2360  }
2361 
2362  virtual ~_Task_impl()
2363  {
2364  // We must invoke _DeregisterCancellation in the derived class destructor. Calling it in the base class destructor could cause
2365  // a partially initialized _Task_impl to be in the list of registrations for a cancellation token.
2366  _DeregisterCancellation();
2367  }
2368 
2369  virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr<_ExceptionHolder> & _ExceptionHolder_arg)
2370  {
2371  enum { _Nothing, _RunContinuations, _Cancel } _Do = _Nothing;
2372  {
2373  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2374  if (_UserException)
2375  {
2376  _ASSERTE(_SynchronousCancel && !_IsCompleted());
2377  // If the state is _Canceled, the exception has to be coming from an ancestor.
2378  _ASSERTE(!_IsCanceled() || _PropagatedFromAncestor);
2379 
2380  // We should not be canceled with an exception more than once.
2381  _ASSERTE(!_HasUserException());
2382 
2383  if (_M_TaskState == _Canceled)
2384  {
2385  // If the task has finished cancelling there should not be any continuation records in the array.
2386  return false;
2387  }
2388  else
2389  {
2390  _ASSERTE(_M_TaskState != _Completed);
2391  _M_exceptionHolder = _ExceptionHolder_arg;
2392  }
2393  }
2394  else
2395  {
2396  // Completed is a non-cancellable state, and if this is an asynchronous cancel, we're unable to do better than the last async cancel
2397  // which is to say, cancellation is already initiated, so return early.
2398  if (_IsCompleted() || _IsCanceled() || (_IsPendingCancel() && !_SynchronousCancel))
2399  {
2400  _ASSERTE(!_IsCompleted() || !_HasUserException());
2401  return false;
2402  }
2403  _ASSERTE(!_SynchronousCancel || !_HasUserException());
2404  }
2405 
2406  if (_SynchronousCancel)
2407  {
2408  // Be aware that this set must be done BEFORE _M_Scheduled being set, or race will happen between this and wait()
2409  _M_TaskState = _Canceled;
2410  // Cancellation completes the task, so all dependent tasks must be run to cancel them
2411  // They are canceled when they begin running (see _RunContinuation) and see that their
2412  // ancestor has been canceled.
2413  _Do = _RunContinuations;
2414  }
2415  else
2416  {
2417  _ASSERTE(!_UserException);
2418 
2419  if (_IsStarted())
2420  {
2421  // should not initiate cancellation under a lock
2422  _Do = _Cancel;
2423  }
2424 
2425  // The _M_TaskState variable transitions to _Canceled when cancellation is completed (the task is not executing user code anymore).
2426  // In the case of a synchronous cancel, this can happen immediately, whereas with an asynchronous cancel, the task has to move from
2427  // _Started to _PendingCancel before it can move to _Canceled when it is finished executing.
2428  _M_TaskState = _PendingCancel;
2429 
2430  _M_taskEventLogger._LogCancelTask();
2431  }
2432  }
2433 
2434  switch (_Do)
2435  {
2436  case _Cancel:
2437  {
2438 #if defined (__cplusplus_winrt)
2439  if (_M_unwrapped_async_op != nullptr)
2440  {
2441  // We will only try to cancel async operation but not unwrapped tasks, since unwrapped tasks cannot be canceled without its token.
2442  _M_unwrapped_async_op->Cancel();
2443  }
2444 #endif /* defined (__cplusplus_winrt) */
2445  _M_TaskCollection._Cancel();
2446  break;
2447  }
2448  case _RunContinuations:
2449  {
2450  // Only execute continuations and mark the task as completed if we were able to move the task to the _Canceled state.
2451  _M_TaskCollection._Complete();
2452 
2453  if (_M_Continuations)
2454  {
2455  // Scheduling cancellation with automatic inlining.
2456  _ScheduleFuncWithAutoInline([=](){ _RunTaskContinuations(); }, details::_DefaultAutoInline);
2457  }
2458 
2459  break;
2460  }
2461  }
2462  return true;
2463  }
2464 
2465  void _FinalizeAndRunContinuations(_ReturnType _Result)
2466  {
2467  _M_Result.Set(_Result);
2468 
2469  {
2470  //
2471  // Hold this lock to ensure continuations being concurrently either get added
2472  // to the _M_Continuations vector or wait for the result
2473  //
2474  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2475 
2476  // A task could still be in the _Created state if it was created with a task_completion_event.
2477  // It could also be in the _Canceled state for the same reason.
2478  _ASSERTE(!_HasUserException() && !_IsCompleted());
2479  if (_IsCanceled())
2480  {
2481  return;
2482  }
2483 
2484  // Always transition to "completed" state, even in the face of unacknowledged pending cancellation
2485  _M_TaskState = _Completed;
2486  }
2487  _M_TaskCollection._Complete();
2488  _RunTaskContinuations();
2489  }
2490 
2491  //
2492  // This method is invoked when the starts executing. The task returns early if this method returns true.
2493  //
2495  {
2496  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2497  // Canceled state could only result from antecedent task's canceled state, but that code path will not reach here.
2498  _ASSERT(!_IsCanceled());
2499  if (_IsPendingCancel())
2500  return false;
2501 
2502  _ASSERTE(_IsCreated());
2503  _M_TaskState = _Started;
2504  return true;
2505  }
2506 
2507 #if defined (__cplusplus_winrt)
2508  void _SetUnwrappedAsyncOp(_AsyncOperationType^ _AsyncOp)
2509  {
2510  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_ContinuationsCritSec);
2511  // Cancel the async operation if the task itself is canceled, since the thread that canceled the task missed it.
2512  if (_IsPendingCancel())
2513  {
2514  _ASSERTE(!_IsCanceled());
2515  _AsyncOp->Cancel();
2516  }
2517  else
2518  {
2519  _M_unwrapped_async_op = _AsyncOp;
2520  }
2521  }
2522 #endif /* defined (__cplusplus_winrt) */
2523 
2524  // Return true if the task has reached a terminal state
2525  bool _IsDone()
2526  {
2527  return _IsCompleted() || _IsCanceled();
2528  }
2529 
2530  _ReturnType _GetResult()
2531  {
2532  return _M_Result.Get();
2533  }
2534 
2535  _ResultHolder<_ReturnType> _M_Result; // this means that the result type must have a public default ctor.
2536 #if defined (__cplusplus_winrt)
2537  _AsyncOperationType^ _M_unwrapped_async_op;
2538 #endif /* defined (__cplusplus_winrt) */
2539  };
2540 
2541  template<typename _ResultType>
2543  {
2544  private:
2547 
2548  public:
2549 
2551 
2553  _M_fHasValue(false), _M_fIsCanceled(false)
2554  {
2555  }
2556 
2558  {
2559  return _M_exceptionHolder != nullptr;
2560  }
2561 
2563  {
2564  for( auto _TaskIt = _M_tasks.begin(); _TaskIt != _M_tasks.end(); ++_TaskIt )
2565  {
2566  _ASSERTE(!_M_fHasValue && !_M_fIsCanceled);
2567  // Cancel the tasks since the event was never signaled or canceled.
2568  (*_TaskIt)->_Cancel(true);
2569  }
2570  }
2571 
2572  // We need to protect the loop over the array, so concurrent_vector would not have helped
2573  _TaskList _M_tasks;
2576  std::shared_ptr<_ExceptionHolder> _M_exceptionHolder;
2579  };
2580 
2581  // Utility method for dealing with void functions
2582  inline std::function<_Unit_type(void)> _MakeVoidToUnitFunc(const std::function<void(void)>& _Func)
2583  {
2584  return [=]() -> _Unit_type { _Func(); return _Unit_type(); };
2585  }
2586 
2587  template <typename _Type>
2588  std::function<_Type(_Unit_type)> _MakeUnitToTFunc(const std::function<_Type(void)>& _Func)
2589  {
2590  return [=](_Unit_type) -> _Type { return _Func(); };
2591  }
2592 
2593  template <typename _Type>
2594  std::function<_Unit_type(_Type)> _MakeTToUnitFunc(const std::function<void(_Type)>& _Func)
2595  {
2596  return [=](_Type t) -> _Unit_type { _Func(t); return _Unit_type(); };
2597  }
2598 
2599  inline std::function<_Unit_type(_Unit_type)> _MakeUnitToUnitFunc(const std::function<void(void)>& _Func)
2600  {
2601  return [=](_Unit_type) -> _Unit_type { _Func(); return _Unit_type(); };
2602  }
2603 } // namespace details
2604 
2621 
2622 template<typename _ResultType>
2624 {
2625 public:
2629 
2631  : _M_Impl(std::make_shared<details::_Task_completion_event_impl<_ResultType>>())
2632  {
2633  }
2634 
2650 
2651  bool set(_ResultType _Result) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2652  {
2653  // Subsequent sets are ignored. This makes races to set benign: the first setter wins and all others are ignored.
2654  if (_IsTriggered())
2655  {
2656  return false;
2657  }
2658 
2659  _TaskList _Tasks;
2660  bool _RunContinuations = false;
2661  {
2662  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2663 
2664  if (!_IsTriggered())
2665  {
2666  _M_Impl->_M_value.Set(_Result);
2667  _M_Impl->_M_fHasValue = true;
2668 
2669  _Tasks.swap(_M_Impl->_M_tasks);
2670  _RunContinuations = true;
2671  }
2672  }
2673 
2674  if (_RunContinuations)
2675  {
2676  for( auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt )
2677  {
2678  // If current task was cancelled by a cancellation_token, it would be in cancel pending state.
2679  if ((*_TaskIt)->_IsPendingCancel())
2680  (*_TaskIt)->_Cancel(true);
2681  else
2682  {
2683  // Tasks created with task_completion_events can be marked as async, (we do this in when_any and when_all
2684  // if one of the tasks involved is an async task). Since continuations of async tasks can execute inline, we
2685  // need to run continuations after the lock is released.
2686  (*_TaskIt)->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
2687  }
2688  }
2689  if (_M_Impl->_HasUserException())
2690  {
2691  _M_Impl->_M_exceptionHolder.reset();
2692  }
2693  return true;
2694  }
2695 
2696  return false;
2697  }
2698 
2699  template<typename _E>
2700  __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
2701  bool set_exception(_E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2702  {
2703  // It is important that _CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for set_exception.
2704  return _Cancel(std::make_exception_ptr(_Except), _CAPTURE_CALLSTACK());
2705  }
2706 
2713 
2714  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
2715  bool set_exception(std::exception_ptr _ExceptionPtr) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2716  {
2717  // It is important that _CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for set_exception.
2718  return _Cancel(_ExceptionPtr, _CAPTURE_CALLSTACK());
2719  }
2720 
2725  bool _Cancel() const
2726  {
2727  // Cancel with the stored exception if one exists.
2728  return _CancelInternal();
2729  }
2730 
2735  template<typename _ExHolderType>
2736  bool _Cancel(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint = details::_TaskCreationCallstack ()) const
2737  {
2738  bool _Canceled;
2739  if(_StoreException(_ExHolder, _SetExceptionAddressHint))
2740  {
2741  _Canceled = _CancelInternal();
2742  _ASSERTE(_Canceled);
2743  }
2744  else
2745  {
2746  _Canceled = false;
2747  }
2748  return _Canceled;
2749  }
2750 
2756  template<typename _ExHolderType>
2757  bool _StoreException(_ExHolderType _ExHolder, const details::_TaskCreationCallstack &_SetExceptionAddressHint = details::_TaskCreationCallstack ()) const
2758  {
2759  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2760  if (!_IsTriggered() && !_M_Impl->_HasUserException())
2761  {
2762  // Create the exception holder only if we have ensured there we will be successful in setting it onto the
2763  // task completion event. Failing to do so will result in an unobserved task exception.
2764  _M_Impl->_M_exceptionHolder = _ToExceptionHolder(_ExHolder, _SetExceptionAddressHint);
2765  return true;
2766  }
2767  return false;
2768  }
2769 
2773  bool _IsTriggered() const
2774  {
2775  return _M_Impl->_M_fHasValue || _M_Impl->_M_fIsCanceled;
2776  }
2777 
2778 private:
2779 
2780  static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder, const details::_TaskCreationCallstack&)
2781  {
2782  return _ExHolder;
2783  }
2784 
2785  static std::shared_ptr<details::_ExceptionHolder> _ToExceptionHolder(std::exception_ptr _ExceptionPtr, const details::_TaskCreationCallstack &_SetExceptionAddressHint)
2786  {
2787  return std::make_shared<details::_ExceptionHolder>(_ExceptionPtr, _SetExceptionAddressHint);
2788  }
2789 
2790 
2791  template <typename T> friend class task; // task can register itself with the event by calling the private _RegisterTask
2792  template <typename T> friend class task_completion_event;
2793 
2795 
2799  bool _CancelInternal() const
2800  {
2801  // Cancellation of task completion events is an internal only utility. Our usage is such that _CancelInternal
2802  // will never be invoked if the task completion event has been set.
2803  _ASSERTE(!_M_Impl->_M_fHasValue);
2804  if (_M_Impl->_M_fIsCanceled)
2805  {
2806  return false;
2807  }
2808 
2809  _TaskList _Tasks;
2810  bool _Cancel = false;
2811  {
2812  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2813  _ASSERTE(!_M_Impl->_M_fHasValue);
2814  if (!_M_Impl->_M_fIsCanceled)
2815  {
2816  _M_Impl->_M_fIsCanceled = true;
2817  _Tasks.swap(_M_Impl->_M_tasks);
2818  _Cancel = true;
2819  }
2820  }
2821 
2822  bool _UserException = _M_Impl->_HasUserException();
2823 
2824  if (_Cancel)
2825  {
2826  for( auto _TaskIt = _Tasks.begin(); _TaskIt != _Tasks.end(); ++_TaskIt )
2827  {
2828  // Need to call this after the lock is released. See comments in set().
2829  if (_UserException)
2830  {
2831  (*_TaskIt)->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
2832  }
2833  else
2834  {
2835  (*_TaskIt)->_Cancel(true);
2836  }
2837  }
2838  }
2839  return _Cancel;
2840  }
2841 
2846  void _RegisterTask(const typename details::_Task_ptr<_ResultType>::_Type & _TaskParam)
2847  {
2848  ::Concurrency::extensibility::scoped_critical_section_t _LockHolder(_M_Impl->_M_taskListCritSec);
2849 
2850  //If an exception was already set on this event, then cancel the task with the stored exception.
2851  if(_M_Impl->_HasUserException())
2852  {
2853  _TaskParam->_CancelWithExceptionHolder(_M_Impl->_M_exceptionHolder, true);
2854  }
2855  else if (_M_Impl->_M_fHasValue)
2856  {
2857  _TaskParam->_FinalizeAndRunContinuations(_M_Impl->_M_value.Get());
2858  }
2859  else
2860  {
2861  _M_Impl->_M_tasks.push_back(_TaskParam);
2862  }
2863  }
2864 
2865  std::shared_ptr<details::_Task_completion_event_impl<_ResultType>> _M_Impl;
2866 };
2867 
2881 
2882 template<>
2884 {
2885 public:
2898 
2899  bool set() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2900  {
2901  return _M_unitEvent.set(details::_Unit_type());
2902  }
2903 
2904  template<typename _E>
2905  __declspec(noinline) // Ask for no inlining so that the _ReturnAddress intrinsic gives us the expected result
2906  bool set_exception(_E _Except) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2907  {
2908  return _M_unitEvent._Cancel(std::make_exception_ptr(_Except), _CAPTURE_CALLSTACK());
2909  }
2910 
2917 
2918  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK intrinsic gives us the expected result
2919  bool set_exception(std::exception_ptr _ExceptionPtr) const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2920  {
2921  // It is important that _CAPTURE_CALLSTACK() evaluate to the instruction after the call instruction for set_exception.
2922  return _M_unitEvent._Cancel(_ExceptionPtr, _CAPTURE_CALLSTACK());
2923  }
2924 
2929  void _Cancel() const // 'const' (even though it's not deep) allows to safely pass events by value into lambdas
2930  {
2931  _M_unitEvent._Cancel();
2932  }
2933 
2938  void _Cancel(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
2939  {
2940  _M_unitEvent._Cancel(_ExHolder);
2941  }
2942 
2948  bool _StoreException(const std::shared_ptr<details::_ExceptionHolder>& _ExHolder) const
2949  {
2950  return _M_unitEvent._StoreException(_ExHolder);
2951  }
2952 
2956  bool _IsTriggered() const
2957  {
2958  return _M_unitEvent._IsTriggered();
2959  }
2960 
2961 private:
2962  template <typename T> friend class task; // task can register itself with the event by calling the private _RegisterTask
2963 
2969  {
2970  _M_unitEvent._RegisterTask(_TaskParam);
2971  }
2972 
2973  // The void event contains an event a dummy type so common code can be used for events with void and non-void results.
2975 };
2976 
2977 namespace details
2978 {
2979  //
2980  // Compile-time validation helpers
2981  //
2982 
2983  // Task constructor validation: issue helpful diagnostics for common user errors. Do not attempt full validation here.
2984  //
2985  // Anything callable is fine
2986  template<typename _ReturnType, typename _Ty>
2987  auto _IsValidTaskCtor(_Ty _Param, int,int,int,int) -> decltype(_Param(), std::true_type());
2988 
2989 #if defined (__cplusplus_winrt)
2990  // Anything that has GetResults is fine: this covers all async operations
2991  template<typename _ReturnType, typename _Ty>
2992  auto _IsValidTaskCtor(_Ty _Param, int, int, int,...) -> decltype(_Param->GetResults(), std::true_type());
2993 #endif
2994 
2995  // Allow parameters with set: this covers task_completion_event
2996  template<typename _ReturnType, typename _Ty>
2997  auto _IsValidTaskCtor(_Ty _Param, int, int, ...) -> decltype(_Param.set(stdx::declval<_ReturnType>()), std::true_type());
2998 
2999  template<typename _ReturnType, typename _Ty>
3000  auto _IsValidTaskCtor(_Ty _Param, int, ...) -> decltype(_Param.set(), std::true_type());
3001 
3002  // All else is invalid
3003  template<typename _ReturnType, typename _Ty>
3004  std::false_type _IsValidTaskCtor(_Ty _Param, ...);
3005 
3006  template<typename _ReturnType, typename _Ty>
3008  {
3009  static_assert(std::is_same<decltype(_IsValidTaskCtor<_ReturnType>(_Param,0,0,0,0)),std::true_type>::value,
3010 #if defined (__cplusplus_winrt)
3011  "incorrect argument for task constructor; can be a callable object, an asynchronous operation, or a task_completion_event"
3012 #else /* defined (__cplusplus_winrt) */
3013  "incorrect argument for task constructor; can be a callable object or a task_completion_event"
3014 #endif /* defined (__cplusplus_winrt) */
3015  );
3016 #if defined (__cplusplus_winrt)
3017  static_assert(!(std::is_same<_Ty,_ReturnType>::value && details::_IsIAsyncInfo<_Ty>::_Value),
3018  "incorrect template argument for task; consider using the return type of the async operation");
3019 #endif /* defined (__cplusplus_winrt) */
3020  }
3021 
3022 #if defined (__cplusplus_winrt)
3023  // Helpers for create_async validation
3024  //
3025  // A parameter lambda taking no arguments is valid
3026  template<typename _Ty>
3027  static auto _IsValidCreateAsync(_Ty _Param, int, int, int, int) -> decltype(_Param(), std::true_type());
3028 
3029  // A parameter lambda taking an cancellation_token argument is valid
3030  template<typename _Ty>
3031  static auto _IsValidCreateAsync(_Ty _Param, int, int, int, ...) -> decltype(_Param(cancellation_token::none()), std::true_type());
3032 
3033  // A parameter lambda taking a progress report argument is valid
3034  template<typename _Ty>
3035  static auto _IsValidCreateAsync(_Ty _Param, int, int, ...) -> decltype(_Param(details::_ProgressReporterCtorArgType()), std::true_type());
3036 
3037  // A parameter lambda taking a progress report and a cancellation_token argument is valid
3038  template<typename _Ty>
3039  static auto _IsValidCreateAsync(_Ty _Param, int, ...) -> decltype(_Param(details::_ProgressReporterCtorArgType(), cancellation_token::none()), std::true_type());
3040 
3041  // All else is invalid
3042  template<typename _Ty>
3043  static std::false_type _IsValidCreateAsync(_Ty _Param, ...);
3044 #endif /* defined (__cplusplus_winrt) */
3045 }
3050 template<typename _InpType, typename _OutType>
3052 {
3053 public:
3054  static auto _Perform(std::function<_OutType(_InpType)> _Func) -> decltype(_Func)
3055  {
3056  return _Func;
3057  }
3058 };
3059 
3060 template<typename _OutType>
3061 class _Continuation_func_transformer<void, _OutType>
3062 {
3063 public:
3064  static auto _Perform(std::function<_OutType(void)> _Func) -> decltype(details::_MakeUnitToTFunc<_OutType>(_Func))
3065  {
3066  return details::_MakeUnitToTFunc<_OutType>(_Func);
3067  }
3068 };
3069 
3070 template<typename _InType>
3072 {
3073 public:
3074  static auto _Perform(std::function<void(_InType)> _Func) -> decltype(details::_MakeTToUnitFunc<_InType>(_Func))
3075  {
3076  return details::_MakeTToUnitFunc<_InType>(_Func);
3077  }
3078 };
3079 
3080 template<>
3082 {
3083 public:
3084  static auto _Perform(std::function<void(void)> _Func) -> decltype(details::_MakeUnitToUnitFunc(_Func))
3085  {
3086  return details::_MakeUnitToUnitFunc(_Func);
3087  }
3088 };
3089 
3090 // A helper class template that transforms an intial task lambda returns void into a lambda that returns a non-void type (details::_Unit_type is used
3091 // to substitute for void). This is to minimize the special handling required for 'void'.
3092 template<typename _RetType>
3094 {
3095 public:
3096  static auto _Perform(std::function<_RetType(void)> _Func) -> decltype(_Func)
3097  {
3098  return _Func;
3099  }
3100 };
3101 
3102 template<>
3104 {
3105 public:
3106  static auto _Perform(std::function<void(void)> _Func) -> decltype(details::_MakeVoidToUnitFunc(_Func))
3107  {
3108  return details::_MakeVoidToUnitFunc(_Func);
3109  }
3110 };
3111 
3125 
3126 template<typename _ReturnType>
3127 class task
3128 {
3129 public:
3133 
3134  typedef _ReturnType result_type;
3135 
3157 
3158  task() : _M_Impl(nullptr)
3159  {
3160  // The default constructor should create a task with a nullptr impl. This is a signal that the
3161  // task is not usable and should throw if any wait(), get() or then() APIs are used.
3162  }
3163 
3198 
3199  template<typename _Ty>
3200  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3201  explicit task(_Ty _Param)
3202  {
3203  task_options _TaskOptions;
3204  details::_ValidateTaskConstructorArgs<_ReturnType,_Ty>(_Param);
3205 
3206  _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
3207  // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluate to the the call site of the task constructor.
3208  _SetTaskCreationCallstack(_CAPTURE_CALLSTACK());
3209 
3210  _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param,0));
3211  }
3212 
3246 
3247  template<typename _Ty>
3248  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3249  explicit task(_Ty _Param, const task_options &_TaskOptions)
3250  {
3251  details::_ValidateTaskConstructorArgs<_ReturnType,_Ty>(_Param);
3252 
3253  _CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
3254  // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluate to the the call site of the task constructor.
3255  _SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK());
3256 
3257  _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param,0));
3258  }
3259 
3284 
3285  task(const task& _Other): _M_Impl(_Other._M_Impl) {}
3286 
3311 
3312  task(task&& _Other): _M_Impl(std::move(_Other._M_Impl)) {}
3313 
3324 
3325  task& operator=(const task& _Other)
3326  {
3327  if (this != &_Other)
3328  {
3329  _M_Impl = _Other._M_Impl;
3330  }
3331  return *this;
3332  }
3333 
3344 
3345  task& operator=(task&& _Other)
3346  {
3347  if (this != &_Other)
3348  {
3349  _M_Impl = std::move(_Other._M_Impl);
3350  }
3351  return *this;
3352  }
3353 
3373 
3374  template<typename _Function>
3375  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3376  auto then(const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3377  {
3378  task_options _TaskOptions;
3380  return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
3381  }
3382 
3406 
3407  template<typename _Function>
3408  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3409  auto then(const _Function& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3410  {
3412  return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
3413  }
3414 
3442 
3443  template<typename _Function>
3444  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3445  auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3446  {
3447  task_options _TaskOptions(_CancellationToken, _ContinuationContext);
3449  return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
3450  }
3451 
3460 
3461  task_status wait() const
3462  {
3463  if (!_M_Impl)
3464  {
3465  throw invalid_operation("wait() cannot be called on a default constructed task.");
3466  }
3467 
3468  return _M_Impl->_Wait();
3469  }
3470 
3482 
3483  _ReturnType get() const
3484  {
3485  if (!_M_Impl)
3486  {
3487  throw invalid_operation("get() cannot be called on a default constructed task.");
3488  }
3489 
3490  if (_M_Impl->_Wait() == canceled)
3491  {
3492  throw task_canceled();
3493  }
3494 
3495  return _M_Impl->_GetResult();
3496  }
3497 
3507  bool is_done() const
3508  {
3509  if (!_M_Impl)
3510  {
3511  throw invalid_operation("is_done() cannot be called on a default constructed task.");
3512  }
3513 
3514  return _M_Impl->_IsDone();
3515  }
3516 
3524  {
3525  if (!_M_Impl)
3526  {
3527  throw invalid_operation("scheduler() cannot be called on a default constructed task.");
3528  }
3529 
3530  return _M_Impl->_GetScheduler();
3531  }
3532 
3539 
3540  bool is_apartment_aware() const
3541  {
3542  if (!_M_Impl)
3543  {
3544  throw invalid_operation("is_apartment_aware() cannot be called on a default constructed task.");
3545  }
3546  return _M_Impl->_IsApartmentAware();
3547  }
3548 
3555 
3556  bool operator==(const task<_ReturnType>& _Rhs) const
3557  {
3558  return (_M_Impl == _Rhs._M_Impl);
3559  }
3560 
3567 
3568  bool operator!=(const task<_ReturnType>& _Rhs) const
3569  {
3570  return !operator==(_Rhs);
3571  }
3572 
3577  {
3578  _ASSERTE(_Ct != nullptr);
3579  _M_Impl = details::_Task_ptr<_ReturnType>::_Make(_Ct, _Scheduler);
3581  {
3582  _M_Impl->_RegisterCancellation(_M_Impl);
3583  }
3584  }
3585 
3590  {
3591  return _M_Impl;
3592  }
3593 
3598  {
3599  _ASSERTE(!_M_Impl);
3600  _M_Impl = _Impl;
3601  }
3602 
3607  {
3608  _ASSERTE(!_M_Impl);
3609  _M_Impl = std::move(_Impl);
3610  }
3611 
3615  void _SetAsync(bool _Async = true)
3616  {
3617  _GetImpl()->_SetAsync(_Async);
3618  }
3619 
3624  {
3625  _GetImpl()->_SetTaskCreationCallstack(_callstack);
3626  }
3627 
3633  template<typename _Function>
3634  auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState,
3635  details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3636  {
3637  // inherit from antecedent
3638  auto _Scheduler = _GetImpl()->_GetScheduler();
3639 
3640  return _ThenImpl<_ReturnType, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
3641  }
3642 
3643 private:
3644  template <typename T> friend class task;
3645 
3646 
3647  // The task handle type used to construct an 'initial task' - a task with no dependents.
3648  template <typename _InternalReturnType, typename _Function, typename _TypeSelection>
3650  details::_PPLTaskHandle<_ReturnType, _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>, details::_UnrealizedChore_t>
3651  {
3652  _Function _M_function;
3653  _InitialTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _TaskImpl, const _Function & _func)
3654  : details::_PPLTaskHandle<_ReturnType, _InitialTaskHandle<_InternalReturnType, _Function, _TypeSelection>, details::_UnrealizedChore_t>::_PPLTaskHandle(_TaskImpl)
3655  , _M_function(_func)
3656  {
3657  }
3658 
3659  virtual ~_InitialTaskHandle() {}
3660 
3661  template <typename _Func>
3662  auto _LogWorkItemAndInvokeUserLambda(_Func && _func) const -> decltype(_func())
3663  {
3664  details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
3665  return _func();
3666  }
3667 
3668  void _Perform() const
3669  {
3670  _Init(_TypeSelection());
3671  }
3672 
3674  {
3675  this->_M_pTask->_Cancel(true);
3676  }
3677 
3678  //
3679  // Overload 0: returns _InternalReturnType
3680  //
3681  // This is the most basic task with no unwrapping
3682  //
3684  {
3685  this->_M_pTask->_FinalizeAndRunContinuations(_LogWorkItemAndInvokeUserLambda(_Init_func_transformer<_InternalReturnType>::_Perform(_M_function)));
3686  }
3687 
3688  //
3689  // Overload 1: returns IAsyncOperation<_InternalReturnType>^ (only uder /ZW)
3690  // or
3691  // returns task<_InternalReturnType>
3692  //
3693  // This is task whose functor returns an async operation or a task which will be unwrapped for continuation
3694  // Depending on the output type, the right _AsyncInit gets invoked
3695  //
3697  {
3698  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask, _LogWorkItemAndInvokeUserLambda(_M_function));
3699  }
3700 
3701 #if defined (__cplusplus_winrt)
3702  //
3703  // Overload 2: returns IAsyncAction^
3704  //
3705  // This is task whose functor returns an async action which will be unwrapped for continuation
3706  //
3707  void _Init(details::_TypeSelectorAsyncAction) const
3708  {
3709  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask, ref new details::_IAsyncActionToAsyncOperationConverter(_LogWorkItemAndInvokeUserLambda(_M_function)));
3710  }
3711 
3712  //
3713  // Overload 3: returns IAsyncOperationWithProgress<_InternalReturnType, _ProgressType>^
3714  //
3715  // This is task whose functor returns an async operation with progress which will be unwrapped for continuation
3716  //
3718  {
3720 
3721  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask,
3722  ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_InternalReturnType,_ProgressType>(_LogWorkItemAndInvokeUserLambda(_M_function)));
3723  }
3724 
3725  //
3726  // Overload 4: returns IAsyncActionWithProgress<_ProgressType>^
3727  //
3728  // This is task whose functor returns an async action with progress which will be unwrapped for continuation
3729  //
3730  void _Init(details::_TypeSelectorAsyncActionWithProgress) const
3731  {
3733 
3734  details::_Task_impl_base::_AsyncInit<_ReturnType, _InternalReturnType>(this->_M_pTask,
3735  ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(_LogWorkItemAndInvokeUserLambda(_M_function)));
3736  }
3737 #endif /* defined (__cplusplus_winrt) */
3738  };
3739 
3740 
3744  template <typename _InternalReturnType, typename _ContinuationReturnType, typename _Function, typename _IsTaskBased, typename _TypeSelection>
3746  details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3747  _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
3748  {
3750 
3752  _Function _M_function;
3753 
3755  const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type & _ContinuationImpl,
3756  const _Function & _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode)
3757  : details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3758  _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
3759  ::_PPLTaskHandle(_ContinuationImpl)
3760  , _M_ancestorTaskImpl(_AncestorImpl)
3761  , _M_function(_Func)
3762  {
3763  this->_M_isTaskBasedContinuation = _IsTaskBased::value;
3764  this->_M_continuationContext = _Context;
3765  this->_M_continuationContext._Resolve(_AncestorImpl->_IsApartmentAware());
3766  this->_M_inliningMode = _InliningMode;
3767  }
3768 
3770 
3771  template <typename _Func, typename _Arg>
3772  auto _LogWorkItemAndInvokeUserLambda(_Func && _func, _Arg && _value) const -> decltype(_func(std::forward<_Arg>(_value)))
3773  {
3774  details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger);
3775  return _func(std::forward<_Arg>(_value));
3776  }
3777 
3778  void _Perform() const
3779  {
3780  _Continue(_IsTaskBased(), _TypeSelection());
3781  }
3782 
3784  {
3785  if (_M_ancestorTaskImpl->_HasUserException())
3786  {
3787  // If the ancestor encountered an exception, transfer the exception to the continuation
3788  // This traverses down the tree to propagate the exception.
3789  this->_M_pTask->_CancelWithExceptionHolder(_M_ancestorTaskImpl->_GetExceptionHolder(), true);
3790  }
3791  else
3792  {
3793  // If the ancestor was canceled, then your own execution should be canceled.
3794  // This traverses down the tree to cancel it.
3795  this->_M_pTask->_Cancel(true);
3796  }
3797  }
3798 
3799  //
3800  // Overload 0-0: _InternalReturnType -> _TaskType
3801  //
3802  // This is a straight task continuation which simply invokes its target with the ancestor's completion argument
3803  //
3805  {
3806  this->_M_pTask->_FinalizeAndRunContinuations(
3807  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _ContinuationReturnType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult()));
3808  }
3809 
3810  //
3811  // Overload 0-1: _InternalReturnType -> IAsyncOperation<_TaskType>^ (only uder /ZW)
3812  // or
3813  // _InternalReturnType -> task<_TaskType>
3814  //
3815  // This is a straight task continuation which returns an async operation or a task which will be unwrapped for continuation
3816  // Depending on the output type, the right _AsyncInit gets invoked
3817  //
3819  {
3821 
3822  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3823  this->_M_pTask,
3824  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult())
3825  );
3826  }
3827 
3828 #if defined (__cplusplus_winrt)
3829  //
3830  // Overload 0-2: _InternalReturnType -> IAsyncAction^
3831  //
3832  // This is a straight task continuation which returns an async action which will be unwrapped for continuation
3833  //
3834  void _Continue(std::false_type, details::_TypeSelectorAsyncAction) const
3835  {
3837 
3838  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3839  this->_M_pTask,
3840  ref new details::_IAsyncActionToAsyncOperationConverter(
3841  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult())));
3842  }
3843 
3844  //
3845  // Overload 0-3: _InternalReturnType -> IAsyncOperationWithProgress<_TaskType, _ProgressType>^
3846  //
3847  // This is a straight task continuation which returns an async operation with progress which will be unwrapped for continuation
3848  //
3850  {
3852 
3853  auto _OpWithProgress = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult());
3855 
3856  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3857  this->_M_pTask,
3858  ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType, _ProgressType>(_OpWithProgress));
3859  }
3860 
3861  //
3862  // Overload 0-4: _InternalReturnType -> IAsyncActionWithProgress<_ProgressType>^
3863  //
3864  // This is a straight task continuation which returns an async action with progress which will be unwrapped for continuation
3865  //
3866  void _Continue(std::false_type, details::_TypeSelectorAsyncActionWithProgress) const
3867  {
3868  typedef details::_FunctionTypeTraits<_Function, _InternalReturnType>::_FuncRetType _FuncOutputType;
3869 
3870  auto _OpWithProgress = _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_InternalReturnType, _FuncOutputType>::_Perform(_M_function), _M_ancestorTaskImpl->_GetResult());
3872 
3873  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(
3874  this->_M_pTask,
3875  ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(_OpWithProgress));
3876  }
3877 
3878 #endif /* defined (__cplusplus_winrt) */
3879 
3880  //
3881  // Overload 1-0: task<_InternalReturnType> -> _TaskType
3882  //
3883  // This is an exception handling type of continuation which takes the task rather than the task's result.
3884  //
3886  {
3887  typedef task<_InternalReturnType> _FuncInputType;
3888  task<_InternalReturnType> _ResultTask;
3889  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3890  this->_M_pTask->_FinalizeAndRunContinuations(
3891  _LogWorkItemAndInvokeUserLambda(_Continuation_func_transformer<_FuncInputType, _ContinuationReturnType>::_Perform(_M_function), std::move(_ResultTask)));
3892  }
3893 
3894  //
3895  // Overload 1-1: task<_InternalReturnType> -> IAsyncOperation<_TaskType>^
3896  // or
3897  // task<_TaskType>
3898  //
3899  // This is an exception handling type of continuation which takes the task rather than
3900  // the task's result. It also returns an async operation or a task which will be unwrapped
3901  // for continuation
3902  //
3904  {
3905  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3906  task<_InternalReturnType> _ResultTask;
3907  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3908  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3909  _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask)));
3910  }
3911 
3912 #if defined (__cplusplus_winrt)
3913 
3914  //
3915  // Overload 1-2: task<_InternalReturnType> -> IAsyncAction^
3916  //
3917  // This is an exception handling type of continuation which takes the task rather than
3918  // the task's result. It also returns an async action which will be unwrapped for continuation
3919  //
3920  void _Continue(std::true_type, details::_TypeSelectorAsyncAction) const
3921  {
3922  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3923  task<_InternalReturnType> _ResultTask;
3924  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3925  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3926  ref new details::_IAsyncActionToAsyncOperationConverter(_LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
3927  }
3928 
3929  //
3930  // Overload 1-3: task<_InternalReturnType> -> IAsyncOperationWithProgress<_TaskType, _ProgressType>^
3931  //
3932  // This is an exception handling type of continuation which takes the task rather than
3933  // the task's result. It also returns an async operation with progress which will be unwrapped
3934  // for continuation
3935  //
3937  {
3938  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3939  task<_InternalReturnType> _ResultTask;
3940  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3941 
3943 
3944  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3945  ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<_ContinuationReturnType, _ProgressType>(
3946  _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
3947  }
3948 
3949  //
3950  // Overload 1-4: task<_InternalReturnType> -> IAsyncActionWithProgress<_ProgressType>^
3951  //
3952  // This is an exception handling type of continuation which takes the task rather than
3953  // the task's result. It also returns an async operation with progress which will be unwrapped
3954  // for continuation
3955  //
3956  void _Continue(std::true_type, details::_TypeSelectorAsyncActionWithProgress) const
3957  {
3958  // The continuation takes a parameter of type task<_Input>, which is the same as the ancestor task.
3959  task<_InternalReturnType> _ResultTask;
3960  _ResultTask._SetImpl(std::move(_M_ancestorTaskImpl));
3961 
3963 
3964  details::_Task_impl_base::_AsyncInit<_NormalizedContinuationReturnType, _ContinuationReturnType>(this->_M_pTask,
3965  ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_ProgressType>(
3966  _LogWorkItemAndInvokeUserLambda(_M_function, std::move(_ResultTask))));
3967  }
3968 #endif /* defined (__cplusplus_winrt) */
3969  };
3970 
3974  template<typename _InternalReturnType, typename _Function>
3975  void _TaskInitWithFunctor(const _Function& _Func)
3976  {
3978 
3979  _M_Impl->_M_fFromAsync = _Async_type_traits::_IsAsyncTask;
3980  _M_Impl->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
3981  _M_Impl->_M_taskEventLogger._LogScheduleTask(false);
3982  _M_Impl->_ScheduleTask(new _InitialTaskHandle<_InternalReturnType, _Function, typename _Async_type_traits::_AsyncKind>(_GetImpl(), _Func), details::_NoInline);
3983  }
3984 
3989  {
3990  _Event._RegisterTask(_M_Impl);
3991  }
3992 
3993 #if defined (__cplusplus_winrt)
3994  void _TaskInitAsyncOp(Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
3998  {
3999  _M_Impl->_M_fFromAsync = true;
4000 
4001  // Mark this task as started here since we can set the state in the constructor without acquiring a lock. Once _AsyncInit
4002  // returns a completion could execute concurrently and the task must be fully initialized before that happens.
4003  _M_Impl->_M_TaskState = details::_Task_impl_base::_Started;
4004  // Pass the shared pointer into _AsyncInit for storage in the Async Callback.
4005  details::_Task_impl_base::_AsyncInit<_ReturnType, _ReturnType>(_M_Impl, _AsyncOp);
4006  }
4007 
4011  void _TaskInitNoFunctor(Windows::Foundation::IAsyncOperation<typename details::_ValueTypeOrRefType<_ReturnType>::_Value>^ _AsyncOp)
4012  {
4013  _TaskInitAsyncOp(_AsyncOp);
4014  }
4015 
4019  template<typename _Progress>
4020  void _TaskInitNoFunctor(Windows::Foundation::IAsyncOperationWithProgress<typename details::_ValueTypeOrRefType<_ReturnType>::_Value, _Progress>^ _AsyncOp)
4021  {
4022  _TaskInitAsyncOp(ref new details::_IAsyncOperationWithProgressToAsyncOperationConverter<typename details::_ValueTypeOrRefType<_ReturnType>::_Value, _Progress>(_AsyncOp));
4023  }
4024 #endif /* defined (__cplusplus_winrt) */
4025 
4029  template<typename _Function>
4030  void _TaskInitMaybeFunctor(_Function & _Func, std::true_type)
4031  {
4032  _TaskInitWithFunctor<_ReturnType, _Function>(_Func);
4033  }
4034 
4038  template<typename _Ty>
4040  {
4041  _TaskInitNoFunctor(_Param);
4042  }
4043 
4044  template<typename _InternalReturnType, typename _Function>
4045  auto _ThenImpl(const _Function& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4046  {
4047  if (!_M_Impl)
4048  {
4049  throw invalid_operation("then() cannot be called on a default constructed task.");
4050  }
4051 
4052  details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
4053  auto _Scheduler = _TaskOptions.has_scheduler() ? _TaskOptions.get_scheduler() : _GetImpl()->_GetScheduler();
4055  return _ThenImpl<_InternalReturnType, _Function>(_Func, _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack);
4056  }
4057 
4061  template<typename _InternalReturnType, typename _Function>
4062  auto _ThenImpl(const _Function& _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack,
4063  details::_TaskInliningMode_t _InliningMode = details::_NoInline) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4064  {
4065  if (!_M_Impl)
4066  {
4067  throw invalid_operation("then() cannot be called on a default constructed task.");
4068  }
4069 
4072  typedef typename _Async_type_traits::_TaskRetType _TaskType;
4073 
4074  //
4075  // 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
4076  // an exception handling continuation. In that case, we break the chain with a _None. That continuation is never canceled unless the user
4077  // explicitly passes the same token.
4078  //
4079  if (_PTokenState == nullptr)
4080  {
4081  if (_Function_type_traits::_Takes_task::value)
4082  {
4083  _PTokenState = details::_CancellationTokenState::_None();
4084  }
4085  else
4086  {
4087  _PTokenState = _GetImpl()->_M_pTokenState;
4088  }
4089  }
4090 
4091  task<_TaskType> _ContinuationTask;
4092  _ContinuationTask._CreateImpl(_PTokenState, _Scheduler);
4093 
4094  _ContinuationTask._GetImpl()->_M_fFromAsync = (_GetImpl()->_M_fFromAsync || _Async_type_traits::_IsAsyncTask);
4095  _ContinuationTask._GetImpl()->_M_fUnwrappedTask = _Async_type_traits::_IsUnwrappedTaskOrAsync;
4096  _ContinuationTask._SetTaskCreationCallstack(_CreationStack);
4097 
4098  _GetImpl()->_ScheduleContinuation(new _ContinuationTaskHandle<_InternalReturnType, _TaskType, _Function, typename _Function_type_traits::_Takes_task, typename _Async_type_traits::_AsyncKind>(
4099  _GetImpl(), _ContinuationTask._GetImpl(), _Func, _ContinuationContext, _InliningMode));
4100 
4101  return _ContinuationTask;
4102  }
4103 
4104  // The underlying implementation for this task
4106 };
4107 
4118 
4119 template<>
4120 class task<void>
4121 {
4122 public:
4126 
4127  typedef void result_type;
4128 
4150 
4151  task() : _M_unitTask()
4152  {
4153  // The default constructor should create a task with a nullptr impl. This is a signal that the
4154  // task is not usable and should throw if any wait(), get() or then() APIs are used.
4155  }
4156 
4187 
4188  template<typename _Ty>
4189  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4190  explicit task(_Ty _Param, const task_options& _TaskOptions = task_options())
4191  {
4192  details::_ValidateTaskConstructorArgs<void,_Ty>(_Param);
4193 
4194  _M_unitTask._CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler());
4195  // Do not move the next line out of this function. It is important that _CAPTURE_CALLSTACK() evaluate to the the call site of the task constructor.
4196  _M_unitTask._SetTaskCreationCallstack(details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : _CAPTURE_CALLSTACK());
4197 
4198  _TaskInitMaybeFunctor(_Param, details::_IsCallable(_Param,0));
4199  }
4200 
4225 
4226  task(const task& _Other): _M_unitTask(_Other._M_unitTask){}
4227 
4252 
4253  task(task&& _Other) : _M_unitTask(std::move(_Other._M_unitTask)) {}
4254 
4265 
4266  task& operator=(const task& _Other)
4267  {
4268  if (this != &_Other)
4269  {
4270  _M_unitTask = _Other._M_unitTask;
4271  }
4272  return *this;
4273  }
4274 
4285 
4286  task& operator=(task&& _Other)
4287  {
4288  if (this != &_Other)
4289  {
4290  _M_unitTask = std::move(_Other._M_unitTask);
4291  }
4292  return *this;
4293  }
4294 
4318 
4319  template<typename _Function>
4320  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4321  auto then(const _Function& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4322  {
4324  return _M_unitTask._ThenImpl<void, _Function>(_Func, _TaskOptions);
4325  }
4326 
4354 
4355  template<typename _Function>
4356  __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4357  auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4358  {
4359  task_options _TaskOptions(_CancellationToken, _ContinuationContext);
4361  return _M_unitTask._ThenImpl<void, _Function>(_Func, _TaskOptions);
4362  }
4363 
4372 
4373  task_status wait() const
4374  {
4375  return _M_unitTask.wait();
4376  }
4377 
4386 
4387  void get() const
4388  {
4389  _M_unitTask.get();
4390  }
4391 
4401  bool is_done() const
4402  {
4403  return _M_unitTask.is_done();
4404  }
4405 
4413  {
4414  return _M_unitTask.scheduler();
4415  }
4416 
4423 
4424  bool is_apartment_aware() const
4425  {
4426  return _M_unitTask.is_apartment_aware();
4427  }
4428 
4435 
4436  bool operator==(const task<void>& _Rhs) const
4437  {
4438  return (_M_unitTask == _Rhs._M_unitTask);
4439  }
4440 
4447 
4448  bool operator!=(const task<void>& _Rhs) const
4449  {
4450  return !operator==(_Rhs);
4451  }
4452 
4457  {
4458  _M_unitTask._CreateImpl(_Ct, _Scheduler);
4459  }
4460 
4465  {
4466  return _M_unitTask._M_Impl;
4467  }
4468 
4473  {
4474  _M_unitTask._SetImpl(_Impl);
4475  }
4476 
4481  {
4482  _M_unitTask._SetImpl(std::move(_Impl));
4483  }
4484 
4488  void _SetAsync(bool _Async = true)
4489  {
4490  _M_unitTask._SetAsync(_Async);
4491  }
4492 
4497  {
4498  _M_unitTask._SetTaskCreationCallstack(_callstack);
4499  }
4500 
4504  template<typename _Function>
4505  auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState,
4506  details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4507  {
4508  // inherit from antecedent
4509  auto _Scheduler = _GetImpl()->_GetScheduler();
4510 
4511  return _M_unitTask._ThenImpl<void, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
4512  }
4513 
4514 private:
4515  template <typename T> friend class task;
4516  template <typename T> friend class task_completion_event;
4517 
4522  {
4523  _M_unitTask._TaskInitNoFunctor(_Event._M_unitEvent);
4524  }
4525 
4526 #if defined (__cplusplus_winrt)
4527  void _TaskInitNoFunctor(Windows::Foundation::IAsyncAction^ _AsyncAction)
4531  {
4532  _M_unitTask._TaskInitAsyncOp(ref new details::_IAsyncActionToAsyncOperationConverter(_AsyncAction));
4533  }
4534 
4538  template<typename _P>
4539  void _TaskInitNoFunctor(Windows::Foundation::IAsyncActionWithProgress<_P>^ _AsyncActionWithProgress)
4540  {
4541  _M_unitTask._TaskInitAsyncOp(ref new details::_IAsyncActionWithProgressToAsyncOperationConverter<_P>(_AsyncActionWithProgress));
4542  }
4543 #endif /* defined (__cplusplus_winrt) */
4544 
4548  template<typename _Function>
4549  void _TaskInitMaybeFunctor(_Function & _Func, std::true_type)
4550  {
4551  _M_unitTask._TaskInitWithFunctor<void, _Function>(_Func);
4552  }
4553 
4557  template<typename _T>
4559  {
4560  _TaskInitNoFunctor(_Param);
4561  }
4562 
4563  // The void task contains a task of a dummy type so common code can be used for tasks with void and non-void results.
4565 };
4566 
4567 namespace details
4568 {
4572 
4573 #if defined (__cplusplus_winrt)
4574  // Unwrap functions for asyncOperations
4575  template<typename _Ty>
4576  _Ty _GetUnwrappedType(Windows::Foundation::IAsyncOperation<_Ty>^);
4577 
4578  void _GetUnwrappedType(Windows::Foundation::IAsyncAction^);
4579 
4580  template<typename _Ty, typename _Progress>
4581  _Ty _GetUnwrappedType(Windows::Foundation::IAsyncOperationWithProgress<_Ty, _Progress>^);
4582 
4583  template<typename _Progress>
4584  void _GetUnwrappedType(Windows::Foundation::IAsyncActionWithProgress<_Progress>^);
4585 #endif /* defined (__cplusplus_winrt) */
4586 
4587  // Unwrap task<T>
4588  template<typename _Ty>
4590 
4591  // Unwrap all supportted types
4592  template<typename _Ty>
4593  auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg));
4594  // fallback
4595  template<typename _Ty>
4596  _Ty _GetUnwrappedReturnType(_Ty, ...);
4597 
4603 
4604  // Non-Callable
4605  template<typename _Ty>
4607 
4608  // Non-Callable
4609  template<typename _Ty>
4610  auto _GetTaskType(_Ty _NonFunc, std::false_type) -> decltype(_GetUnwrappedType(_NonFunc));
4611 
4612  // Callable
4613  template<typename _Ty>
4614  auto _GetTaskType(_Ty _Func, std::true_type) -> decltype(_GetUnwrappedReturnType(_Func(), 0));
4615 
4616  // Special callable returns void
4617  void _GetTaskType(std::function<void()>, std::true_type);
4618  struct _BadArgType{};
4619 
4620  template<typename _Ty>
4621  auto _FilterValidTaskType(_Ty _Param, int) -> decltype(_GetTaskType(_Param, _IsCallable(_Param, 0)));
4622 
4623  template<typename _Ty>
4624  _BadArgType _FilterValidTaskType(_Ty _Param, ...);
4625 
4626  template<typename _Ty>
4628  {
4629  typedef decltype(_FilterValidTaskType(stdx::declval<_Ty>(), 0)) _Type;
4630  };
4631 } // namespace details
4632 
4660 
4661 template<typename _Ty>
4662 __declspec(noinline)
4663 auto create_task(_Ty _Param, task_options _TaskOptions = task_options()) -> task<typename details::_TaskTypeFromParam<_Ty>::_Type>
4664 {
4665  static_assert(!std::is_same<typename details::_TaskTypeFromParam<_Ty>::_Type,details::_BadArgType>::value,
4666 #if defined (__cplusplus_winrt)
4667  "incorrect argument for create_task; can be a callable object, an asynchronous operation, or a task_completion_event"
4668 #else /* defined (__cplusplus_winrt) */
4669  "incorrect argument for create_task; can be a callable object or a task_completion_event"
4670 #endif /* defined (__cplusplus_winrt) */
4671  );
4673  task<typename details::_TaskTypeFromParam<_Ty>::_Type> _CreatedTask(_Param, _TaskOptions);
4674  return _CreatedTask;
4675 }
4676 
4707 
4708 template<typename _ReturnType>
4709 __declspec(noinline)
4710 task<_ReturnType> create_task(const task<_ReturnType>& _Task)
4711 {
4712  task<_ReturnType> _CreatedTask(_Task);
4713  return _CreatedTask;
4714 }
4715 
4716 #if defined (__cplusplus_winrt)
4717 namespace details
4718 {
4719  template<typename _T>
4720  task<_T> _To_task_helper(Windows::Foundation::IAsyncOperation<_T>^ op)
4721  {
4722  return task<_T>(op);
4723  }
4724 
4725  template<typename _T, typename _Progress>
4726  task<_T> _To_task_helper(Windows::Foundation::IAsyncOperationWithProgress<_T, _Progress>^ op)
4727  {
4728  return task<_T>(op);
4729  }
4730 
4731  inline task<void> _To_task_helper(Windows::Foundation::IAsyncAction^ op)
4732  {
4733  return task<void>(op);
4734  }
4735 
4736  template<typename _Progress>
4737  task<void> _To_task_helper(Windows::Foundation::IAsyncActionWithProgress<_Progress>^ op)
4738  {
4739  return task<void>(op);
4740  }
4741 
4742  template<typename _ProgressType>
4743  class _ProgressDispatcherBase
4744  {
4745  public:
4746 
4747  virtual ~_ProgressDispatcherBase()
4748  {
4749  }
4750 
4751  virtual void _Report(const _ProgressType& _Val) = 0;
4752  };
4753 
4754  template<typename _ProgressType, typename _ClassPtrType>
4755  class _ProgressDispatcher : public _ProgressDispatcherBase<_ProgressType>
4756  {
4757  public:
4758 
4759  virtual ~_ProgressDispatcher()
4760  {
4761  }
4762 
4763  _ProgressDispatcher(_ClassPtrType _Ptr) : _M_ptr(_Ptr)
4764  {
4765  }
4766 
4767  virtual void _Report(const _ProgressType& _Val)
4768  {
4769  _M_ptr->_FireProgress(_Val);
4770  }
4771 
4772  private:
4773 
4774  _ClassPtrType _M_ptr;
4775  };
4776  class _ProgressReporterCtorArgType{};
4777 } // namespace details
4778 
4790 
4791 template<typename _ProgressType>
4792 class progress_reporter
4793 {
4794  typedef std::shared_ptr<details::_ProgressDispatcherBase<_ProgressType>> _PtrType;
4795 
4796 public:
4797 
4804 
4805  void report(const _ProgressType& _Val) const
4806  {
4807  _M_dispatcher->_Report(_Val);
4808  }
4809 
4810  template<typename _ClassPtrType>
4811  static progress_reporter _CreateReporter(_ClassPtrType _Ptr)
4812  {
4813  progress_reporter _Reporter;
4814  details::_ProgressDispatcherBase<_ProgressType> *_PDispatcher = new details::_ProgressDispatcher<_ProgressType, _ClassPtrType>(_Ptr);
4815  _Reporter._M_dispatcher = _PtrType(_PDispatcher);
4816  return _Reporter;
4817  }
4818  progress_reporter() {}
4819 
4820 private:
4821  progress_reporter(details::_ProgressReporterCtorArgType);
4822 
4823  _PtrType _M_dispatcher;
4824 };
4825 
4826 namespace details
4827 {
4828  //
4829  // maps internal definitions for AsyncStatus and defines states that are not client visible
4830  //
4831  enum _AsyncStatusInternal
4832  {
4833  _AsyncCreated = -1, // externally invisible
4834  // client visible states (must match AsyncStatus exactly)
4835  _AsyncStarted = 0, // Windows::Foundation::AsyncStatus::Started,
4836  _AsyncCompleted = 1, // Windows::Foundation::AsyncStatus::Completed,
4837  _AsyncCanceled = 2, // Windows::Foundation::AsyncStatus::Canceled,
4838  _AsyncError = 3, // Windows::Foundation::AsyncStatus::Error,
4839  // non-client visible internal states
4840  _AsyncCancelPending,
4841  _AsyncClosed,
4842  _AsyncUndefined
4843  };
4844 
4845  //
4846  // designates whether the "GetResults" method returns a single result (after complete fires) or multiple results
4847  // (which are progressively consumable between Start state and before Close is called)
4848  //
4849  enum _AsyncResultType
4850  {
4851  SingleResult = 0x0001,
4852  MultipleResults = 0x0002
4853  };
4854 
4855  // ***************************************************************************
4856  // Template type traits and helpers for async production APIs:
4857  //
4858 
4859  struct _ZeroArgumentFunctor { };
4860  struct _OneArgumentFunctor { };
4861  struct _TwoArgumentFunctor { };
4862 
4863  // ****************************************
4864  // CLASS TYPES:
4865 
4866  // ********************
4867  // TWO ARGUMENTS:
4868 
4869  // non-void arg:
4870  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4871  _Arg1 _Arg1ClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4872 
4873  // non-void arg:
4874  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4875  _Arg2 _Arg2ClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4876 
4877  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4878  _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4879 
4880  template<typename _Class, typename _ReturnType, typename _Arg1, typename _Arg2>
4881  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)(_Arg1, _Arg2) const);
4882 
4883  // ********************
4884  // ONE ARGUMENT:
4885 
4886  // non-void arg:
4887  template<typename _Class, typename _ReturnType, typename _Arg1>
4888  _Arg1 _Arg1ClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
4889 
4890  // non-void arg:
4891  template<typename _Class, typename _ReturnType, typename _Arg1>
4892  void _Arg2ClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
4893 
4894  template<typename _Class, typename _ReturnType, typename _Arg1>
4895  _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)(_Arg1) const);
4896 
4897  template<typename _Class, typename _ReturnType, typename _Arg1>
4898  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)(_Arg1) const);
4899 
4900  // ********************
4901  // ZERO ARGUMENT:
4902 
4903  // void arg:
4904  template<typename _Class, typename _ReturnType>
4905  void _Arg1ClassHelperThunk(_ReturnType (_Class::*)() const);
4906 
4907  // void arg:
4908  template<typename _Class, typename _ReturnType>
4909  void _Arg2ClassHelperThunk(_ReturnType (_Class::*)() const);
4910 
4911  // void arg:
4912  template<typename _Class, typename _ReturnType>
4913  _ReturnType _ReturnTypeClassHelperThunk(_ReturnType (_Class::*)() const);
4914 
4915  template<typename _Class, typename _ReturnType>
4916  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType (_Class::*)() const);
4917 
4918  // ****************************************
4919  // POINTER TYPES:
4920 
4921  // ********************
4922  // TWO ARGUMENTS:
4923 
4924  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4925  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4926 
4927  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4928  _Arg2 _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4929 
4930  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4931  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4932 
4933  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4934  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1, _Arg2));
4935 
4936  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4937  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4938 
4939  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4940  _Arg2 _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4941 
4942  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4943  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4944 
4945  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4946  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1, _Arg2));
4947 
4948  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4949  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4950 
4951  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4952  _Arg2 _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4953 
4954  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4955  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4956 
4957  template<typename _ReturnType, typename _Arg1, typename _Arg2>
4958  _TwoArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1, _Arg2));
4959 
4960  // ********************
4961  // ONE ARGUMENT:
4962 
4963  template<typename _ReturnType, typename _Arg1>
4964  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
4965 
4966  template<typename _ReturnType, typename _Arg1>
4967  void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
4968 
4969  template<typename _ReturnType, typename _Arg1>
4970  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)(_Arg1));
4971 
4972  template<typename _ReturnType, typename _Arg1>
4973  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)(_Arg1));
4974 
4975  template<typename _ReturnType, typename _Arg1>
4976  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
4977 
4978  template<typename _ReturnType, typename _Arg1>
4979  void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
4980 
4981  template<typename _ReturnType, typename _Arg1>
4982  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)(_Arg1));
4983 
4984  template<typename _ReturnType, typename _Arg1>
4985  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)(_Arg1));
4986 
4987  template<typename _ReturnType, typename _Arg1>
4988  _Arg1 _Arg1PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
4989 
4990  template<typename _ReturnType, typename _Arg1>
4991  void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
4992 
4993  template<typename _ReturnType, typename _Arg1>
4994  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)(_Arg1));
4995 
4996  template<typename _ReturnType, typename _Arg1>
4997  _OneArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)(_Arg1));
4998 
4999  // ********************
5000  // ZERO ARGUMENT:
5001 
5002  template<typename _ReturnType>
5003  void _Arg1PFNHelperThunk(_ReturnType(__cdecl *)());
5004 
5005  template<typename _ReturnType>
5006  void _Arg2PFNHelperThunk(_ReturnType(__cdecl *)());
5007 
5008  template<typename _ReturnType>
5009  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__cdecl *)());
5010 
5011  template<typename _ReturnType>
5012  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__cdecl *)());
5013 
5014  template<typename _ReturnType>
5015  void _Arg1PFNHelperThunk(_ReturnType(__stdcall *)());
5016 
5017  template<typename _ReturnType>
5018  void _Arg2PFNHelperThunk(_ReturnType(__stdcall *)());
5019 
5020  template<typename _ReturnType>
5021  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__stdcall *)());
5022 
5023  template<typename _ReturnType>
5024  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__stdcall *)());
5025 
5026  template<typename _ReturnType>
5027  void _Arg1PFNHelperThunk(_ReturnType(__fastcall *)());
5028 
5029  template<typename _ReturnType>
5030  void _Arg2PFNHelperThunk(_ReturnType(__fastcall *)());
5031 
5032  template<typename _ReturnType>
5033  _ReturnType _ReturnTypePFNHelperThunk(_ReturnType(__fastcall *)());
5034 
5035  template<typename _ReturnType>
5036  _ZeroArgumentFunctor _ArgumentCountHelper(_ReturnType(__fastcall *)());
5037 
5038  template<typename _T>
5039  struct _FunctorArguments
5040  {
5041  static const size_t _Count = 0;
5042  };
5043 
5044  template<>
5045  struct _FunctorArguments<_OneArgumentFunctor>
5046  {
5047  static const size_t _Count = 1;
5048  };
5049 
5050  template<>
5051  struct _FunctorArguments<_TwoArgumentFunctor>
5052  {
5053  static const size_t _Count = 2;
5054  };
5055 
5056  template<typename _T>
5057  struct _FunctorTypeTraits
5058  {
5059  typedef decltype(_ArgumentCountHelper(&(_T::operator()))) _ArgumentCountType;
5060  static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
5061 
5062  typedef decltype(_ReturnTypeClassHelperThunk(&(_T::operator()))) _ReturnType;
5063  typedef decltype(_Arg1ClassHelperThunk(&(_T::operator()))) _Argument1Type;
5064  typedef decltype(_Arg2ClassHelperThunk(&(_T::operator()))) _Argument2Type;
5065  };
5066 
5067  template<typename _T>
5068  struct _FunctorTypeTraits<_T *>
5069  {
5070  typedef decltype(_ArgumentCountHelper(stdx::declval<_T*>())) _ArgumentCountType;
5071  static const size_t _ArgumentCount = _FunctorArguments<_ArgumentCountType>::_Count;
5072 
5073  typedef decltype(_ReturnTypePFNHelperThunk(stdx::declval<_T*>())) _ReturnType;
5074  typedef decltype(_Arg1PFNHelperThunk(stdx::declval<_T*>())) _Argument1Type;
5075  typedef decltype(_Arg2PFNHelperThunk(stdx::declval<_T*>())) _Argument2Type;
5076  };
5077 
5078  template<typename _T>
5079  struct _ProgressTypeTraits
5080  {
5081  static const bool _TakesProgress = false;
5082  typedef void _ProgressType;
5083  };
5084 
5085  template<typename _T>
5086  struct _ProgressTypeTraits<progress_reporter<_T>>
5087  {
5088  static const bool _TakesProgress = true;
5089  typedef typename _T _ProgressType;
5090  };
5091 
5092 
5093  template<typename _T, size_t count = _FunctorTypeTraits<_T>::_ArgumentCount>
5094  struct _CAFunctorOptions
5095  {
5096  static const bool _TakesProgress = false;
5097  static const bool _TakesToken = false;
5098  typedef void _ProgressType;
5099  };
5100 
5101  template<typename _T>
5102  struct _CAFunctorOptions<_T, 1>
5103  {
5104  private:
5105 
5106  typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
5107 
5108  public:
5109 
5110  static const bool _TakesProgress = _ProgressTypeTraits<_Argument1Type>::_TakesProgress;
5111  static const bool _TakesToken = !_TakesProgress;
5112  typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
5113  };
5114 
5115  template<typename _T>
5116  struct _CAFunctorOptions<_T, 2>
5117  {
5118  private:
5119 
5120  typedef typename _FunctorTypeTraits<_T>::_Argument1Type _Argument1Type;
5121 
5122  public:
5123 
5124  static const bool _TakesProgress = true;
5125  static const bool _TakesToken = true;
5126  typedef typename _ProgressTypeTraits<_Argument1Type>::_ProgressType _ProgressType;
5127  };
5128 
5129  ref class _Zip
5130  {
5131  };
5132 
5133  // ***************************************************************************
5134  // Async Operation Task Generators
5135  //
5136 
5137  //
5138  // Functor returns an IAsyncInfo - result needs to be wrapped in a task:
5139  //
5140  template<typename _AsyncSelector, typename _ReturnType>
5141  struct _SelectorTaskGenerator
5142  {
5143  template<typename _Function>
5144  static task<_ReturnType> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5145  {
5146  task_options _taskOptinos(_Cts.get_token());
5148  return task<_ReturnType>(_Func(), _taskOptinos);
5149  }
5150 
5151  template<typename _Function>
5152  static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5153  {
5154  task_options _taskOptinos(_Cts.get_token());
5156  return task<_ReturnType>(_Func(_Cts.get_token()), _taskOptinos);
5157  }
5158 
5159  template<typename _Function, typename _ProgressObject>
5160  static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5161  {
5162  task_options _taskOptinos(_Cts.get_token());
5164  return task<_ReturnType>(_Func(_Progress), _taskOptinos);
5165  }
5166 
5167  template<typename _Function, typename _ProgressObject>
5168  static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5169  {
5170  task_options _taskOptinos(_Cts.get_token());
5172  return task<_ReturnType>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
5173  }
5174  };
5175 
5176  template<typename _AsyncSelector>
5177  struct _SelectorTaskGenerator<_AsyncSelector, void>
5178  {
5179  template<typename _Function>
5180  static task<void> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5181  {
5182  task_options _taskOptinos(_Cts.get_token());
5184  return task<void>(_Func(), _taskOptinos);
5185  }
5186 
5187  template<typename _Function>
5188  static task<void> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5189  {
5190  task_options _taskOptinos(_Cts.get_token());
5192  return task<void>(_Func(_Cts.get_token()), _taskOptinos);
5193  }
5194 
5195  template<typename _Function, typename _ProgressObject>
5196  static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5197  {
5198  task_options _taskOptinos(_Cts.get_token());
5200  return task<void>(_Func(_Progress), _taskOptinos);
5201  }
5202 
5203  template<typename _Function, typename _ProgressObject>
5204  static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5205  {
5206  task_options _taskOptinos(_Cts.get_token());
5208  return task<void>(_Func(_Progress, _Cts.get_token()), _taskOptinos);
5209  }
5210  };
5211 
5212  //
5213  // Functor returns a result - it needs to be wrapped in a task:
5214  //
5215  template<typename _ReturnType>
5216  struct _SelectorTaskGenerator<_TypeSelectorNoAsync, _ReturnType>
5217  {
5218 
5219 #pragma warning(push)
5220 #pragma warning(disable: 4702)
5221  template<typename _Function>
5222  static task<_ReturnType> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5223  {
5224  task_options _taskOptinos(_Cts.get_token());
5226  return task<_ReturnType>( [=]() -> _ReturnType {
5227  _Task_generator_oversubscriber_t _Oversubscriber;
5228  (_Oversubscriber);
5229  return _Func();
5230  }, _taskOptinos);
5231  }
5232 #pragma warning(pop)
5233 
5234  template<typename _Function>
5235  static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5236  {
5237  task_options _taskOptinos(_Cts.get_token());
5239  return task<_ReturnType>( [=]() -> _ReturnType {
5240  _Task_generator_oversubscriber_t _Oversubscriber;
5241  (_Oversubscriber);
5242  return _Func(_Cts.get_token());
5243  }, _taskOptinos);
5244  }
5245 
5246  template<typename _Function, typename _ProgressObject>
5247  static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5248  {
5249  task_options _taskOptinos(_Cts.get_token());
5251  return task<_ReturnType>( [=]() -> _ReturnType {
5252  _Task_generator_oversubscriber_t _Oversubscriber;
5253  (_Oversubscriber);
5254  return _Func(_Progress);
5255  }, _taskOptinos);
5256  }
5257 
5258  template<typename _Function, typename _ProgressObject>
5259  static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5260  {
5261  task_options _taskOptinos(_Cts.get_token());
5263  return task<_ReturnType>( [=]() -> _ReturnType {
5264  _Task_generator_oversubscriber_t _Oversubscriber;
5265  (_Oversubscriber);
5266  return _Func(_Progress, _Cts.get_token());
5267  }, _taskOptinos);
5268  }
5269  };
5270 
5271  template<>
5272  struct _SelectorTaskGenerator<_TypeSelectorNoAsync, void>
5273  {
5274  template<typename _Function>
5275  static task<void> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5276  {
5277  task_options _taskOptinos(_Cts.get_token());
5279  return task<void>( [=]() {
5280  _Task_generator_oversubscriber_t _Oversubscriber;
5281  (_Oversubscriber);
5282  _Func();
5283  }, _taskOptinos);
5284  }
5285 
5286  template<typename _Function>
5287  static task<void> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5288  {
5289  task_options _taskOptinos(_Cts.get_token());
5291  return task<void>( [=]() {
5292  _Task_generator_oversubscriber_t _Oversubscriber;
5293  (_Oversubscriber);
5294  _Func(_Cts.get_token());
5295  }, _taskOptinos);
5296  }
5297 
5298  template<typename _Function, typename _ProgressObject>
5299  static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5300  {
5301  task_options _taskOptinos(_Cts.get_token());
5303  return task<void>( [=]() {
5304  _Task_generator_oversubscriber_t _Oversubscriber;
5305  (_Oversubscriber);
5306  _Func(_Progress);
5307  }, _taskOptinos);
5308  }
5309 
5310  template<typename _Function, typename _ProgressObject>
5311  static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5312  {
5313  task_options _taskOptinos(_Cts.get_token());
5315  return task<void>( [=]() {
5316  _Task_generator_oversubscriber_t _Oversubscriber;
5317  (_Oversubscriber);
5318  _Func(_Progress, _Cts.get_token());
5319  }, _taskOptinos);
5320  }
5321  };
5322 
5323  //
5324  // Functor returns a task - the task can directly be returned:
5325  //
5326  template<typename _ReturnType>
5327  struct _SelectorTaskGenerator<_TypeSelectorAsyncTask, _ReturnType>
5328  {
5329  template<typename _Function>
5330  static task<_ReturnType> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5331  {
5332  return _Func();
5333  }
5334 
5335  template<typename _Function>
5336  static task<_ReturnType> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5337  {
5338  return _Func(_Cts.get_token());
5339  }
5340 
5341  template<typename _Function, typename _ProgressObject>
5342  static task<_ReturnType> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5343  {
5344  return _Func(_Progress);
5345  }
5346 
5347  template<typename _Function, typename _ProgressObject>
5348  static task<_ReturnType> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5349  {
5350  return _Func(_Progress, _Cts.get_token());
5351  }
5352  };
5353 
5354  template<>
5355  struct _SelectorTaskGenerator<_TypeSelectorAsyncTask, void>
5356  {
5357  template<typename _Function>
5358  static task<void> _GenerateTask_0(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5359  {
5360  return _Func();
5361  }
5362 
5363  template<typename _Function>
5364  static task<void> _GenerateTask_1C(const _Function& _Func, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5365  {
5366  return _Func(_Cts.get_token());
5367  }
5368 
5369  template<typename _Function, typename _ProgressObject>
5370  static task<void> _GenerateTask_1P(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5371  {
5372  return _Func(_Progress);
5373  }
5374 
5375  template<typename _Function, typename _ProgressObject>
5376  static task<void> _GenerateTask_2PC(const _Function& _Func, const _ProgressObject& _Progress, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5377  {
5378  return _Func(_Progress, _Cts.get_token());
5379  }
5380  };
5381 
5382  template<typename _Generator, bool _TakesToken, bool TakesProgress>
5383  struct _TaskGenerator
5384  {
5385  };
5386 
5387  template<typename _Generator>
5388  struct _TaskGenerator<_Generator, false, false>
5389  {
5390  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5391  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5392  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5393  {
5394  return _Generator::_GenerateTask_0(_Func, _Cts, _callstack);
5395  }
5396  };
5397 
5398  template<typename _Generator>
5399  struct _TaskGenerator<_Generator, true, false>
5400  {
5401  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5402  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5403  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5404  {
5405  return _Generator::_GenerateTask_1C(_Func, _Cts, _callstack);
5406  }
5407  };
5408 
5409  template<typename _Generator>
5410  struct _TaskGenerator<_Generator, false, true>
5411  {
5412  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5413  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5414  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5415  {
5416  return _Generator::_GenerateTask_1P(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5417  }
5418  };
5419 
5420  template<typename _Generator>
5421  struct _TaskGenerator<_Generator, true, true>
5422  {
5423  template<typename _Function, typename _ClassPtr, typename _ProgressType>
5424  static auto _GenerateTask(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5425  -> decltype(_Generator::_GenerateTask_0(_Func, _Cts, _callstack))
5426  {
5427  return _Generator::_GenerateTask_2PC(_Func, progress_reporter<_ProgressType>::_CreateReporter(_Ptr), _Cts, _callstack);
5428  }
5429  };
5430 
5431  // ***************************************************************************
5432  // Async Operation Attributes Classes
5433  //
5434  // These classes are passed through the hierarchy of async base classes in order to hold multiple attributes of a given async construct in
5435  // a single container. An attribute class must define:
5436  //
5437  // Mandatory:
5438  // -------------------------
5439  //
5440  // _AsyncBaseType : The Windows Runtime interface which is being implemented.
5441  // _CompletionDelegateType : The Windows Runtime completion delegate type for the interface.
5442  // _ProgressDelegateType : If _TakesProgress is true, the Windows Runtime progress delegate type for the interface. If it is false, an empty Windows Runtime type.
5443  // _ReturnType : The return type of the async construct (void for actions / non-void for operations)
5444  //
5445  // _TakesProgress : An indication as to whether or not
5446  //
5447  // _Generate_Task : A function adapting the user's function into what's necessary to produce the appropriate task
5448  //
5449  // Optional:
5450  // -------------------------
5451  //
5452 
5453  template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken, bool _TakesProgress>
5454  struct _AsyncAttributes
5455  {
5456  };
5457 
5458  template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
5459  struct _AsyncAttributes<_Function, _ProgressType, _ReturnType, _TaskTraits, _TakesToken, true>
5460  {
5461  typedef typename Windows::Foundation::IAsyncOperationWithProgress<_ReturnType, _ProgressType> _AsyncBaseType;
5462  typedef typename Windows::Foundation::AsyncOperationProgressHandler<_ReturnType, _ProgressType> _ProgressDelegateType;
5463  typedef typename Windows::Foundation::AsyncOperationWithProgressCompletedHandler<_ReturnType, _ProgressType> _CompletionDelegateType;
5464  typedef typename _ReturnType _ReturnType;
5465  typedef typename _ProgressType _ProgressType;
5466  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5467  typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5468  typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
5469 
5470  static const bool _TakesProgress = true;
5471  static const bool _TakesToken = _TakesToken;
5472 
5473  template<typename _Function, typename _ClassPtr>
5474  static task<_ReturnType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5475  {
5476  return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5477  }
5478  };
5479 
5480  template<typename _Function, typename _ProgressType, typename _ReturnType, typename _TaskTraits, bool _TakesToken>
5481  struct _AsyncAttributes<_Function, _ProgressType, _ReturnType, _TaskTraits, _TakesToken, false>
5482  {
5483  typedef typename Windows::Foundation::IAsyncOperation<_ReturnType> _AsyncBaseType;
5484  typedef _Zip _ProgressDelegateType;
5485  typedef typename Windows::Foundation::AsyncOperationCompletedHandler<_ReturnType> _CompletionDelegateType;
5486  typedef typename _ReturnType _ReturnType;
5487  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5488  typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5489  typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
5490 
5491  static const bool _TakesProgress = false;
5492  static const bool _TakesToken = _TakesToken;
5493 
5494  template<typename _Function, typename _ClassPtr>
5495  static task<_ReturnType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5496  {
5497  return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5498  }
5499  };
5500 
5501  template<typename _Function, typename _ProgressType, typename _TaskTraits, bool _TakesToken>
5502  struct _AsyncAttributes<_Function, _ProgressType, void, _TaskTraits, _TakesToken, true>
5503  {
5504  typedef typename Windows::Foundation::IAsyncActionWithProgress<_ProgressType> _AsyncBaseType;
5505  typedef typename Windows::Foundation::AsyncActionProgressHandler<_ProgressType> _ProgressDelegateType;
5506  typedef typename Windows::Foundation::AsyncActionWithProgressCompletedHandler<_ProgressType> _CompletionDelegateType;
5507  typedef void _ReturnType;
5508  typedef typename _ProgressType _ProgressType;
5509  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5510  typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5511  typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, true> _TaskGenerator;
5512 
5513  static const bool _TakesProgress = true;
5514  static const bool _TakesToken = _TakesToken;
5515 
5516  template<typename _Function, typename _ClassPtr>
5517  static task<_ReturnType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5518  {
5519  return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5520  }
5521  };
5522 
5523  template<typename _Function, typename _ProgressType, typename _TaskTraits, bool _TakesToken>
5524  struct _AsyncAttributes<_Function, _ProgressType, void, _TaskTraits, _TakesToken, false>
5525  {
5526  typedef typename Windows::Foundation::IAsyncAction _AsyncBaseType;
5527  typedef _Zip _ProgressDelegateType;
5528  typedef typename Windows::Foundation::AsyncActionCompletedHandler _CompletionDelegateType;
5529  typedef void _ReturnType;
5530  typedef typename _TaskTraits::_AsyncKind _AsyncKind;
5531  typedef typename _SelectorTaskGenerator<_AsyncKind, _ReturnType> _SelectorTaskGenerator;
5532  typedef typename _TaskGenerator<_SelectorTaskGenerator, _TakesToken, false> _TaskGenerator;
5533 
5534  static const bool _TakesProgress = false;
5535  static const bool _TakesToken = _TakesToken;
5536 
5537  template<typename _Function, typename _ClassPtr>
5538  static task<_ReturnType> _Generate_Task(const _Function& _Func, _ClassPtr _Ptr, cancellation_token_source _Cts, const _TaskCreationCallstack & _callstack)
5539  {
5540  return _TaskGenerator::_GenerateTask<_Function, _ClassPtr, _ProgressType>(_Func, _Ptr, _Cts, _callstack);
5541  }
5542  };
5543 
5544  template<typename _Function>
5545  struct _AsyncLambdaTypeTraits
5546  {
5547  typedef typename _FunctorTypeTraits<_Function>::_ReturnType _ReturnType;
5548  typedef typename _FunctorTypeTraits<_Function>::_Argument1Type _Argument1Type;
5549  typedef typename _CAFunctorOptions<_Function>::_ProgressType _ProgressType;
5550 
5551  static const bool _TakesProgress = _CAFunctorOptions<_Function>::_TakesProgress;
5552  static const bool _TakesToken = _CAFunctorOptions<_Function>::_TakesToken;
5553 
5554  typedef typename _TaskTypeTraits<_ReturnType> _TaskTraits;
5555  typedef typename _AsyncAttributes<_Function, _ProgressType, typename _TaskTraits::_TaskRetType, _TaskTraits, _TakesToken, _TakesProgress> _AsyncAttributes;
5556  };
5557 
5558  // ***************************************************************************
5559  // AsyncInfo (and completion) Layer:
5560  //
5561 
5562  //
5563  // Internal base class implementation for async operations (based on internal Windows representation for ABI level async operations)
5564  //
5565  template < typename _Attributes, _AsyncResultType resultType = SingleResult >
5566  ref class _AsyncInfoBase abstract : _Attributes::_AsyncBaseType
5567  {
5568  internal:
5569 
5570  _AsyncInfoBase() :
5571  _M_currentStatus(_AsyncStatusInternal::_AsyncCreated),
5572  _M_errorCode(S_OK),
5573  _M_completeDelegate(nullptr),
5574  _M_CompleteDelegateAssigned(0),
5575  _M_CallbackMade(0)
5576  {
5578  }
5579 
5580  public:
5581  virtual typename _Attributes::_ReturnType GetResults()
5582  {
5583  throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5584  }
5585 
5586  virtual property unsigned int Id
5587  {
5588  unsigned int get()
5589  {
5590  _CheckValidStateForAsyncInfoCall();
5591 
5592  return _M_id;
5593  }
5594 
5595  void set(unsigned int id)
5596  {
5597  _CheckValidStateForAsyncInfoCall();
5598 
5599  if (id == 0)
5600  {
5601  throw ::Platform::Exception::CreateException(E_INVALIDARG);
5602  }
5603  else if (_M_currentStatus != _AsyncStatusInternal::_AsyncCreated)
5604  {
5605  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5606  }
5607 
5608  _M_id = id;
5609  }
5610  }
5611 
5612  virtual property Windows::Foundation::AsyncStatus Status
5613  {
5614  Windows::Foundation::AsyncStatus get()
5615  {
5616  _CheckValidStateForAsyncInfoCall();
5617 
5618  _AsyncStatusInternal _Current = _M_currentStatus;
5619 
5620  //
5621  // Map our internal cancel pending to cancelled. This way "pending cancelled" looks to the outside as "cancelled" but
5622  // can still transition to "completed" if the operation completes without acknowledging the cancellation request
5623  //
5624  switch(_Current)
5625  {
5626  case _AsyncCancelPending:
5627  _Current = _AsyncCanceled;
5628  break;
5629  case _AsyncCreated:
5630  _Current = _AsyncStarted;
5631  break;
5632  default:
5633  break;
5634  }
5635 
5636  return static_cast<Windows::Foundation::AsyncStatus>(_Current);
5637  }
5638  }
5639 
5640  virtual property Windows::Foundation::HResult ErrorCode
5641  {
5642  Windows::Foundation::HResult get()
5643  {
5644  _CheckValidStateForAsyncInfoCall();
5645 
5646  Windows::Foundation::HResult _Hr;
5647  _Hr.Value = _M_errorCode;
5648  return _Hr;
5649  }
5650  }
5651 
5652  virtual property typename _Attributes::_ProgressDelegateType^ Progress
5653  {
5654  typename typename _Attributes::_ProgressDelegateType^ get()
5655  {
5656  return _GetOnProgress();
5657  }
5658 
5659  void set(typename _Attributes::_ProgressDelegateType^ _ProgressHandler)
5660  {
5661  _PutOnProgress(_ProgressHandler);
5662  }
5663  }
5664 
5665  virtual void Cancel()
5666  {
5667  if (_TransitionToState(_AsyncCancelPending))
5668  {
5669  _OnCancel();
5670  }
5671  }
5672 
5673  virtual void Close()
5674  {
5675  if (_TransitionToState(_AsyncClosed))
5676  {
5677  _OnClose();
5678  }
5679  else
5680  {
5681  if (_M_currentStatus != _AsyncClosed) // Closed => Closed transition is just ignored
5682  {
5683  throw ::Platform::Exception::CreateException(E_ILLEGAL_STATE_CHANGE);
5684  }
5685  }
5686  }
5687 
5688  virtual property typename _Attributes::_CompletionDelegateType^ Completed
5689  {
5690  typename _Attributes::_CompletionDelegateType^ get()
5691  {
5692  _CheckValidStateForDelegateCall();
5693  return _M_completeDelegate;
5694  }
5695 
5696  void set(typename _Attributes::_CompletionDelegateType^ _CompleteHandler)
5697  {
5698  _CheckValidStateForDelegateCall();
5699  // this delegate property is "write once"
5700  if (InterlockedIncrement(&_M_CompleteDelegateAssigned) == 1)
5701  {
5702  _M_completeDelegateContext = _ContextCallback::_CaptureCurrent();
5703  _M_completeDelegate = _CompleteHandler;
5704  // Guarantee that the write of _M_completeDelegate is ordered with respect to the read of state below
5705  // as perceived from _FireCompletion on another thread.
5706  MemoryBarrier();
5707  if (_IsTerminalState())
5708  {
5709  _FireCompletion();
5710  }
5711  }
5712  else
5713  {
5714  throw ::Platform::Exception::CreateException(E_ILLEGAL_DELEGATE_ASSIGNMENT);
5715  }
5716  }
5717  }
5718 
5719 
5720  protected private:
5721 
5722  // _Start - this is not externally visible since async operations "hot start" before returning to the caller
5723  void _Start()
5724  {
5725  if (_TransitionToState(_AsyncStarted))
5726  {
5727  _OnStart();
5728  }
5729  else
5730  {
5731  throw ::Platform::Exception::CreateException(E_ILLEGAL_STATE_CHANGE);
5732  }
5733  }
5734 
5735 
5736  void _FireCompletion()
5737  {
5738  _TryTransitionToCompleted();
5739 
5740  // we guarantee that completion can only ever be fired once
5741  if (_M_completeDelegate != nullptr && InterlockedIncrement(&_M_CallbackMade) == 1)
5742  {
5743  _M_completeDelegateContext._CallInContext([=] {
5744  _M_completeDelegate((_Attributes::_AsyncBaseType^)this, this->Status);
5745  _M_completeDelegate = nullptr;
5746  });
5747  }
5748  }
5749 
5750  virtual typename _Attributes::_ProgressDelegateType^ _GetOnProgress()
5751  {
5752  throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5753  }
5754 
5755  virtual void _PutOnProgress(typename _Attributes::_ProgressDelegateType^ _ProgressHandler)
5756  {
5757  throw ::Platform::Exception::CreateException(E_UNEXPECTED);
5758  }
5759 
5760  bool _TryTransitionToCompleted()
5761  {
5762  return _TransitionToState(_AsyncStatusInternal::_AsyncCompleted);
5763  }
5764 
5765  bool _TryTransitionToCancelled()
5766  {
5767  return _TransitionToState(_AsyncStatusInternal::_AsyncCanceled);
5768  }
5769 
5770  bool _TryTransitionToError(const HRESULT error)
5771  {
5772  _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_errorCode), error, S_OK);
5773  return _TransitionToState(_AsyncStatusInternal::_AsyncError);
5774  }
5775 
5776  // This method checks to see if the delegate properties can be
5777  // modified in the current state and generates the appropriate
5778  // error hr in the case of violation.
5779  inline void _CheckValidStateForDelegateCall()
5780  {
5781  if (_M_currentStatus == _AsyncClosed)
5782  {
5783  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5784  }
5785  }
5786 
5787  // This method checks to see if results can be collected in the
5788  // current state and generates the appropriate error hr in
5789  // the case of a violation.
5790  inline void _CheckValidStateForResultsCall()
5791  {
5792  _AsyncStatusInternal _Current = _M_currentStatus;
5793 
5794  if (_Current == _AsyncError)
5795  {
5796  throw ::Platform::Exception::CreateException(_M_errorCode);
5797  }
5798 #pragma warning(push)
5799 #pragma warning(disable: 4127) // Conditional expression is constant
5800  // single result illegal before transition to Completed or Cancelled state
5801  if (resultType == SingleResult)
5802 #pragma warning(pop)
5803  {
5804  if (_Current != _AsyncCompleted)
5805  {
5806  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5807  }
5808  }
5809  // multiple results can be called after Start has been called and before/after Completed
5810  else if (_Current != _AsyncStarted &&
5811  _Current != _AsyncCancelPending &&
5812  _Current != _AsyncCanceled &&
5813  _Current != _AsyncCompleted)
5814  {
5815  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5816  }
5817  }
5818 
5819  // This method can be called by derived classes periodically to determine
5820  // whether the asynchronous operation should continue processing or should
5821  // be halted.
5822  inline bool _ContinueAsyncOperation()
5823  {
5824  return (_M_currentStatus == _AsyncStarted);
5825  }
5826 
5827  // These two methods are used to allow the async worker implementation do work on
5828  // state transitions. No real "work" should be done in these methods. In other words
5829  // they should not block for a long time on UI timescales.
5830  virtual void _OnStart() = 0;
5831  virtual void _OnClose() = 0;
5832  virtual void _OnCancel() = 0;
5833 
5834  private:
5835 
5836  // This method is used to check if calls to the AsyncInfo properties
5837  // (id, status, errorcode) are legal in the current state. It also
5838  // generates the appropriate error hr to return in the case of an
5839  // illegal call.
5840  inline void _CheckValidStateForAsyncInfoCall()
5841  {
5842  _AsyncStatusInternal _Current = _M_currentStatus;
5843  if (_Current == _AsyncClosed)
5844  {
5845  throw ::Platform::Exception::CreateException(E_ILLEGAL_METHOD_CALL);
5846  }
5847  else if (_Current == _AsyncCreated)
5848  {
5849  throw ::Platform::Exception::CreateException(E_ASYNC_OPERATION_NOT_STARTED);
5850  }
5851 
5852  }
5853 
5854  inline bool _TransitionToState(const _AsyncStatusInternal _NewState)
5855  {
5856  _AsyncStatusInternal _Current = _M_currentStatus;
5857 
5858  // This enforces the valid state transitions of the asynchronous worker object
5859  // state machine.
5860  switch(_NewState)
5861  {
5862  case _AsyncStatusInternal::_AsyncStarted:
5863  if (_Current != _AsyncCreated)
5864  {
5865  return false;
5866  }
5867  break;
5868  case _AsyncStatusInternal::_AsyncCompleted:
5869  if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
5870  {
5871  return false;
5872  }
5873  break;
5874  case _AsyncStatusInternal::_AsyncCancelPending:
5875  if (_Current != _AsyncStarted)
5876  {
5877  return false;
5878  }
5879  break;
5880  case _AsyncStatusInternal::_AsyncCanceled:
5881  if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
5882  {
5883  return false;
5884  }
5885  break;
5886  case _AsyncStatusInternal::_AsyncError:
5887  if (_Current != _AsyncStarted && _Current != _AsyncCancelPending)
5888  {
5889  return false;
5890  }
5891  break;
5892  case _AsyncStatusInternal::_AsyncClosed:
5893  if (!_IsTerminalState(_Current))
5894  {
5895  return false;
5896  }
5897  break;
5898  default:
5899  return false;
5900  break;
5901  }
5902 
5903  // attempt the transition to the new state
5904  // Note: if currentStatus_ == _Current, then there was no intervening write
5905  // by the async work object and the swap succeeded.
5906  _AsyncStatusInternal _RetState = static_cast<_AsyncStatusInternal>(
5907  _InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&_M_currentStatus),
5908  _NewState,
5909  static_cast<LONG>(_Current)));
5910 
5911  // ICE returns the former state, if the returned state and the
5912  // state we captured at the beginning of this method are the same,
5913  // the swap succeeded.
5914  return (_RetState == _Current);
5915  }
5916 
5917  inline bool _IsTerminalState()
5918  {
5919  return _IsTerminalState(_M_currentStatus);
5920  }
5921 
5922  inline bool _IsTerminalState(_AsyncStatusInternal status)
5923  {
5924  return (status == _AsyncError ||
5925  status == _AsyncCanceled ||
5926  status == _AsyncCompleted ||
5927  status == _AsyncClosed);
5928  }
5929 
5930  private:
5931 
5932  _ContextCallback _M_completeDelegateContext;
5933  typename _Attributes::_CompletionDelegateType^ volatile _M_completeDelegate;
5934  _AsyncStatusInternal volatile _M_currentStatus;
5935  HRESULT volatile _M_errorCode;
5936  unsigned int _M_id;
5937  long volatile _M_CompleteDelegateAssigned;
5938  long volatile _M_CallbackMade;
5939  };
5940 
5941  // ***************************************************************************
5942  // Progress Layer (optional):
5943  //
5944 
5945  template< typename _Attributes, bool _HasProgress, _AsyncResultType _ResultType = SingleResult >
5946  ref class _AsyncProgressBase abstract : _AsyncInfoBase<_Attributes, _ResultType>
5947  {
5948  };
5949 
5950  template< typename _Attributes, _AsyncResultType _ResultType>
5951  ref class _AsyncProgressBase<_Attributes, true, _ResultType> abstract : _AsyncInfoBase<_Attributes, _ResultType>
5952  {
5953  internal:
5954 
5955  _AsyncProgressBase() : _AsyncInfoBase<_Attributes, _ResultType>(),
5956  _M_progressDelegate(nullptr)
5957  {
5958  }
5959 
5960  virtual typename _Attributes::_ProgressDelegateType^ _GetOnProgress() override
5961  {
5962  _CheckValidStateForDelegateCall();
5963  return _M_progressDelegate;
5964  }
5965 
5966  virtual void _PutOnProgress(typename _Attributes::_ProgressDelegateType^ _ProgressHandler) override
5967  {
5968  _CheckValidStateForDelegateCall();
5969  _M_progressDelegate = _ProgressHandler;
5970  _M_progressDelegateContext = _ContextCallback::_CaptureCurrent();
5971  }
5972 
5973  void _FireProgress(const typename _Attributes::_ProgressType& _ProgressValue)
5974  {
5975  if (_M_progressDelegate != nullptr)
5976  {
5977  _M_progressDelegateContext._CallInContext([=] {
5978  _M_progressDelegate((_Attributes::_AsyncBaseType^)this, _ProgressValue);
5979  });
5980  }
5981  }
5982 
5983  private:
5984 
5985  _ContextCallback _M_progressDelegateContext;
5986  typename _Attributes::_ProgressDelegateType^ _M_progressDelegate;
5987  };
5988 
5989  template<typename _Attributes, _AsyncResultType _ResultType = SingleResult>
5990  ref class _AsyncBaseProgressLayer abstract : _AsyncProgressBase<_Attributes, _Attributes::_TakesProgress, _ResultType>
5991  {
5992  };
5993 
5994  // ***************************************************************************
5995  // Task Adaptation Layer:
5996  //
5997 
5998  //
5999  // _AsyncTaskThunkBase provides a bridge between IAsync<Action/Operation> and task.
6000  //
6001  template<typename _Attributes, typename _ReturnType>
6002  ref class _AsyncTaskThunkBase abstract : _AsyncBaseProgressLayer<_Attributes>
6003  {
6004  public:
6005 
6006  virtual _ReturnType GetResults() override
6007  {
6008  _CheckValidStateForResultsCall();
6009  return _M_task.get();
6010  }
6011 
6012  internal:
6013 
6014  typedef task<_ReturnType> _TaskType;
6015 
6016  _AsyncTaskThunkBase(const _TaskType& _Task)
6017  : _M_task(_Task)
6018  {
6019  }
6020 
6021  _AsyncTaskThunkBase()
6022  {
6023  }
6024 
6025  protected:
6026 
6027  virtual void _OnStart() override
6028  {
6029  _M_task.then( [=](_TaskType _Antecedent) {
6030  try
6031  {
6032  _Antecedent.get();
6033  }
6034  catch(task_canceled&)
6035  {
6036  _TryTransitionToCancelled();
6037  }
6038  catch(::Platform::Exception^ _Ex)
6039  {
6040  _TryTransitionToError(_Ex->HResult);
6041  }
6042  catch(...)
6043  {
6044  _TryTransitionToError(E_FAIL);
6045  }
6046  _FireCompletion();
6047  });
6048  }
6049 
6050  internal:
6051 
6052  _TaskType _M_task;
6053  cancellation_token_source _M_cts;
6054  };
6055 
6056  template<typename _Attributes>
6057  ref class _AsyncTaskThunk : _AsyncTaskThunkBase<_Attributes, typename _Attributes::_ReturnType>
6058  {
6059  internal:
6060 
6061  _AsyncTaskThunk(const _TaskType& _Task) :
6062  _AsyncTaskThunkBase(_Task)
6063  {
6064  }
6065 
6066  _AsyncTaskThunk()
6067  {
6068  }
6069 
6070  protected:
6071 
6072  virtual void _OnClose() override
6073  {
6074  }
6075 
6076  virtual void _OnCancel() override
6077  {
6078  _M_cts.cancel();
6079  }
6080  };
6081 
6082  // ***************************************************************************
6083  // Async Creation Layer:
6084  //
6085  template<typename _Function>
6086  ref class _AsyncTaskGeneratorThunk sealed : _AsyncTaskThunk<typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes>
6087  {
6088  internal:
6089 
6090  typedef typename _AsyncLambdaTypeTraits<_Function>::_AsyncAttributes _Attributes;
6091  typedef typename _AsyncTaskThunk<_Attributes> _Base;
6092  typedef typename _Attributes::_AsyncBaseType _AsyncBaseType;
6093 
6094  _AsyncTaskGeneratorThunk(const _Function& _Func, const _TaskCreationCallstack &_callstack) : _M_func(_Func), _M_creationCallstack(_callstack)
6095  {
6096  // Virtual call here is safe as the class is declared 'sealed'
6097  _Start();
6098  }
6099 
6100  protected:
6101 
6102  //
6103  // The only thing we must do different from the base class is we must spin the hot task on transition from Created->Started. Otherwise,
6104  // let the base thunk handle everything.
6105  //
6106 
6107  virtual void _OnStart() override
6108  {
6109  //
6110  // Call the appropriate task generator to actually produce a task of the expected type. This might adapt the user lambda for progress reports,
6111  // wrap the return result in a task, or allow for direct return of a task depending on the form of the lambda.
6112  //
6113  _M_task = _Attributes::_Generate_Task(_M_func, this, _M_cts, _M_creationCallstack);
6114  _Base::_OnStart();
6115  }
6116 
6117  virtual void _OnCancel() override
6118  {
6119  _Base::_OnCancel();
6120  }
6121 
6122  private:
6123  _TaskCreationCallstack _M_creationCallstack;
6124  _Function _M_func;
6125  };
6126 } // namespace details
6127 
6167 
6168 template<typename _Function>
6169 __declspec(noinline)
6170 details::_AsyncTaskGeneratorThunk<_Function> ^create_async(const _Function& _Func)
6171 {
6172  static_assert(std::is_same<decltype(details::_IsValidCreateAsync(_Func,0,0,0,0)),std::true_type>::value,
6173  "argument to create_async must be a callable object taking zero, one or two arguments");
6174  return ref new details::_AsyncTaskGeneratorThunk<_Function>(_Func, _CAPTURE_CALLSTACK());
6175 }
6176 
6177 #endif /* defined (__cplusplus_winrt) */
6178 
6179 namespace details
6180 {
6181  // Helper struct for when_all operators to know when tasks have completed
6182  template<typename _Type>
6183  struct _RunAllParam
6184  {
6185  _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
6186  {
6187  }
6188 
6189  void _Resize(size_t _Len, bool _SkipVector = false)
6190  {
6191  _M_numTasks = _Len;
6192  if (!_SkipVector)
6193  {
6194  _M_vector._Result.resize(_Len);
6195  }
6196  }
6197 
6198  task_completion_event<_Unit_type> _M_completed;
6199  _ResultHolder<std::vector<_Type> > _M_vector;
6200  _ResultHolder<_Type> _M_mergeVal;
6201  atomic_size_t _M_completeCount;
6202  size_t _M_numTasks;
6203  };
6204 
6205  template<typename _Type>
6206  struct _RunAllParam<std::vector<_Type> >
6207  {
6208  _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
6209  {
6210  }
6211 
6212  void _Resize(size_t _Len, bool _SkipVector = false)
6213  {
6214  _M_numTasks = _Len;
6215 
6216  if (!_SkipVector)
6217  {
6218  _M_vector.resize(_Len);
6219  }
6220  }
6221 
6222  task_completion_event<_Unit_type> _M_completed;
6223  std::vector<_ResultHolder<std::vector<_Type> > > _M_vector;
6224  atomic_size_t _M_completeCount;
6225  size_t _M_numTasks;
6226  };
6227 
6228  // Helper struct specialization for void
6229  template<>
6230  struct _RunAllParam<_Unit_type>
6231  {
6232  _RunAllParam() : _M_completeCount(0), _M_numTasks(0)
6233  {
6234  }
6235 
6236  void _Resize(size_t _Len)
6237  {
6238  _M_numTasks = _Len;
6239  }
6240 
6241  task_completion_event<_Unit_type> _M_completed;
6242  atomic_size_t _M_completeCount;
6243  size_t _M_numTasks;
6244  };
6245 
6246  inline void _JoinAllTokens_Add(const cancellation_token_source& _MergedSrc, _CancellationTokenState *_PJoinedTokenState)
6247  {
6248  if (_PJoinedTokenState != nullptr && _PJoinedTokenState != _CancellationTokenState::_None())
6249  {
6250  cancellation_token _T = cancellation_token::_FromImpl(_PJoinedTokenState);
6251  _T.register_callback( [=](){
6252  _MergedSrc.cancel();
6253  });
6254  }
6255  }
6256 
6257  template<typename _ElementType, typename _Function, typename _TaskType>
6258  void _WhenAllContinuationWrapper(_RunAllParam<_ElementType>* _PParam, _Function _Func, task<_TaskType>& _Task)
6259  {
6260  if (_Task._GetImpl()->_IsCompleted())
6261  {
6262  _Func();
6263  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6264  {
6265  // Inline execute its direct continuation, the _ReturnTask
6266  _PParam->_M_completed.set(_Unit_type());
6267  // It's safe to delete it since all usage of _PParam in _ReturnTask has been finished.
6268  delete _PParam;
6269  }
6270  }
6271  else
6272  {
6273  _ASSERTE(_Task._GetImpl()->_IsCanceled());
6274  if (_Task._GetImpl()->_HasUserException())
6275  {
6276  // _Cancel will return false if the TCE is already canceled with or without exception
6277  _PParam->_M_completed._Cancel(_Task._GetImpl()->_GetExceptionHolder());
6278  }
6279  else
6280  {
6281  _PParam->_M_completed._Cancel();
6282  }
6283 
6284  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6285  {
6286  delete _PParam;
6287  }
6288  }
6289  }
6290 
6291  template<typename _ElementType, typename _Iterator>
6292  struct _WhenAllImpl
6293  {
6294  static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6295  {
6296  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6297 
6298  auto _PParam = new _RunAllParam<_ElementType>();
6299  cancellation_token_source _MergedSource;
6300 
6301  // Step1: Create task completion event.
6302  task_options _Options(_TaskOptions);
6303  _Options.set_cancellation_token(_MergedSource.get_token());
6304  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6305  // The return task must be created before step 3 to enforce inline execution.
6306  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> std::vector<_ElementType> {
6307  return _PParam->_M_vector.Get();
6308  }, nullptr);
6309 
6310  // Step2: Combine and check tokens, and count elements in range.
6311  if (_PTokenState)
6312  {
6313  _JoinAllTokens_Add(_MergedSource, _PTokenState);
6314  _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6315  }
6316  else
6317  {
6318  size_t _TaskNum = 0;
6319  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6320  {
6321  _TaskNum++;
6322  _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6323  }
6324  _PParam->_Resize(_TaskNum);
6325  }
6326 
6327  // Step3: Check states of previous tasks.
6328  if( _Begin == _End )
6329  {
6330  _PParam->_M_completed.set(_Unit_type());
6331  delete _PParam;
6332  }
6333  else
6334  {
6335  size_t _Index = 0;
6336  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6337  {
6338  if (_PTask->is_apartment_aware())
6339  {
6340  _ReturnTask._SetAsync();
6341  }
6342 
6343  _PTask->_Then([_PParam, _Index](task<_ElementType> _ResultTask) {
6344 
6345  // Dev10 compiler bug
6346  typedef _ElementType _ElementTypeDev10;
6347  auto _PParamCopy = _PParam;
6348  auto _IndexCopy = _Index;
6349  auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask](){
6350  _PParamCopy->_M_vector._Result[_IndexCopy] = _ResultTask._GetImpl()->_GetResult();
6351  };
6352 
6353  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6355 
6356  _Index++;
6357  }
6358  }
6359 
6360  return _ReturnTask;
6361  }
6362  };
6363 
6364  template<typename _ElementType, typename _Iterator>
6365  struct _WhenAllImpl<std::vector<_ElementType>, _Iterator>
6366  {
6367  static task<std::vector<_ElementType>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6368  {
6369  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6370 
6371  auto _PParam = new _RunAllParam<std::vector<_ElementType>>();
6372  cancellation_token_source _MergedSource;
6373 
6374  // Step1: Create task completion event.
6375  task_options _Options(_TaskOptions);
6376  _Options.set_cancellation_token(_MergedSource.get_token());
6377  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6378  // The return task must be created before step 3 to enforce inline execution.
6379  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> std::vector<_ElementType> {
6380  _ASSERTE(_PParam->_M_completeCount == _PParam->_M_numTasks);
6381  std::vector<_ElementType> _Result;
6382  for(size_t _I = 0; _I < _PParam->_M_numTasks; _I++)
6383  {
6384  const std::vector<_ElementType>& _Vec = _PParam->_M_vector[_I].Get();
6385  _Result.insert(_Result.end(), _Vec.begin(), _Vec.end());
6386  }
6387  return _Result;
6388  }, nullptr);
6389 
6390  // Step2: Combine and check tokens, and count elements in range.
6391  if (_PTokenState)
6392  {
6393  _JoinAllTokens_Add(_MergedSource, _PTokenState);
6394  _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6395  }
6396  else
6397  {
6398  size_t _TaskNum = 0;
6399  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6400  {
6401  _TaskNum++;
6402  _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6403  }
6404  _PParam->_Resize(_TaskNum);
6405  }
6406 
6407  // Step3: Check states of previous tasks.
6408  if( _Begin == _End )
6409  {
6410  _PParam->_M_completed.set(_Unit_type());
6411  delete _PParam;
6412  }
6413  else
6414  {
6415  size_t _Index = 0;
6416  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6417  {
6418  if (_PTask->is_apartment_aware())
6419  {
6420  _ReturnTask._SetAsync();
6421  }
6422 
6423  _PTask->_Then([_PParam, _Index](task<std::vector<_ElementType>> _ResultTask) {
6424  // Dev10 compiler bug
6425  typedef _ElementType _ElementTypeDev10;
6426  auto _PParamCopy = _PParam;
6427  auto _IndexCopy = _Index;
6428  auto _Func = [_PParamCopy, _IndexCopy, &_ResultTask]() {
6429  _PParamCopy->_M_vector[_IndexCopy].Set(_ResultTask._GetImpl()->_GetResult());
6430  };
6431 
6432  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6434 
6435  _Index++;
6436  }
6437  }
6438 
6439  return _ReturnTask;
6440  }
6441  };
6442 
6443  template<typename _Iterator>
6444  struct _WhenAllImpl<void, _Iterator>
6445  {
6446  static task<void> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6447  {
6448  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6449 
6450  auto _PParam = new _RunAllParam<_Unit_type>();
6451  cancellation_token_source _MergedSource;
6452 
6453  // Step1: Create task completion event.
6454  task_options _Options(_TaskOptions);
6455  _Options.set_cancellation_token(_MergedSource.get_token());
6456  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _Options);
6457  // The return task must be created before step 3 to enforce inline execution.
6458  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) {
6459  }, nullptr);
6460 
6461  // Step2: Combine and check tokens, and count elements in range.
6462  if (_PTokenState)
6463  {
6464  _JoinAllTokens_Add(_MergedSource, _PTokenState);
6465  _PParam->_Resize(static_cast<size_t>(std::distance(_Begin, _End)));
6466  }
6467  else
6468  {
6469  size_t _TaskNum = 0;
6470  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6471  {
6472  _TaskNum++;
6473  _JoinAllTokens_Add(_MergedSource, _PTask->_GetImpl()->_M_pTokenState);
6474  }
6475  _PParam->_Resize(_TaskNum);
6476  }
6477 
6478  // Step3: Check states of previous tasks.
6479  if( _Begin == _End )
6480  {
6481  _PParam->_M_completed.set(_Unit_type());
6482  delete _PParam;
6483  }
6484  else
6485  {
6486  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6487  {
6488  if (_PTask->is_apartment_aware())
6489  {
6490  _ReturnTask._SetAsync();
6491  }
6492 
6493  _PTask->_Then([_PParam](task<void> _ResultTask) {
6494  auto _Func = [](){};
6495  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6497  }
6498  }
6499 
6500  return _ReturnTask;
6501  }
6502  };
6503 
6504  template<typename _ReturnType>
6505  task<std::vector<_ReturnType>> _WhenAllVectorAndValue(const task<std::vector<_ReturnType>>& _VectorTask, const task<_ReturnType>& _ValueTask,
6506  bool _OutputVectorFirst)
6507  {
6508  auto _PParam = new _RunAllParam<_ReturnType>();
6509  cancellation_token_source _MergedSource;
6510 
6511  // Step1: Create task completion event.
6512  task<_Unit_type> _All_tasks_completed(_PParam->_M_completed, _MergedSource.get_token());
6513  // The return task must be created before step 3 to enforce inline execution.
6514  auto _ReturnTask = _All_tasks_completed._Then([=](_Unit_type) -> std::vector<_ReturnType> {
6515  _ASSERTE(_PParam->_M_completeCount == 2);
6516  auto _Result = _PParam->_M_vector.Get(); // copy by value
6517  auto _mergeVal = _PParam->_M_mergeVal.Get();
6518 
6519  if (_OutputVectorFirst == true)
6520  {
6521  _Result.push_back(_mergeVal);
6522  }
6523  else
6524  {
6525  _Result.insert(_Result.begin(), _mergeVal);
6526  }
6527  return _Result;
6528  }, nullptr);
6529 
6530  // Step2: Combine and check tokens.
6531  _JoinAllTokens_Add(_MergedSource, _VectorTask._GetImpl()->_M_pTokenState);
6532  _JoinAllTokens_Add(_MergedSource, _ValueTask._GetImpl()->_M_pTokenState);
6533 
6534  // Step3: Check states of previous tasks.
6535  _PParam->_Resize(2, true);
6536 
6537  if (_VectorTask.is_apartment_aware() || _ValueTask.is_apartment_aware())
6538  {
6539  _ReturnTask._SetAsync();
6540  }
6541  _VectorTask._Then([_PParam](task<std::vector<_ReturnType>> _ResultTask) {
6542  // Dev10 compiler bug
6543  typedef _ReturnType _ReturnTypeDev10;
6544  auto _PParamCopy = _PParam;
6545  auto _Func = [_PParamCopy, &_ResultTask]() {
6546  auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
6547  _PParamCopy->_M_vector.Set(_ResultLocal);
6548  };
6549 
6550  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6552  _ValueTask._Then([_PParam](task<_ReturnType> _ResultTask) {
6553  // Dev10 compiler bug
6554  typedef _ReturnType _ReturnTypeDev10;
6555  auto _PParamCopy = _PParam;
6556  auto _Func = [_PParamCopy, &_ResultTask]() {
6557  auto _ResultLocal = _ResultTask._GetImpl()->_GetResult();
6558  _PParamCopy->_M_mergeVal.Set(_ResultLocal);
6559  };
6560 
6561  _WhenAllContinuationWrapper(_PParam, _Func, _ResultTask);
6563 
6564  return _ReturnTask;
6565  }
6566 } // namespace details
6567 
6590 
6591 template <typename _Iterator>
6592 auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
6593  -> decltype (details::_WhenAllImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End))
6594 {
6595  typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
6596  return details::_WhenAllImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
6597 }
6598 
6623 
6624 template<typename _ReturnType>
6625 task<std::vector<_ReturnType>> operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs)
6626 {
6627  task<_ReturnType> _PTasks[2] = {_Lhs, _Rhs};
6628  return when_all(_PTasks, _PTasks+2);
6629 }
6630 
6655 
6656 template<typename _ReturnType>
6657 task<std::vector<_ReturnType>> operator&&(const task<std::vector<_ReturnType>> & _Lhs, const task<_ReturnType> & _Rhs)
6658 {
6659  return details::_WhenAllVectorAndValue(_Lhs, _Rhs, true);
6660 }
6661 
6686 
6687 template<typename _ReturnType>
6688 task<std::vector<_ReturnType>> operator&&(const task<_ReturnType> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
6689 {
6690  return details::_WhenAllVectorAndValue(_Rhs, _Lhs, false);
6691 }
6692 
6717 
6718 template<typename _ReturnType>
6719 task<std::vector<_ReturnType>> operator&&(const task<std::vector<_ReturnType>> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
6720 {
6721  task<std::vector<_ReturnType>> _PTasks[2] = {_Lhs, _Rhs};
6722  return when_all(_PTasks, _PTasks+2);
6723 }
6724 
6749 
6750 inline task<void> operator&&(const task<void> & _Lhs, const task<void> & _Rhs)
6751 {
6752  task<void> _PTasks[2] = {_Lhs, _Rhs};
6753  return when_all(_PTasks, _PTasks+2);
6754 }
6755 
6756 namespace details
6757 {
6758  // Helper struct for when_any operators to know when tasks have completed
6759  template <typename _CompletionType>
6760  struct _RunAnyParam
6761  {
6762  _RunAnyParam() : _M_exceptionRelatedToken(nullptr), _M_completeCount(0), _M_numTasks(0), _M_fHasExplicitToken(false)
6763  {
6764  }
6765  ~_RunAnyParam()
6766  {
6767  if (_CancellationTokenState::_IsValid(_M_exceptionRelatedToken))
6768  _M_exceptionRelatedToken->_Release();
6769  }
6770  task_completion_event<_CompletionType> _M_Completed;
6771  cancellation_token_source _M_cancellationSource;
6772  _CancellationTokenState * _M_exceptionRelatedToken;
6773  atomic_size_t _M_completeCount;
6774  size_t _M_numTasks;
6775  bool _M_fHasExplicitToken;
6776  };
6777 
6778  template<typename _CompletionType, typename _Function, typename _TaskType>
6779  void _WhenAnyContinuationWrapper(_RunAnyParam<_CompletionType> * _PParam, const _Function & _Func, task<_TaskType>& _Task)
6780  {
6781  bool _IsTokenCancled = !_PParam->_M_fHasExplicitToken && _Task._GetImpl()->_M_pTokenState != _CancellationTokenState::_None() && _Task._GetImpl()->_M_pTokenState->_IsCanceled();
6782  if (_Task._GetImpl()->_IsCompleted() && !_IsTokenCancled)
6783  {
6784  _Func();
6785  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6786  {
6787  delete _PParam;
6788  }
6789  }
6790  else
6791  {
6792  _ASSERTE(_Task._GetImpl()->_IsCanceled() || _IsTokenCancled);
6793  if (_Task._GetImpl()->_HasUserException() && !_IsTokenCancled)
6794  {
6795  if (_PParam->_M_Completed._StoreException(_Task._GetImpl()->_GetExceptionHolder()))
6796  {
6797  // This can only enter once.
6798  _PParam->_M_exceptionRelatedToken = _Task._GetImpl()->_M_pTokenState;
6799  _ASSERTE(_PParam->_M_exceptionRelatedToken);
6800  // Deref token will be done in the _PParam destructor.
6801  if (_PParam->_M_exceptionRelatedToken != _CancellationTokenState::_None())
6802  {
6803  _PParam->_M_exceptionRelatedToken->_Reference();
6804  }
6805  }
6806  }
6807 
6808  if (atomic_increment(_PParam->_M_completeCount) == _PParam->_M_numTasks)
6809  {
6810  // If no one has be completed so far, we need to make some final cancellation decision.
6811  if (!_PParam->_M_Completed._IsTriggered())
6812  {
6813  // If we already explicit token, we can skip the token join part.
6814  if (!_PParam->_M_fHasExplicitToken)
6815  {
6816  if (_PParam->_M_exceptionRelatedToken)
6817  {
6818  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PParam->_M_exceptionRelatedToken);
6819  }
6820  else
6821  {
6822  // If haven't captured any exception token yet, there was no exception for all those tasks,
6823  // so just pick a random token (current one) for normal cancellation.
6824  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _Task._GetImpl()->_M_pTokenState);
6825  }
6826  }
6827  // Do exception cancellation or normal cancellation based on whether it has stored exception.
6828  _PParam->_M_Completed._Cancel();
6829  }
6830  delete _PParam;
6831  }
6832  }
6833  }
6834 
6835  template<typename _ElementType, typename _Iterator>
6836  struct _WhenAnyImpl
6837  {
6838  static task<std::pair<_ElementType, size_t>> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6839  {
6840  if( _Begin == _End )
6841  {
6842  throw invalid_operation("when_any(begin, end) cannot be called on an empty container.");
6843  }
6844  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6845  auto _PParam = new _RunAnyParam<std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState *>>();
6846 
6847  if (_PTokenState)
6848  {
6849  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
6850  _PParam->_M_fHasExplicitToken = true;
6851  }
6852 
6853  task_options _Options(_TaskOptions);
6854  _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
6855  task<std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
6856 
6857  // Keep a copy ref to the token source
6858  auto _CancellationSource = _PParam->_M_cancellationSource;
6859 
6860  _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
6861  size_t _Index = 0;
6862  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6863  {
6864  if (_PTask->is_apartment_aware())
6865  {
6866  _Any_tasks_completed._SetAsync();
6867  }
6868 
6869  _PTask->_Then([_PParam, _Index](task<_ElementType> _ResultTask) {
6870  auto _PParamCopy = _PParam; // Dev10
6871  auto _IndexCopy = _Index; // Dev10
6872  auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
6873  _PParamCopy->_M_Completed.set(std::make_pair(std::make_pair(_ResultTask._GetImpl()->_GetResult(), _IndexCopy), _ResultTask._GetImpl()->_M_pTokenState));
6874  };
6875 
6876  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6878 
6879  _Index++;
6880  }
6881 
6882  // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
6883  return _Any_tasks_completed._Then([=](std::pair<std::pair<_ElementType, size_t>, _CancellationTokenState *> _Result) -> std::pair<_ElementType, size_t> {
6884  _ASSERTE(_Result.second);
6885  if (!_PTokenState)
6886  {
6887  _JoinAllTokens_Add(_CancellationSource, _Result.second);
6888  }
6889  return _Result.first;
6890  }, nullptr);
6891  }
6892  };
6893 
6894  template<typename _Iterator>
6895  struct _WhenAnyImpl<void, _Iterator>
6896  {
6897  static task<size_t> _Perform(const task_options& _TaskOptions, _Iterator _Begin, _Iterator _End)
6898  {
6899  if( _Begin == _End )
6900  {
6901  throw invalid_operation("when_any(begin, end) cannot be called on an empty container.");
6902  }
6903 
6904  _CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
6905  auto _PParam = new _RunAnyParam<std::pair<size_t, _CancellationTokenState *>>();
6906 
6907  if (_PTokenState)
6908  {
6909  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _PTokenState);
6910  _PParam->_M_fHasExplicitToken = true;
6911  }
6912 
6913  task_options _Options(_TaskOptions);
6914  _Options.set_cancellation_token(_PParam->_M_cancellationSource.get_token());
6915  task<std::pair<size_t, _CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _Options);
6916 
6917  // Keep a copy ref to the token source
6918  auto _CancellationSource = _PParam->_M_cancellationSource;
6919 
6920  _PParam->_M_numTasks = static_cast<size_t>(std::distance(_Begin, _End));
6921  size_t _Index = 0;
6922  for (auto _PTask = _Begin; _PTask != _End; ++_PTask)
6923  {
6924  if (_PTask->is_apartment_aware())
6925  {
6926  _Any_tasks_completed._SetAsync();
6927  }
6928 
6929  _PTask->_Then([_PParam, _Index](task<void> _ResultTask) {
6930  auto _PParamCopy = _PParam; // Dev10
6931  auto _IndexCopy = _Index; // Dev10
6932  auto _Func = [&_ResultTask, _PParamCopy, _IndexCopy]() {
6933  _PParamCopy->_M_Completed.set(std::make_pair(_IndexCopy, _ResultTask._GetImpl()->_M_pTokenState));
6934  };
6935  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
6937 
6938  _Index++;
6939  }
6940 
6941  // All _Any_tasks_completed._SetAsync() must be finished before this return continuation task being created.
6942  return _Any_tasks_completed._Then([=](std::pair<size_t, _CancellationTokenState *> _Result) -> size_t {
6943  _ASSERTE(_Result.second);
6944  if (!_PTokenState)
6945  {
6946  _JoinAllTokens_Add(_CancellationSource, _Result.second);
6947  }
6948  return _Result.first;
6949  }, nullptr);
6950  }
6951  };
6952 } // namespace details
6953 
6973 
6974 template<typename _Iterator>
6975 auto when_any(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions = task_options())
6976  -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_TaskOptions, _Begin, _End))
6977 {
6978  typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
6979  return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_TaskOptions, _Begin, _End);
6980 }
6981 
7005 
7006 template<typename _Iterator>
7007 auto when_any(_Iterator _Begin, _Iterator _End, cancellation_token _CancellationToken)
7008  -> decltype (details::_WhenAnyImpl<typename std::iterator_traits<_Iterator>::value_type::result_type, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End))
7009 {
7010  typedef typename std::iterator_traits<_Iterator>::value_type::result_type _ElementType;
7011  return details::_WhenAnyImpl<_ElementType, _Iterator>::_Perform(_CancellationToken._GetImplValue(), _Begin, _End);
7012 }
7013 
7039 
7040 template<typename _ReturnType>
7041 task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs)
7042 {
7043  auto _PParam = new details::_RunAnyParam<std::pair<_ReturnType, size_t>>();
7044 
7045  task<std::pair<_ReturnType, size_t>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
7046  // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7047  // So that _PParam can be used before it getting deleted.
7048  auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<_ReturnType, size_t> _Ret) -> _ReturnType {
7049  _ASSERTE(_Ret.second);
7050  _JoinAllTokens_Add(_PParam->_M_cancellationSource, reinterpret_cast<details::_CancellationTokenState *>(_Ret.second));
7051  return _Ret.first;
7052  }, nullptr);
7053 
7054  if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7055  {
7056  _ReturnTask._SetAsync();
7057  }
7058 
7059  _PParam->_M_numTasks = 2;
7060  auto _Continuation = [_PParam](task<_ReturnType> _ResultTask) {
7061  // Dev10 compiler bug
7062  auto _PParamCopy = _PParam;
7063  auto _Func = [&_ResultTask, _PParamCopy]() {
7064  _PParamCopy->_M_Completed.set(std::make_pair(_ResultTask._GetImpl()->_GetResult(), reinterpret_cast<size_t>(_ResultTask._GetImpl()->_M_pTokenState)));
7065  };
7066  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7067  };
7068 
7069  _Lhs._Then(_Continuation, details::_CancellationTokenState::_None());
7070  _Rhs._Then(_Continuation, details::_CancellationTokenState::_None());
7071 
7072  return _ReturnTask;
7073 }
7074 
7100 
7101 template<typename _ReturnType>
7102 task<std::vector<_ReturnType>> operator||(const task<std::vector<_ReturnType>> & _Lhs, const task<_ReturnType> & _Rhs)
7103 {
7104  auto _PParam = new details::_RunAnyParam<std::pair<std::vector<_ReturnType>, details::_CancellationTokenState *>>();
7105 
7106  task<std::pair<std::vector<_ReturnType>, details::_CancellationTokenState *>> _Any_tasks_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
7107 
7108  // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7109  // So that _PParam can be used before it getting deleted.
7110  auto _ReturnTask = _Any_tasks_completed._Then([=](std::pair<std::vector<_ReturnType>, details::_CancellationTokenState *> _Ret) -> std::vector<_ReturnType> {
7111  _ASSERTE(_Ret.second);
7112  _JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
7113  return _Ret.first;
7114  }, nullptr);
7115 
7116  if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7117  {
7118  _ReturnTask._SetAsync();
7119  }
7120 
7121  _PParam->_M_numTasks = 2;
7122  _Lhs._Then([_PParam](task<std::vector<_ReturnType>> _ResultTask) {
7123  // Dev10 compiler bug
7124  auto _PParamCopy = _PParam;
7125  auto _Func = [&_ResultTask, _PParamCopy]() {
7126  auto _Result = _ResultTask._GetImpl()->_GetResult();
7127  _PParamCopy->_M_Completed.set(std::make_pair(_Result, _ResultTask._GetImpl()->_M_pTokenState));
7128  };
7129  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7131 
7132 
7133  _Rhs._Then([_PParam](task<_ReturnType> _ResultTask)
7134  {
7135  // Dev10 compiler bug
7136  typedef _ReturnType _ReturnTypeDev10;
7137  auto _PParamCopy = _PParam;
7138  auto _Func = [&_ResultTask, _PParamCopy]() {
7139  auto _Result = _ResultTask._GetImpl()->_GetResult();
7140 
7141  std::vector<_ReturnTypeDev10> _Vec;
7142  _Vec.push_back(_Result);
7143  _PParamCopy->_M_Completed.set(std::make_pair(_Vec, _ResultTask._GetImpl()->_M_pTokenState));
7144  };
7145  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7147 
7148  return _ReturnTask;
7149 }
7150 
7176 
7177 template<typename _ReturnType>
7178 task<std::vector<_ReturnType>> operator||(const task<_ReturnType> & _Lhs, const task<std::vector<_ReturnType>> & _Rhs)
7179 {
7180  return _Rhs || _Lhs;
7181 }
7182 
7208 
7209 inline task<void> operator||(const task<void> & _Lhs, const task<void> & _Rhs)
7210 {
7211  auto _PParam = new details::_RunAnyParam<std::pair<details::_Unit_type, details::_CancellationTokenState *>>();
7212 
7213  task<std::pair<details::_Unit_type, details::_CancellationTokenState *>> _Any_task_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token());
7214  // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called,
7215  // So that _PParam can be used before it getting deleted.
7216  auto _ReturnTask = _Any_task_completed._Then([=](std::pair<details::_Unit_type, details::_CancellationTokenState *> _Ret) {
7217  _ASSERTE(_Ret.second);
7218  details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second);
7219  }, nullptr);
7220 
7221  if (_Lhs.is_apartment_aware() || _Rhs.is_apartment_aware())
7222  {
7223  _ReturnTask._SetAsync();
7224  }
7225 
7226  _PParam->_M_numTasks = 2;
7227  auto _Continuation = [_PParam](task<void> _ResultTask) mutable {
7228  // Dev10 compiler needs this.
7229  auto _PParam1 = _PParam;
7230  auto _Func = [&_ResultTask, _PParam1]() {
7231  _PParam1->_M_Completed.set(std::make_pair(details::_Unit_type(), _ResultTask._GetImpl()->_M_pTokenState));
7232  };
7233  _WhenAnyContinuationWrapper(_PParam, _Func, _ResultTask);
7234  };
7235 
7236  _Lhs._Then(_Continuation, details::_CancellationTokenState::_None());
7237  _Rhs._Then(_Continuation, details::_CancellationTokenState::_None());
7238 
7239  return _ReturnTask;
7240 }
7241 
7242 template<typename _Ty>
7243 task<_Ty> task_from_result(_Ty _Param, const task_options& _TaskOptions = task_options())
7244 {
7245  task_completion_event<_Ty> _Tce;
7246  _Tce.set(_Param);
7247  return create_task(_Tce, _TaskOptions);
7248 }
7249 
7250 // Work around VS 2010 compiler bug
7251 #if _MSC_VER == 1600
7252 inline task<bool> task_from_result(bool _Param)
7253 {
7254  task_completion_event<bool> _Tce;
7255  _Tce.set(_Param);
7256  return create_task(_Tce, task_options());
7257 }
7258 #endif
7259 inline task<void> task_from_result(const task_options& _TaskOptions = task_options())
7260 {
7261  task_completion_event<void> _Tce;
7262  _Tce.set();
7263  return create_task(_Tce, _TaskOptions);
7264 }
7265 
7266 template<typename _TaskType, typename _ExType>
7267 task<_TaskType> task_from_exception(_ExType _Exception, const task_options& _TaskOptions = task_options())
7268 {
7269  task_completion_event<_TaskType> _Tce;
7270  _Tce.set_exception(_Exception);
7271  return create_task(_Tce, _TaskOptions);
7272 }
7273 
7274 namespace details
7275 {
7283  inline
7284  task<bool> do_while(std::function<task<bool>(void)> func)
7285  {
7286  task<bool> first = func();
7287  return first.then([=](bool guard) -> task<bool> {
7288  if (guard)
7289  return do_while(func);
7290  else
7291  return first;
7292  });
7293  }
7294 
7295 } // namespace details
7296 
7297 } // namespace Concurrency
7298 
7299 #pragma pop_macro("new")
7300 #pragma warning(pop)
7301 #pragma pack(pop)
7302 
7303 #endif // _PPLTASKS_H
_InitialTaskHandle(const typename details::_Task_ptr< _ReturnType >::_Type &_TaskImpl, const _Function &_func)
Definition: ppltasks.h:3653
void _LogWorkItemStarted()
Definition: ppltasks.h:1549
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2291
void _set_creation_callstack(const _TaskCreationCallstack &_callstack)
Definition: ppltasks.h:1178
void _RethrowUserException()
Definition: ppltasks.h:918
virtual ~_PPLTaskHandle()
Definition: ppltasks.h:1584
std::function< _Unit_type(void)> _MakeVoidToUnitFunc(const std::function< void(void)> &_Func)
Definition: ppltasks.h:2582
bool _IsCompleted()
Definition: ppltasks.h:1879
static auto _Perform(std::function< _RetType(void)> _Func) -> decltype(_Func)
Definition: ppltasks.h:3096
static _TaskCreationCallstack _CaptureSingleFrameCallstack(void *_SingleFrame)
Definition: ppltasks.h:229
_TaskCreationCallstack _M_presetCreationCallstack
Definition: ppltasks.h:1176
scheduler_ptr _M_Scheduler
Definition: ppltasks.h:1360
Definition: concrt.h:378
void _TaskInitMaybeFunctor(_Function &_Func, std::true_type)
Initializes a task using a callable object.
Definition: ppltasks.h:4549
static auto _Perform(std::function< _OutType(void)> _Func) -> decltype(details::_MakeUnitToTFunc< _OutType >(_Func))
Definition: ppltasks.h:3064
_T atomic_exchange(std::atomic< _T > &_Target, _T _Value)
Definition: pplinterface.h:154
void _LogScheduleTask(bool)
Definition: ppltasks.h:1547
void _Continue(std::false_type, details::_TypeSelectorNoAsync) const
Definition: ppltasks.h:3804
void _SyncCancelAndPropagateException() const
Definition: ppltasks.h:3783
task_options()
Default list of task creation options
Definition: ppltasks.h:1203
bool _M_HasScheduler
Definition: ppltasks.h:1365
std::function< _Unit_type(_Unit_type)> _MakeUnitToUnitFunc(const std::function< void(void)> &_Func)
Definition: ppltasks.h:2599
This class describes an exception thrown when an invalid operation is performed that is not more accu...
Definition: concrt.h:1705
void _LogTaskExecutionCompleted()
Definition: ppltasks.h:1552
_ContextCallback & operator=(_ContextCallback &&)
Definition: ppltasks.h:756
_CRTIMP _In_ int _Value
Definition: setjmp.h:190
bool _HasUserException()
Definition: ppltasks.h:1889
_ContextCallback(_ContextCallback &&)
Definition: ppltasks.h:747
_ContextCallback(bool=false)
Definition: ppltasks.h:739
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:4505
exception_ptr current_exception()
Definition: exception:527
_T && declval()
std::shared_ptr< _Task_impl_base > _Task_ptr_base
Definition: ppltasks.h:1390
_Holder(_TaskProcThunk *_PThunk)
Definition: ppltasks.h:503
#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:3623
future< typename result_of< _Fty(_ArgTypes...)>::type > _Async(_Launch_type _Policy, _Fty &&_Fnarg, _ArgTypes &&..._Args)
Definition: future:1874
std::function< _Type(_Unit_type)> _MakeUnitToTFunc(const std::function< _Type(void)> &_Func)
Definition: ppltasks.h:2588
_ContinuationList _M_Continuations
Definition: ppltasks.h:2296
details::_Task_ptr< _ReturnType >::_Type _M_ancestorTaskImpl
Definition: ppltasks.h:3751
void _Perform() const
Definition: ppltasks.h:3668
auto _IsCallable(_Function _Func, int) -> decltype(_Func(), std::true_type())
Definition: ppltasks.h:395
std::vector< void * > _M_frames
Definition: ppltasks.h:221
_TaskCreationCallstack _M_stackTrace
Definition: ppltasks.h:948
scheduler_ptr _GetScheduler() const
Definition: ppltasks.h:2275
void __cdecl ReportUnhandledError(::Platform::Exception^)
~_Task_completion_event_impl()
Definition: ppltasks.h:2562
bool operator==(const _Concurrent_queue_iterator< _C, _Ty > &_I, const _Concurrent_queue_iterator< _C, _U > &_J)
Definition: concurrent_queue.h:317
Definition: concrt.h:4426
Definition: concrt.h:5277
void _LogTaskExecutionStarted()
Definition: ppltasks.h:1551
_Task_ptr_base _GetTaskImplBase() const
Definition: ppltasks.h:1630
void _RunContinuation(_ContinuationTaskHandleBase *_PTaskHandle)
Function executes a continuation. This function is recorded by a parent task implementation when a co...
Definition: ppltasks.h:1964
details::_NormalizeVoidToUnitType< _ContinuationReturnType >::_Type _NormalizedContinuationReturnType
Definition: ppltasks.h:3749
task_options(cancellation_token _Token)
Task option that specify a cancellation token
Definition: ppltasks.h:1215
_ContextCallback & operator=(const _ContextCallback &)
Definition: ppltasks.h:751
_PPLTaskHandle(const typename _Task_ptr< _ReturnType >::_Type &_PTask)
Definition: ppltasks.h:1580
static cancellation_token none()
Returns a cancellation token which can never be subject to cancellation.
Definition: pplcancellation_token.h:628
_ContinuationTaskHandleBase * _M_next
Definition: ppltasks.h:1395
auto _FilterValidTaskType(_Ty _Param, int) -> decltype(_GetTaskType(_Param, _IsCallable(_Param, 0)))
bool _IsCanceled()
Definition: ppltasks.h:1884
task(const task &_Other)
Constructs a task object.
Definition: ppltasks.h:3285
This class describes an exception thrown by the PPL tasks layer in order to force the current task to...
Definition: concrt.h:1879
void _Resolve(bool) const
Definition: ppltasks.h:766
static auto _Perform(std::function< void(_InType)> _Func) -> decltype(details::_MakeTToUnitFunc< _InType >(_Func))
Definition: ppltasks.h:3074
task< details::_Unit_type > _M_unitTask
Definition: ppltasks.h:4564
::Concurrency::details::_Task_generator_oversubscriber _Task_generator_oversubscriber_t
Definition: pplconcrt.h:287
The task_completion_event class allows you to delay the execution of a task until a condition is sati...
Definition: ppltasks.h:2623
auto _ThenImpl(const _Function &_Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context &_ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack, details::_TaskInliningMode_t _InliningMode=details::_NoInline) const -> typename details::_ContinuationTypeTraits< _Function, _InternalReturnType >::_TaskOfType
The one and only implementation of then for void and non-void tasks.
Definition: ppltasks.h:4062
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:4496
Definition: exception:427
Definition: concrt.h:4427
_Unit_type _Type
Definition: ppltasks.h:266
::Concurrency::details::_TaskCollection_t _M_TaskCollection
Definition: ppltasks.h:2305
task_completion_event()
Constructs a task_completion_event object.
Definition: ppltasks.h:2630
bool _M_fHasValue
Definition: ppltasks.h:2577
_Task_ptr< _ReturnType >::_Type _M_pTask
Definition: ppltasks.h:1635
__declspec(noinline) bool set_exception(std
Propagates an exception to all tasks associated with this event.
Definition: ppltasks.h:2714
_ContextCallback(const _ContextCallback &)
Definition: ppltasks.h:743
task< typename _TaskTypeTraits< typename _FunctionTypeTraits< _Function, _ReturnType >::_FuncRetType >::_TaskRetType > _TaskOfType
Definition: ppltasks.h:448
_In_ intptr_t _In_ int _Action
Definition: process.h:202
static const bool _Value
Definition: ppltasks.h:272
_OutIt move(_InIt _First, _InIt _Last, _OutIt _Dest)
Definition: xutility:2447
file_status status(const _Path &_Pval)
Definition: filesystem:1604
void _Init(details::_TypeSelectorNoAsync) const
Definition: ppltasks.h:3683
__declspec(noinline) explicit task(_Ty _Param)
Constructs a task object.
Definition: ppltasks.h:3200
cancellation_token _M_CancellationToken
Definition: ppltasks.h:1361
Definition: agile.h:114
_Internal_task_options & _get_internal_task_options(task_options &options)
Definition: ppltasks.h:1370
typedef void(__cdecl *_se_translator_function)(unsigned int
void reserve(size_type _Count)
Definition: vector:998
_Function _M_function
Definition: ppltasks.h:3652
STL namespace.
Definition: ppltasks.h:789
void _SetImpl(typename details::_Task_ptr< _ReturnType >::_Type &&_Impl)
Set the implementation of the task to be the supplied implementaion using a move instead of a copy...
Definition: ppltasks.h:3606
bool operator==(const task< void > &_Rhs) const
Determines whether two task objects represent the same internal task.
Definition: ppltasks.h:4436
std::vector< typename _Task_ptr< _ResultType >::_Type > _TaskList
Definition: ppltasks.h:2550
void _Perform() const
Definition: ppltasks.h:3778
void _TaskInitNoFunctor(task_completion_event< _ReturnType > &_Event)
Initializes a task using a task completion event.
Definition: ppltasks.h:3988
Definition: pplconcrt.h:97
Represents the allowed options for creating a task
Definition: ppltasks.h:1195
task()
Constructs a task object.
Definition: ppltasks.h:4151
The Concurrency namespace provides classes and functions that provide access to the Concurrency Runti...
Definition: agents.h:42
Definition: ppltasks.h:3649
bool _M_isTaskBasedContinuation
Definition: ppltasks.h:1397
Definition: ppltasks.h:4618
bool _Cancel(bool _SynchronousCancel)
Definition: ppltasks.h:1810
The implementation of a first-class task. This structure contains the task group used to execute the ...
Definition: ppltasks.h:1380
void _TaskRetType
Definition: ppltasks.h:401
void _SetAsync(bool _Async=true)
Sets a property determining whether the task is apartment aware.
Definition: ppltasks.h:4488
cancellation_token get_cancellation_token() const
Returns the cancellation token
Definition: ppltasks.h:1325
_TaskEventLogger _M_taskEventLogger
Definition: ppltasks.h:2310
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION()
Definition: pplconcrt.h:81
_ExceptionHolder(const std::exception_ptr &_E, const _TaskCreationCallstack &_stackTrace)
Definition: ppltasks.h:891
Definition: ppltasks.h:384
_CancellationTokenState * _M_pTokenState
Definition: ppltasks.h:2299
reference_wrapper< _Ty > ref(_Ty &_Val) _NOEXCEPT
Definition: xrefwrap:691
_TaskInliningMode_t _M_inliningMode
Definition: ppltasks.h:1400
integral_constant< bool, false > false_type
Definition: xtr1common:48
bool _IsApartmentAware()
Definition: ppltasks.h:1900
void _Cancel() const
Cancel the task_completion_event. Any task created using this event will be marked as canceled if it ...
Definition: ppltasks.h:2929
scheduler_ptr scheduler() const
Returns the scheduler for this task
Definition: ppltasks.h:4412
iterator_traits< _InIt >::difference_type distance(_InIt _First, _InIt _Last)
Definition: xutility:755
Definition: concrt.h:5273
auto _LogWorkItemAndInvokeUserLambda(_Func &&_func, _Arg &&_value) const -> decltype(_func(std::forward< _Arg >(_value)))
Definition: ppltasks.h:3772
_TypeSelectorNoAsync _AsyncKind
Definition: ppltasks.h:477
task_completion_event< details::_Unit_type > _M_unitEvent
Definition: ppltasks.h:2974
The task_completion_event class allows you to delay the execution of a task until a condition is sati...
Definition: ppltasks.h:2883
_Internal_task_options()
Definition: ppltasks.h:1183
unsigned char _Unit_type
Definition: ppltasks.h:247
virtual ~_InitialTaskHandle()
Definition: ppltasks.h:3659
A non-reentrant mutex which is explicitly aware of the Concurrency Runtime.
Definition: concrt.h:3548
__declspec(noinline) bool set_exception(_E _Except) const
Definition: ppltasks.h:2905
bool _CancelWithException(const std::exception_ptr &_Exception)
Definition: ppltasks.h:1831
bool is_done() const
Determines if the task is completed.
Definition: ppltasks.h:3507
Definition: ppltasks.h:378
_TaskProcThunk * _M_pThunk
Definition: ppltasks.h:512
_TaskWorkItemRAIILogger(_TaskEventLogger &)
Definition: ppltasks.h:1558
bool has_scheduler() const
Indicates whether a scheduler n was specified by the user
Definition: ppltasks.h:1341
_TaskCreationCallstack()
Definition: ppltasks.h:223
bool _IsTriggered() const
Tests whether current event has been either Set, or Canceled.
Definition: ppltasks.h:2773
void _DeregisterCancellation()
Definition: ppltasks.h:1854
void _LogWorkItemCompleted()
Definition: ppltasks.h:1550
void _ScheduleContinuationTask(_ContinuationTaskHandleBase *_PTaskHandle)
Definition: ppltasks.h:1996
static std::shared_ptr< details::_ExceptionHolder > _ToExceptionHolder(std::exception_ptr _ExceptionPtr, const details::_TaskCreationCallstack &_SetExceptionAddressHint)
Definition: ppltasks.h:2785
details::_Internal_task_options _M_InternalTaskOptions
Definition: ppltasks.h:1363
task_status _Wait()
Definition: ppltasks.h:1679
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:2948
void * _M_SingleFrame
Definition: ppltasks.h:220
void _SetImpl(details::_Task_ptr< details::_Unit_type >::_Type &&_Impl)
Set the implementation of the task to be the supplied implementaion using a move instead of a copy...
Definition: ppltasks.h:4480
void _TaskInitMaybeFunctor(_Function &_Func, std::true_type)
Initializes a task using a callable object.
Definition: ppltasks.h:4030
#define _ASSERTE(expr)
Definition: crtdbg.h:216
static auto _Perform(std::function< void(void)> _Func) -> decltype(details::_MakeUnitToUnitFunc(_Func))
Definition: ppltasks.h:3084
bool operator==(const _ContextCallback &) const
Definition: ppltasks.h:775
_In_ size_t _In_z_ const unsigned char * _Src
Definition: mbstring.h:95
task()
Constructs a task object.
Definition: ppltasks.h:3158
Definition: ppltasks.h:878
void _Continue(std::false_type, details::_TypeSelectorAsyncOperationOrTask) const
Definition: ppltasks.h:3818
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:2369
shared_ptr< _Ty > make_shared(_Types &&..._Args)
Definition: memory:1000
void _Init(details::_TypeSelectorAsyncOperationOrTask) const
Definition: ppltasks.h:3696
details::_Task_ptr< _ReturnType >::_Type _M_Impl
Definition: ppltasks.h:4105
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2281
_UnwrapTaskType< _Type >::_Type _TaskRetType
Definition: ppltasks.h:386
_TaskEventLogger(_Task_impl_base *)
Definition: ppltasks.h:1554
Definition: vccorlib.h:112
_TaskInliningMode
The enum defines inlining scheduling policy for ppltasks. Scheduling a chore or a functor with _TaskI...
Definition: concrt.h:5270
virtual ~_Task_impl_base()
Definition: ppltasks.h:1670
::Concurrency::extensibility::critical_section_t _M_ContinuationsCritSec
Definition: ppltasks.h:2295
#define FAILED(hr)
Definition: comutil.h:71
_ResultHolder< _ResultType > _M_value
Definition: ppltasks.h:2575
bool has_cancellation_token() const
Indicates whether a cancellation token was specified by the user
Definition: ppltasks.h:1317
_CRTIMP size_t __cdecl CaptureCallstack(void **stackData, size_t skipFrames, size_t captureFrames)
#define bool
Definition: stdbool.h:10
task_continuation_context get_continuation_context() const
Returns the continuation context
Definition: ppltasks.h:1333
_ContinuationTaskHandleBase * _ContinuationList
Definition: ppltasks.h:2293
_Boolarray operator&&(const valarray< _Ty > &_Left, const _Ty &_Right)
Definition: valarray:661
bool operator!=(const task< _ReturnType > &_Rhs) const
Determines whether two task objects represent different internal tasks.
Definition: ppltasks.h:3568
_TaskList _M_tasks
Definition: ppltasks.h:2573
static _CancellationTokenState * _None()
Definition: pplcancellation_token.h:328
void _LogCancelTask()
Definition: ppltasks.h:1548
std::shared_ptr< _Task_impl< _ReturnType > > _Type
Definition: ppltasks.h:1385
static void _RunTask(TaskProc _Proc, void *_Parameter, _TaskInliningMode _InliningMode)
Definition: pplconcrt.h:237
auto _IsValidTaskCtor(_Ty _Param, int, int, int, int) -> decltype(_Param(), std::true_type())
atomic_long _M_exceptionObserved
Definition: ppltasks.h:936
_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:2780
_TaskTypeTraits< _FuncRetType >::_AsyncKind _AsyncKind
Definition: ppltasks.h:469
bool _IsCreated()
Definition: ppltasks.h:1864
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: ppltasks.h:4120
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:3461
The tasks queued to the task_group or structured_task_group object completed successfully.
Definition: pplinterface.h:127
bool _IsTriggered() const
Test whether current event has been either Set, or Canceled.
Definition: ppltasks.h:2956
bool operator!=(const task< void > &_Rhs) const
Determines whether two task objects represent different internal tasks.
Definition: ppltasks.h:4448
auto _ThenImpl(const _Function &_Func, const task_options &_TaskOptions) const -> typename details::_ContinuationTypeTraits< _Function, _InternalReturnType >::_TaskOfType
Definition: ppltasks.h:4045
The task_group or structured_task_group object was canceled. One or more tasks may not have executed...
Definition: pplinterface.h:133
auto _IsTaskHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t)), std::true_type())
Definition: pplcancellation_token.h:104
Definition: ppltasks.h:1383
void _ScheduleContinuation(_ContinuationTaskHandleBase *_PTaskHandle)
Schedule the actual continuation. This will either schedule the function on the continuation task's i...
Definition: ppltasks.h:2067
::Concurrency::extensibility::critical_section_t _M_taskListCritSec
Definition: ppltasks.h:2574
task_options(task_continuation_context _ContinuationContext)
Task option that specify a continuation context. This is valid only for continuations (then) ...
Definition: ppltasks.h:1227
Definition: ppltasks.h:3093
__declspec(noinline) static _TaskCreationCallstack _CaptureMultiFramesCallstack(size_t _CaptureFrames)
Definition: ppltasks.h:237
Definition: ppltasks.h:1545
bool _CancelWithExceptionHolder(const std::shared_ptr< _ExceptionHolder > &_ExHolder, bool _PropagatedFromAncestor)
Definition: ppltasks.h:1816
auto _ReturnTypeHelper(_Type t, _Function _Func, int, int) -> decltype(_Func(_To_task(t)))
_TaskInternalState
Definition: ppltasks.h:1647
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:2757
__declspec(noinline) auto then(const _Function &_Func) const -> typename details::_ContinuationTypeTraits< _Function, _ReturnType >::_TaskOfType
Adds a continuation task to this task.
Definition: ppltasks.h:3375
void rethrow_exception(_In_ exception_ptr _P)
Definition: exception:532
details::_Task_completion_event_impl< details::_Unit_type >::_TaskList _TaskList
Definition: ppltasks.h:2794
std::exception_ptr _M_stdException
Definition: ppltasks.h:939
std::function< _Unit_type(_Type)> _MakeTToUnitFunc(const std::function< void(_Type)> &_Func)
Definition: ppltasks.h:2594
#define false
Definition: stdbool.h:11
void Set(const _Type &_type)
Definition: ppltasks.h:791
bool is_apartment_aware() const
Determines whether the task unwraps a Windows Runtime IAsyncInfo interface or is descended from such ...
Definition: ppltasks.h:3540
_CRTIMP2 unsigned int __cdecl GetNextAsyncId()
#define or
Definition: iso646.h:15
auto _GetUnwrappedReturnType(_Ty _Arg, int) -> decltype(_GetUnwrappedType(_Arg))
_TaskCollection_t::_TaskProcHandle_t _UnrealizedChore_t
Definition: ppltasks.h:1389
static _ContextCallback _CaptureCurrent()
Definition: ppltasks.h:734
Definition: vector:649
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:2968
auto _VoidIsTaskHelper(_Function _Func, int, int) -> decltype(_Func(_To_task()), std::true_type())
bool __cdecl is_task_cancellation_requested()
Returns an indication of whether the task that is currently executing has received a request to cance...
Definition: ppltasks.h:188
_Task_impl_base(_CancellationTokenState *_PTokenState, scheduler_ptr _Scheduler_arg)
Definition: ppltasks.h:1657
bool _IsPendingCancel()
Definition: ppltasks.h:1874
task & operator=(task &&_Other)
Replaces the contents of one task object with another.
Definition: ppltasks.h:3345
The task_continuation_context class allows you to specify where you would like a continuation to be e...
Definition: ppltasks.h:1088
task(task &&_Other)
Constructs a task object.
Definition: ppltasks.h:3312
void _SetImpl(const typename details::_Task_ptr< _ReturnType >::_Type &_Impl)
Set the implementation of the task to be the supplied implementaion.
Definition: ppltasks.h:3597
Represents a pointer to a scheduler. This class exists to allow the the specification of a shared lif...
Definition: pplinterface.h:58
bool _M_hasPresetCreationCallstack
Definition: ppltasks.h:1175
_TaskCreationCallstack _M_pTaskCreationCallstack
Definition: ppltasks.h:2308
virtual ~_ContinuationTaskHandle()
Definition: ppltasks.h:3769
void _SetAsync(bool _Async=true)
Sets a property determining whether the task is apartment aware.
Definition: ppltasks.h:3615
_CancellationTokenRegistration * _M_pRegistration
Definition: ppltasks.h:2302
void _ScheduleTask(_UnrealizedChore_t *_PTaskHandle, _TaskInliningMode_t _InliningMode)
Helper function to schedule the task on the Task Collection.
Definition: ppltasks.h:1929
void set_continuation_context(task_continuation_context _ContinuationContext)
Sets the given continuation context in the options
Definition: ppltasks.h:1309
bool _CancelInternal() const
Cancels the task_completion_event.
Definition: ppltasks.h:2799
task_options(const task_options &_TaskOptions)
Task option copy constructor
Definition: ppltasks.h:1288
_Task_impl(_CancellationTokenState *_Ct, scheduler_ptr _Scheduler_arg)
Definition: ppltasks.h:2354
_In_ wctype_t _Type
Definition: ctype.h:205
bool operator==(const task< _ReturnType > &_Rhs) const
Determines whether two task objects represent the same internal task.
Definition: ppltasks.h:3556
_Function _M_function
Definition: ppltasks.h:3752
bool _M_fUnwrappedTask
Definition: ppltasks.h:2286
bool _IsDone()
Definition: ppltasks.h:2525
bool operator!=(const _ContextCallback &) const
Definition: ppltasks.h:780
bool _M_fFromAsync
Definition: ppltasks.h:2284
virtual _Task_ptr_base _GetTaskImplBase() const =0
_T atomic_increment(std::atomic< _T > &_Target)
Definition: pplinterface.h:160
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:2846
static bool _IsValid(_In_opt_ _CancellationTokenState *_PToken)
Definition: pplcancellation_token.h:333
static auto _Perform(std::function< void(void)> _Func) -> decltype(details::_MakeVoidToUnitFunc(_Func))
Definition: ppltasks.h:3106
task_options(scheduler_ptr _Scheduler)
Task option that specify a scheduler
Definition: ppltasks.h:1276
_Boolarray operator||(const valarray< _Ty > &_Left, const _Ty &_Right)
Definition: valarray:675
void _CreateImpl(details::_CancellationTokenState *_Ct, scheduler_ptr _Scheduler)
Create an underlying task implementation.
Definition: ppltasks.h:3576
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2576
task_options(std::shared_ptr< _SchedType > _Scheduler)
Task option that specify a scheduler with shared lifetime
Definition: ppltasks.h:1252
void ReportUnhandledError()
Definition: ppltasks.h:881
#define _T(x)
Definition: tchar.h:2498
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:2938
void _TaskInitWithFunctor(const _Function &_Func)
Initializes a task using a lambda, function pointer or function object.
Definition: ppltasks.h:3975
task_group_status
Describes the execution status of a task_group or structured_task_group object. A value of this type ...
Definition: pplinterface.h:114
__declspec(noinline) bool set_exception(std
Propagates an exception to all tasks associated with this event.
Definition: ppltasks.h:2918
bool _IsStarted()
Definition: ppltasks.h:1869
#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:162
for(;0< _Count;)
Definition: algorithm:1944
Definition: ppltasks.h:538
void _Continue(std::true_type, details::_TypeSelectorNoAsync) const
Definition: ppltasks.h:3885
_ReturnType result_type
The type of the result an object of this class produces.
Definition: ppltasks.h:3134
static _Type _Make(_CancellationTokenState *_Ct, scheduler_ptr _Scheduler_arg)
Definition: ppltasks.h:1386
bool set(_ResultType _Result) const
Sets the task completion event.
Definition: ppltasks.h:2651
Definition: pplcancellation_token.h:212
task_continuation_context _M_continuationContext
Definition: ppltasks.h:1396
_Task_completion_event_impl()
Definition: ppltasks.h:2552
std::shared_ptr< details::_Task_completion_event_impl< _ResultType > > _M_Impl
Definition: ppltasks.h:2865
if(__pUnknown!=*__ppTargetUnknown)
Definition: vccorlib.h:394
void set_cancellation_token(cancellation_token _Token)
Sets the given token in the options
Definition: ppltasks.h:1300
void _SetImpl(const details::_Task_ptr< details::_Unit_type >::_Type &_Impl)
Set the implementation of the task to be the supplied implementaion.
Definition: ppltasks.h:4472
static void __cdecl _Bridge(void *_PData)
Definition: ppltasks.h:492
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: ppltasks.h:134
Definition: ppltasks.h:114
__declspec(noinline) bool set_exception(_E _Except) const
Definition: ppltasks.h:2700
bool _M_fIsCanceled
Definition: ppltasks.h:2578
scheduler_ptr scheduler() const
Returns the scheduler for this task
Definition: ppltasks.h:3523
void _LogTaskCompleted()
Definition: ppltasks.h:1553
#define _ASSERT(expr)
Definition: crtdbg.h:212
Definition: utility:80
auto _VoidReturnTypeHelper(_Function _Func, int, int) -> decltype(_Func(_To_task()))
add_rvalue_reference< _Ty >::type declval() _NOEXCEPT
_ResultHolder< _ReturnType > _M_Result
Definition: ppltasks.h:2535
_ImplType _GetImplValue() const
Definition: pplcancellation_token.h:748
integral_constant< bool, true > true_type
Definition: xtr1common:47
bool _Cancel() const
Internal method to cancel the task_completion_event. Any task created using this event will be marked...
Definition: ppltasks.h:2725
_Diff _Count
Definition: algorithm:1941
task< _Type > _To_task(_Type t)
Definition: ppltasks.h:282
static void _AsyncInit(const typename _Task_ptr< _ReturnType >::_Type &_OuterTask, const task< _InternalReturnType > &_UnwrappedTask)
Definition: ppltasks.h:2240
_CreateImpl(_TaskOptions.get_cancellation_token()._GetImplValue(), _TaskOptions.get_scheduler())
_Type Get()
Definition: ppltasks.h:796
bool _HasCapturedContext() const
Definition: ppltasks.h:761
void _LogCancelTask(_Task_impl_base *)
Definition: ppltasks.h:1544
Helper object used for LWT invocation.
Definition: ppltasks.h:485
task_continuation_context _M_ContinuationContext
Definition: ppltasks.h:1362
TypeT Get() const
Definition: agile.h:191
std::atomic< long > atomic_long
Atomics
Definition: pplinterface.h:142
auto _LogWorkItemAndInvokeUserLambda(_Func &&_func) const -> decltype(_func())
Definition: ppltasks.h:3662
A helper class template that transforms a continuation lambda that either takes or returns void...
Definition: ppltasks.h:3051
__declspec(deprecated("Concurrency::EnableTracing is a deprecated function.")) _CRTIMP HRESULT __cdecl EnableTracing()
Enables tracing in the Concurrency Runtime. This function is deprecated because ETW tracing is now on...
The task handle type used to create a 'continuation task'.
Definition: ppltasks.h:3745
void _Continue(std::true_type, details::_TypeSelectorAsyncOperationOrTask) const
Definition: ppltasks.h:3903
Definition: xtr1common:94
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:1239
exception_ptr make_exception_ptr(_E _Except)
Definition: exception:539
void _SetTaskCreationCallstack(const _TaskCreationCallstack &_Callstack)
Definition: ppltasks.h:1915
_TypeSelectorNoAsync _AsyncKind
Definition: ppltasks.h:402
_Ty _Type
Definition: ppltasks.h:284
Definition: atomic:56
const std::shared_ptr< _ExceptionHolder > & _GetExceptionHolder()
Definition: ppltasks.h:1894
bool is_apartment_aware() const
Determines whether the task unwraps a Windows Runtime IAsyncInfo interface or is descended from such ...
Definition: ppltasks.h:4424
_Ty _GetUnwrappedType(task< _Ty >)
The following type traits are used for the create_task function.
void _RunTaskContinuations()
Definition: ppltasks.h:2133
_TypeSelectorAsyncTask _AsyncOperationKindSelector(task< _T >)
task & operator=(const task &_Other)
Replaces the contents of one task object with another.
Definition: ppltasks.h:3325
_Unit_type _NormalizedTaskRetType
Definition: ppltasks.h:403
bool _M_HasCancellationToken
Definition: ppltasks.h:1364
bool _HasUserException()
Definition: ppltasks.h:2557
void result_type
The type of the result an object of this class produces.
Definition: ppltasks.h:4127
static task_continuation_context use_default()
Creates the default task continuation context.
Definition: ppltasks.h:1109
The base implementation of a first-class task. This class contains all the non-type specific implemen...
Definition: ppltasks.h:1645
void _FinalizeAndRunContinuations(_ReturnType _Result)
Definition: ppltasks.h:2465
_TaskCreationCallstack _GetTaskCreationCallstack()
Definition: ppltasks.h:1910
bool operator!=(const _Concurrent_queue_iterator< _C, _Ty > &_I, const _Concurrent_queue_iterator< _C, _U > &_J)
Definition: concurrent_queue.h:323
void _CreateImpl(details::_CancellationTokenState *_Ct, scheduler_ptr _Scheduler)
Create an underlying task implementation.
Definition: ppltasks.h:4456
void _SyncCancelAndPropagateException() const
Definition: ppltasks.h:3673
task_options(scheduler_interface &_Scheduler)
Task option that specify a scheduler reference
Definition: ppltasks.h:1264
const details::_Task_ptr< details::_Unit_type >::_Type & _GetImpl() const
Return the underlying implementation for this task.
Definition: ppltasks.h:4464
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:3634
An exception safe RAII wrapper for a critical_section object.
Definition: concrt.h:3661
Definition: ppltasks.h:4627
std::function< void(void)> _CallbackFunction
Definition: ppltasks.h:540
virtual ~_ContinuationTaskHandleBase()
Definition: ppltasks.h:1409
Definition: pplcancellation_token.h:167
_FwdIt const _Ty _Val
Definition: algorithm:1938
bool set() const
Sets the task completion event.
Definition: ppltasks.h:2899
virtual void invoke() const
Definition: ppltasks.h:1590
void _CallInContext(_CallbackFunction _Func) const
Definition: ppltasks.h:770
std::function< void()> _M_func
Definition: ppltasks.h:518
const details::_Task_ptr< _ReturnType >::_Type & _GetImpl() const
Return the underlying implementation for this task.
Definition: ppltasks.h:3589
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:4373
_ContinuationTaskHandleBase()
Definition: ppltasks.h:1404
void _RegisterCancellation(std::weak_ptr< _Task_impl_base > _WeakPtr)
Definition: ppltasks.h:1838
virtual ~_Task_impl()
Definition: ppltasks.h:2362
_TaskProcThunk(const std::function< void()> &_Callback)
Definition: ppltasks.h:487
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:3754
long __cdecl _InterlockedCompareExchange(long volatile *, long, long)
std::shared_ptr< ::Concurrency::scheduler_interface > get_ambient_scheduler()
Definition: pplconcrt.h:64
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:533
bool _TransitionedToStarted()
Definition: ppltasks.h:2494
#define true
Definition: stdbool.h:12
The _PPLTaskHandle is the strong-typed task handle base. All user task functions need to be wrapped i...
Definition: ppltasks.h:1578
void _TaskInitMaybeFunctor(_T &_Param, std::false_type)
Initializes a task using a non-callable object.
Definition: ppltasks.h:4558
task_continuation_context(bool _DeferCapture=false)
Definition: ppltasks.h:1165
task_group_status task_status
A type that represents the terminal state of a task. Valid values are completed and canceled...
Definition: ppltasks.h:132
bool is_done() const
Determines if the task is completed.
Definition: ppltasks.h:4401
pair< typename _Unrefwrap< _Ty1 >::type, typename _Unrefwrap< _Ty2 >::type > make_pair(_Ty1 &&_Val1, _Ty2 &&_Val2)
Definition: utility:267
scheduler_ptr get_scheduler() const
Returns the scheduler
Definition: ppltasks.h:1349
const _Ty & _Right
Definition: algorithm:4087
_Type _Result
Definition: ppltasks.h:801
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:2736
void _SetAsync(bool _Async=true)
Definition: ppltasks.h:1905
void _TaskInitNoFunctor(task_completion_event< void > &_Event)
Initializes a task using a task completion event.
Definition: ppltasks.h:4521
void _TaskInitMaybeFunctor(_Ty &_Param, std::false_type)
Initializes a task using a non-callable object.
Definition: ppltasks.h:4039
void _ValidateTaskConstructorArgs(_Ty _Param)
Definition: ppltasks.h:3007
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:215
_ReturnType _GetResult()
Definition: ppltasks.h:2530
__declspec(noinline)~_ExceptionHolder()
Definition: ppltasks.h:906
static auto _Perform(std::function< _OutType(_InpType)> _Func) -> decltype(_Func)
Definition: ppltasks.h:3054