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