STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | List of all members
Concurrency::details::_Task_impl_base Struct Referenceabstract

The base implementation of a first-class task. This class contains all the non-type specific implementation details of the task. More...

#include <ppltasks.h>

Inheritance diagram for Concurrency::details::_Task_impl_base:
Concurrency::details::_Task_impl< _ReturnType >

Public Types

enum  _TaskInternalState {
  _Created, _Started, _PendingCancel, _Completed,
  _Canceled
}
 
typedef _ContinuationTaskHandleBase_ContinuationList
 

Public Member Functions

 _Task_impl_base (_CancellationTokenState *_PTokenState, scheduler_ptr _Scheduler_arg)
 
virtual ~_Task_impl_base ()
 
task_status _Wait ()
 
virtual bool _CancelAndRunContinuations (bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr< _ExceptionHolder > &_ExHolder)=0
 Requests cancellation on the task and schedules continuations if the task can be transitioned to a terminal state. More...
 
bool _Cancel (bool _SynchronousCancel)
 
bool _CancelWithExceptionHolder (const std::shared_ptr< _ExceptionHolder > &_ExHolder, bool _PropagatedFromAncestor)
 
bool _CancelWithException (const std::exception_ptr &_Exception)
 
void _RegisterCancellation (std::weak_ptr< _Task_impl_base > _WeakPtr)
 
void _DeregisterCancellation ()
 
bool _IsCreated ()
 
bool _IsStarted ()
 
bool _IsPendingCancel ()
 
bool _IsCompleted ()
 
bool _IsCanceled ()
 
bool _HasUserException ()
 
const std::shared_ptr< _ExceptionHolder > & _GetExceptionHolder ()
 
bool _IsApartmentAware ()
 
void _SetAsync (bool _Async=true)
 
_TaskCreationCallstack _GetTaskCreationCallstack ()
 
void _SetTaskCreationCallstack (const _TaskCreationCallstack &_Callstack)
 
void _ScheduleTask (_UnrealizedChore_t *_PTaskHandle, _TaskInliningMode_t _InliningMode)
 Helper function to schedule the task on the Task Collection. More...
 
void _RunContinuation (_ContinuationTaskHandleBase *_PTaskHandle)
 Function executes a continuation. This function is recorded by a parent task implementation when a continuation is created in order to execute later. More...
 
void _ScheduleContinuationTask (_ContinuationTaskHandleBase *_PTaskHandle)
 
void _ScheduleContinuation (_ContinuationTaskHandleBase *_PTaskHandle)
 Schedule the actual continuation. This will either schedule the function on the continuation task's implementation if the task has completed or append it to a list of functions to execute when the task actually does complete. More...
 
void _RunTaskContinuations ()
 
scheduler_ptr _GetScheduler () const
 

Static Public Member Functions

static _CRTIMP2 bool __cdecl _IsNonBlockingThread ()
 
template<typename _ReturnType , typename _InternalReturnType >
static void _AsyncInit (const typename _Task_ptr< _ReturnType >::_Type &_OuterTask, const task< _InternalReturnType > &_UnwrappedTask)
 

Public Attributes

volatile _TaskInternalState _M_TaskState
 
bool _M_fFromAsync
 
bool _M_fUnwrappedTask
 
std::shared_ptr< _ExceptionHolder_M_exceptionHolder
 
std::mutex _M_ContinuationsCritSec
 
_ContinuationList _M_Continuations
 
_CancellationTokenState_M_pTokenState
 
_CancellationTokenRegistration_M_pRegistration
 
::Concurrency::details::_TaskCollection_t _M_TaskCollection
 
_TaskCreationCallstack _M_pTaskCreationCallstack
 
_TaskEventLogger _M_taskEventLogger
 

Private Member Functions

 _Task_impl_base (const _Task_impl_base &)
 
_Task_impl_base const & operator= (_Task_impl_base const &)
 

Detailed Description

The base implementation of a first-class task. This class contains all the non-type specific implementation details of the task.

Member Typedef Documentation

Member Enumeration Documentation

Enumerator
_Created 
_Started 
_PendingCancel 
_Completed 
_Canceled 
1454  {
1455  // Tracks the state of the task, rather than the task collection on which the task is scheduled
1456  _Created,
1457  _Started,
1459  _Completed,
1460  _Canceled
1461  };

Constructor & Destructor Documentation

Concurrency::details::_Task_impl_base::_Task_impl_base ( _CancellationTokenState _PTokenState,
scheduler_ptr  _Scheduler_arg 
)
inline
1465  _M_fFromAsync(false), _M_fUnwrappedTask(false),
1466  _M_pRegistration(nullptr), _M_Continuations(nullptr), _M_TaskCollection(_Scheduler_arg),
1467  _M_taskEventLogger(this)
1468  {
1469  // Set cancellation token
1470  _M_pTokenState = _PTokenState;
1471  _ASSERTE(_M_pTokenState != nullptr);
1474  }
_ContinuationList _M_Continuations
Definition: ppltasks.h:2031
::Concurrency::details::_TaskCollection_t _M_TaskCollection
Definition: ppltasks.h:2040
_TaskEventLogger _M_taskEventLogger
Definition: ppltasks.h:2045
_CancellationTokenState * _M_pTokenState
Definition: ppltasks.h:2034
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
static _CancellationTokenState * _None()
Definition: pplcancellation_token.h:332
_CancellationTokenRegistration * _M_pRegistration
Definition: ppltasks.h:2037
bool _M_fUnwrappedTask
Definition: ppltasks.h:2021
bool _M_fFromAsync
Definition: ppltasks.h:2019
long _Reference()
Definition: pplcancellation_token.h:62
virtual Concurrency::details::_Task_impl_base::~_Task_impl_base ( )
inlinevirtual
1477  {
1478  _ASSERTE(_M_pTokenState != nullptr);
1480  {
1482  }
1483  }
_CancellationTokenState * _M_pTokenState
Definition: ppltasks.h:2034
static _CancellationTokenState * _None()
Definition: pplcancellation_token.h:332
long _Release()
Definition: pplcancellation_token.h:73
Concurrency::details::_Task_impl_base::_Task_impl_base ( const _Task_impl_base )
private

Member Function Documentation

template<typename _ReturnType , typename _InternalReturnType >
static void Concurrency::details::_Task_impl_base::_AsyncInit ( const typename _Task_ptr< _ReturnType >::_Type &  _OuterTask,
const task< _InternalReturnType > &  _UnwrappedTask 
)
inlinestatic
1976  {
1977  _ASSERTE(_OuterTask->_M_fUnwrappedTask && !_OuterTask->_IsCanceled());
1978 
1979  //
1980  // We must ensure that continuations off _OuterTask (especially exception handling ones) continue to function in the
1981  // presence of an exception flowing out of the inner task _UnwrappedTask. This requires an exception handling continuation
1982  // off the inner task which does the appropriate funnelling to the outer one. We use _Then instead of then to prevent
1983  // the exception from being marked as observed by our internal continuation. This continuation must be scheduled regardless
1984  // of whether or not the _OuterTask task is canceled.
1985  //
1986  _UnwrappedTask._Then([_OuterTask] (task<_InternalReturnType> _AncestorTask) {
1987 
1988  if (_AncestorTask._GetImpl()->_IsCompleted())
1989  {
1990  _OuterTask->_FinalizeAndRunContinuations(_AncestorTask._GetImpl()->_GetResult());
1991  }
1992  else
1993  {
1994  _ASSERTE(_AncestorTask._GetImpl()->_IsCanceled());
1995  if (_AncestorTask._GetImpl()->_HasUserException())
1996  {
1997  // Set _PropagatedFromAncestor to false, since _AncestorTask is not an ancestor of _UnwrappedTask.
1998  // Instead, it is the enclosing task.
1999  _OuterTask->_CancelWithExceptionHolder(_AncestorTask._GetImpl()->_GetExceptionHolder(), false);
2000  }
2001  else
2002  {
2003  _OuterTask->_Cancel(true);
2004  }
2005  }
2006  }, nullptr, details::_DefaultAutoInline);
2007 
2008  }
Definition: pplinterface.h:226
bool Concurrency::details::_Task_impl_base::_Cancel ( bool  _SynchronousCancel)
inline
1597  {
1598  // Send in a dummy value for exception. It is not used when the first parameter is false.
1599  return _CancelAndRunContinuations(_SynchronousCancel, false, false, _M_exceptionHolder);
1600  }
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2026
virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr< _ExceptionHolder > &_ExHolder)=0
Requests cancellation on the task and schedules continuations if the task can be transitioned to a te...
virtual bool Concurrency::details::_Task_impl_base::_CancelAndRunContinuations ( bool  _SynchronousCancel,
bool  _UserException,
bool  _PropagatedFromAncestor,
const std::shared_ptr< _ExceptionHolder > &  _ExHolder 
)
pure virtual

Requests cancellation on the task and schedules continuations if the task can be transitioned to a terminal state.

Parameters
_SynchronousCancelSet to true if the cancel takes place as a result of the task body encountering an exception, or because an ancestor or task_completion_event the task was registered with were canceled with an exception. A synchronous cancel is one that assures the task could not be running on a different thread at the time the cancellation is in progress. An asynchronous cancel is one where the thread performing the cancel has no control over the thread that could be executing the task, that is the task could execute concurrently while the cancellation is in progress.
_UserExceptionWhether an exception other than the internal runtime cancellation exceptions caused this cancellation.
_PropagatedFromAncestorWhether this exception came from an ancestor task or a task_completion_event as opposed to an exception that was encountered by the task itself. Only valid when _UserException is set to true.
_ExHolderThe exception holder that represents the exception. Only valid when _UserException is set to true.

Implemented in Concurrency::details::_Task_impl< _ReturnType >.

bool Concurrency::details::_Task_impl_base::_CancelWithException ( const std::exception_ptr &  _Exception)
inline
1609  {
1610  // This task was canceled because the task body encountered an exception.
1611  _ASSERTE(!_HasUserException());
1612  return _CancelAndRunContinuations(true, true, false, std::make_shared<_ExceptionHolder>(_Exception, _GetTaskCreationCallstack()));
1613  }
bool _HasUserException()
Definition: ppltasks.h:1666
virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr< _ExceptionHolder > &_ExHolder)=0
Requests cancellation on the task and schedules continuations if the task can be transitioned to a te...
_TaskCreationCallstack _GetTaskCreationCallstack()
Definition: ppltasks.h:1687
bool Concurrency::details::_Task_impl_base::_CancelWithExceptionHolder ( const std::shared_ptr< _ExceptionHolder > &  _ExHolder,
bool  _PropagatedFromAncestor 
)
inline
1603  {
1604  // This task was canceled because an ancestor task encountered an exception.
1605  return _CancelAndRunContinuations(true, true, _PropagatedFromAncestor, _ExHolder);
1606  }
virtual bool _CancelAndRunContinuations(bool _SynchronousCancel, bool _UserException, bool _PropagatedFromAncestor, const std::shared_ptr< _ExceptionHolder > &_ExHolder)=0
Requests cancellation on the task and schedules continuations if the task can be transitioned to a te...
void Concurrency::details::_Task_impl_base::_DeregisterCancellation ( )
inline
1632  {
1633  if (_M_pRegistration != nullptr)
1634  {
1637  _M_pRegistration = nullptr;
1638  }
1639  }
_CancellationTokenState * _M_pTokenState
Definition: ppltasks.h:2034
void _DeregisterCallback(_In_ _CancellationTokenRegistration *_PRegistration)
Definition: pplcancellation_token.h:418
_CancellationTokenRegistration * _M_pRegistration
Definition: ppltasks.h:2037
long _Release()
Definition: pplcancellation_token.h:73
const std::shared_ptr<_ExceptionHolder>& Concurrency::details::_Task_impl_base::_GetExceptionHolder ( )
inline
1672  {
1673  _ASSERTE(_HasUserException());
1674  return _M_exceptionHolder;
1675  }
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2026
bool _HasUserException()
Definition: ppltasks.h:1666
scheduler_ptr Concurrency::details::_Task_impl_base::_GetScheduler ( ) const
inline
2011  {
2013  }
::Concurrency::details::_TaskCollection_t _M_TaskCollection
Definition: ppltasks.h:2040
::Concurrency::scheduler_ptr _GetScheduler() const
Definition: pplwin.h:229
_TaskCreationCallstack Concurrency::details::_Task_impl_base::_GetTaskCreationCallstack ( )
inline
1688  {
1690  }
_TaskCreationCallstack _M_pTaskCreationCallstack
Definition: ppltasks.h:2043
bool Concurrency::details::_Task_impl_base::_HasUserException ( )
inline
1667  {
1668  return static_cast<bool>(_M_exceptionHolder);
1669  }
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2026
bool Concurrency::details::_Task_impl_base::_IsApartmentAware ( )
inline
1678  {
1679  return _M_fFromAsync;
1680  }
bool _M_fFromAsync
Definition: ppltasks.h:2019
bool Concurrency::details::_Task_impl_base::_IsCanceled ( )
inline
1662  {
1663  return (_M_TaskState == _Canceled);
1664  }
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
bool Concurrency::details::_Task_impl_base::_IsCompleted ( )
inline
1657  {
1658  return (_M_TaskState == _Completed);
1659  }
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
bool Concurrency::details::_Task_impl_base::_IsCreated ( )
inline
1642  {
1643  return (_M_TaskState == _Created);
1644  }
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
static _CRTIMP2 bool __cdecl Concurrency::details::_Task_impl_base::_IsNonBlockingThread ( )
static
bool Concurrency::details::_Task_impl_base::_IsPendingCancel ( )
inline
1652  {
1653  return (_M_TaskState == _PendingCancel);
1654  }
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
bool Concurrency::details::_Task_impl_base::_IsStarted ( )
inline
1647  {
1648  return (_M_TaskState == _Started);
1649  }
volatile _TaskInternalState _M_TaskState
Definition: ppltasks.h:2016
void Concurrency::details::_Task_impl_base::_RegisterCancellation ( std::weak_ptr< _Task_impl_base _WeakPtr)
inline
1616  {
1618 
1619  auto _CancellationCallback = [_WeakPtr](){
1620  // Taking ownership of the task prevents dead lock during destruction
1621  // if the destructor waits for the cancellations to be finished
1622  auto _task = _WeakPtr.lock();
1623  if (_task != nullptr)
1624  _task->_Cancel(false);
1625  };
1626 
1627  _M_pRegistration = new details::_CancellationTokenCallback<decltype(_CancellationCallback)>(_CancellationCallback);
1629  }
_CancellationTokenRegistration * _RegisterCallback(TaskProc_t _PCallback, _In_ void *_PData, int _InitialRefs=1)
Definition: pplcancellation_token.h:386
_CancellationTokenState * _M_pTokenState
Definition: ppltasks.h:2034
_CancellationTokenRegistration * _M_pRegistration
Definition: ppltasks.h:2037
static bool _IsValid(_In_opt_ _CancellationTokenState *_PToken)
Definition: pplcancellation_token.h:337
void Concurrency::details::_Task_impl_base::_RunContinuation ( _ContinuationTaskHandleBase _PTaskHandle)
inline

Function executes a continuation. This function is recorded by a parent task implementation when a continuation is created in order to execute later.

Parameters
_PTaskHandleThe continuation task chore handle that need to be executed.
1743  {
1744  _Task_ptr_base _ImplBase = _PTaskHandle->_GetTaskImplBase();
1745  if (_IsCanceled() && !_PTaskHandle->_M_isTaskBasedContinuation)
1746  {
1747  if (_HasUserException())
1748  {
1749  // If the ancestor encountered an exception, transfer the exception to the continuation
1750  // This traverses down the tree to propagate the exception.
1751  _ImplBase->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
1752  }
1753  else
1754  {
1755  // If the ancestor was canceled, then your own execution should be canceled.
1756  // This traverses down the tree to cancel it.
1757  _ImplBase->_Cancel(true);
1758  }
1759  }
1760  else
1761  {
1762  // This can only run when the ancestor has completed or it's a task based continuation that fires when a task is canceled
1763  // (with or without a user exception).
1764  _ASSERTE(_IsCompleted() || _PTaskHandle->_M_isTaskBasedContinuation);
1765  _ASSERTE(!_ImplBase->_IsCanceled());
1766  return _ImplBase->_ScheduleContinuationTask(_PTaskHandle);
1767  }
1768 
1769  // If the handle is not scheduled, we need to manually delete it.
1770  delete _PTaskHandle;
1771  }
bool _IsCompleted()
Definition: ppltasks.h:1656
bool _HasUserException()
Definition: ppltasks.h:1666
std::shared_ptr< _Task_impl_base > _Task_ptr_base
Definition: ppltasks.h:1286
bool _IsCanceled()
Definition: ppltasks.h:1661
const std::shared_ptr< _ExceptionHolder > & _GetExceptionHolder()
Definition: ppltasks.h:1671
void Concurrency::details::_Task_impl_base::_RunTaskContinuations ( )
inline
1901  {
1902  // The link list can no longer be modified at this point,
1903  // since all following up continuations will be scheduled by themselves.
1904  _ContinuationList _Cur = _M_Continuations, _Next;
1905  _M_Continuations = nullptr;
1906  while (_Cur)
1907  {
1908  // Current node might be deleted after running,
1909  // so we must fetch the next first.
1910  _Next = _Cur->_M_next;
1911  _RunContinuation(_Cur);
1912  _Cur = _Next;
1913  }
1914  }
_ContinuationList _M_Continuations
Definition: ppltasks.h:2031
void _RunContinuation(_ContinuationTaskHandleBase *_PTaskHandle)
Function executes a continuation. This function is recorded by a parent task implementation when a co...
Definition: ppltasks.h:1742
_ContinuationTaskHandleBase * _M_next
Definition: ppltasks.h:1291
_ContinuationTaskHandleBase * _ContinuationList
Definition: ppltasks.h:2028
void Concurrency::details::_Task_impl_base::_ScheduleContinuation ( _ContinuationTaskHandleBase _PTaskHandle)
inline

Schedule the actual continuation. This will either schedule the function on the continuation task's implementation if the task has completed or append it to a list of functions to execute when the task actually does complete.

Template Parameters
_FuncInputTypeThe input type of the task.
_FuncOutputTypeThe output type of the task.
1835  {
1836  enum { _Nothing, _Schedule, _Cancel, _CancelWithException } _Do = _Nothing;
1837 
1838  // If the task has canceled, cancel the continuation. If the task has completed, execute the continuation right away.
1839  // Otherwise, add it to the list of pending continuations
1840  {
1841  ::std::lock_guard<std::mutex> _LockHolder(_M_ContinuationsCritSec);
1842  if (_IsCompleted() || (_IsCanceled() && _PTaskHandle->_M_isTaskBasedContinuation))
1843  {
1844  _Do = _Schedule;
1845  }
1846  else if (_IsCanceled())
1847  {
1848  if (_HasUserException())
1849  {
1850  _Do = _CancelWithException;
1851  }
1852  else
1853  {
1854  _Do = _Cancel;
1855  }
1856  }
1857  else
1858  {
1859  // chain itself on the continuation chain.
1860  _PTaskHandle->_M_next = _M_Continuations;
1861  _M_Continuations = _PTaskHandle;
1862  }
1863  }
1864 
1865  // Cancellation and execution of continuations should be performed after releasing the lock. Continuations off of
1866  // async tasks may execute inline.
1867  switch (_Do)
1868  {
1869  case _Schedule:
1870  {
1871  _PTaskHandle->_GetTaskImplBase()->_ScheduleContinuationTask(_PTaskHandle);
1872  break;
1873  }
1874  case _Cancel:
1875  {
1876  // If the ancestor was canceled, then your own execution should be canceled.
1877  // This traverses down the tree to cancel it.
1878  _PTaskHandle->_GetTaskImplBase()->_Cancel(true);
1879 
1880  delete _PTaskHandle;
1881  break;
1882  }
1883  case _CancelWithException:
1884  {
1885  // If the ancestor encountered an exception, transfer the exception to the continuation
1886  // This traverses down the tree to propagate the exception.
1887  _PTaskHandle->_GetTaskImplBase()->_CancelWithExceptionHolder(_GetExceptionHolder(), true);
1888 
1889  delete _PTaskHandle;
1890  break;
1891  }
1892  case _Nothing:
1893  default:
1894  // In this case, we have inserted continuation to continuation chain,
1895  // nothing more need to be done, just leave.
1896  break;
1897  }
1898  }
bool _IsCompleted()
Definition: ppltasks.h:1656
bool _HasUserException()
Definition: ppltasks.h:1666
_ContinuationList _M_Continuations
Definition: ppltasks.h:2031
bool _IsCanceled()
Definition: ppltasks.h:1661
bool _Cancel(bool _SynchronousCancel)
Definition: ppltasks.h:1596
bool _CancelWithException(const std::exception_ptr &_Exception)
Definition: ppltasks.h:1608
std::mutex _M_ContinuationsCritSec
Definition: ppltasks.h:2030
virtual _Task_ptr_base _GetTaskImplBase() const =0
const std::shared_ptr< _ExceptionHolder > & _GetExceptionHolder()
Definition: ppltasks.h:1671
void Concurrency::details::_Task_impl_base::_ScheduleContinuationTask ( _ContinuationTaskHandleBase _PTaskHandle)
inline
1775  {
1776 
1778  // Ensure that the continuation runs in proper context (this might be on a Concurrency Runtime thread or in a different Windows Runtime apartment)
1779  if (_PTaskHandle->_M_continuationContext._HasCapturedContext())
1780  {
1781  // For those continuations need to be scheduled inside captured context, we will try to apply automatic inlining to their inline modes,
1782  // if they haven't been specified as _ForceInline yet. This change will encourage those continuations to be executed inline so that reduce
1783  // the cost of marshaling.
1784  // For normal continuations we won't do any change here, and their inline policies are completely decided by ._ThenImpl method.
1785  if (_PTaskHandle->_M_inliningMode != details::_ForceInline)
1786  {
1787  _PTaskHandle->_M_inliningMode = details::_DefaultAutoInline;
1788  }
1789  _ScheduleFuncWithAutoInline([_PTaskHandle]() {
1790  // Note that we cannot directly capture "this" pointer, instead, we should use _TaskImplPtr, a shared_ptr to the _Task_impl_base.
1791  // Because "this" pointer will be invalid as soon as _PTaskHandle get deleted. _PTaskHandle will be deleted after being scheduled.
1792  auto _TaskImplPtr = _PTaskHandle->_GetTaskImplBase();
1793  if (details::_ContextCallback::_CaptureCurrent() == _PTaskHandle->_M_continuationContext)
1794  {
1795  _TaskImplPtr->_ScheduleTask(_PTaskHandle, details::_ForceInline);
1796  }
1797  else
1798  {
1799  //
1800  // It's entirely possible that the attempt to marshal the call into a differing context will fail. In this case, we need to handle
1801  // the exception and mark the continuation as canceled with the appropriate exception. There is one slight hitch to this:
1802  //
1803  // NOTE: COM's legacy behavior is to swallow SEH exceptions and marshal them back as HRESULTS. This will in effect turn an SEH into
1804  // a C++ exception that gets tagged on the task. One unfortunate result of this is that various pieces of the task infrastructure will
1805  // not be in a valid state after this in /EHsc (due to the lack of destructors running, etc...).
1806  //
1807  _TRY_BEGIN
1808  _PTaskHandle->_M_continuationContext._CallInContext( [_PTaskHandle, _TaskImplPtr](){
1809  _TaskImplPtr->_ScheduleTask(_PTaskHandle, details::_ForceInline);
1810  });
1811  _CATCH_ALL
1812  _TaskImplPtr->_CancelWithException(std::current_exception());
1813  _CATCH_END
1814  }
1815  }, _PTaskHandle->_M_inliningMode);
1816  }
1817  else
1818  {
1819  _ScheduleTask(_PTaskHandle, _PTaskHandle->_M_inliningMode);
1820  }
1821  }
Definition: pplinterface.h:228
#define _TRY_BEGIN
Definition: xstddef:60
#define _CATCH_END
Definition: xstddef:63
_TaskEventLogger _M_taskEventLogger
Definition: ppltasks.h:2045
_CRTIMP2 void __thiscall _LogScheduleTask(bool _isContinuation)
Definition: pplinterface.h:226
static _ContextCallback _CaptureCurrent()
Definition: ppltasks.h:502
#define _CATCH_ALL
Definition: xstddef:62
void _ScheduleTask(_UnrealizedChore_t *_PTaskHandle, _TaskInliningMode_t _InliningMode)
Helper function to schedule the task on the Task Collection.
Definition: ppltasks.h:1706
exception_ptr current_exception() _NOEXCEPT
Definition: exception:359
static void _ScheduleFuncWithAutoInline(const std::function< void()> &_Func, _TaskInliningMode_t _InliningMode)
Schedule a functor with automatic inlining. Note that this is "fire and forget" scheduling, which cannot be waited on or canceled after scheduling. This schedule method will perform automatic inlining base on .
Definition: ppltasks.h:491
void Concurrency::details::_Task_impl_base::_ScheduleTask ( _UnrealizedChore_t _PTaskHandle,
_TaskInliningMode_t  _InliningMode 
)
inline

Helper function to schedule the task on the Task Collection.

Parameters
_PTaskHandleThe task chore handle that need to be executed.
_InliningModeThe inlining scheduling policy for current _PTaskHandle.
1707  {
1708  _TRY_BEGIN
1709  _M_TaskCollection._ScheduleTask(_PTaskHandle, _InliningMode);
1710  _CATCH(const task_canceled &)
1711  // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
1712  // must be called from code that is executed within the task (throwing it from parallel work created by and waited
1713  // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
1714  // the exception and canceled the task. Swallow the exception here.
1715  _ASSERTE(_IsCanceled());
1716  _CATCH(const _Interruption_exception &)
1717  // The _TaskCollection will never be an interruption point since it has a none token.
1718  _ASSERTE(false);
1719  _CATCH_ALL
1720  // The exception could have come from two places:
1721  // 1. From the chore body, so it already should have been caught and canceled.
1722  // In this case swallow the exception.
1723  // 2. From trying to actually schedule the task on the scheduler.
1724  // In this case cancel the task with the current exception, otherwise the
1725  // task will never be signaled leading to deadlock when waiting on the task.
1726 
1727  if (!_HasUserException())
1728  {
1730  }
1731  _CATCH_END
1732  }
bool _HasUserException()
Definition: ppltasks.h:1666
#define _TRY_BEGIN
Definition: xstddef:60
#define _CATCH(x)
Definition: xstddef:61
bool _IsCanceled()
Definition: ppltasks.h:1661
#define _CATCH_END
Definition: xstddef:63
::Concurrency::details::_TaskCollection_t _M_TaskCollection
Definition: ppltasks.h:2040
bool _CancelWithException(const std::exception_ptr &_Exception)
Definition: ppltasks.h:1608
#define false
Definition: stdbool.h:16
#define _CATCH_ALL
Definition: xstddef:62
void _ScheduleTask(_TaskProcHandle_t *_Parameter, _TaskInliningMode _InliningMode)
Definition: pplwin.h:189
if(__pUnknown!=*__ppTargetUnknown)
Definition: vccorlib.h:399
exception_ptr current_exception() _NOEXCEPT
Definition: exception:359
void Concurrency::details::_Task_impl_base::_SetAsync ( bool  _Async = true)
inline
1683  {
1684  _M_fFromAsync = _Async;
1685  }
bool _M_fFromAsync
Definition: ppltasks.h:2019
void Concurrency::details::_Task_impl_base::_SetTaskCreationCallstack ( const _TaskCreationCallstack _Callstack)
inline
1693  {
1694  _M_pTaskCreationCallstack = _Callstack;
1695  }
_TaskCreationCallstack _M_pTaskCreationCallstack
Definition: ppltasks.h:2043
task_status Concurrency::details::_Task_impl_base::_Wait ( )
inline
1486  {
1487  bool _DoWait = true;
1488 
1489  if (_IsNonBlockingThread())
1490  {
1491  // In order to prevent Windows Runtime STA threads from blocking the UI, calling task.wait() task.get() is illegal
1492  // if task has not been completed.
1493  if (!_IsCompleted() && !_IsCanceled())
1494  {
1495  _THROW_NCEE(invalid_operation, "Illegal to wait on a task in a Windows Runtime STA");
1496  }
1497  else
1498  {
1499  // Task Continuations are 'scheduled' *inside* the chore that is executing on the ancestor's task group. If a continuation
1500  // needs to be marshalled to a different apartment instead of scheduling, we make a synchronous cross-apartment COM
1501  // call to execute the continuation. If it then happens to do something which waits on the ancestor (say it calls .get(),
1502  // which task based continuations are wont to do), waiting on the task group results in waiting on the chore that is making
1503  // this synchronous callback, which causes a deadlock. To avoid this, we test the state of the ancestor's event,
1504  // and we will NOT wait on it if it has finished execution (which means now we are in the inline synchronous callback).
1505  _DoWait = false;
1506  }
1507  }
1508 
1509  if (_DoWait)
1510  {
1511  // If this task was created from a Windows Runtime async operation, do not attempt to inline it. The
1512  // async operation will take place on a thread in the appropriate apartment Simply wait for the completed
1513  // event to be set.
1514  if (_M_fFromAsync)
1515  {
1517  }
1518  else
1519  {
1520  // Wait on the task collection to complete. The task collection is guaranteed to still be
1521  // valid since the task must be still within scope so that the _Task_impl_base destructor
1522  // has not yet been called. This call to _Wait potentially inlines execution of work.
1523  _TRY_BEGIN
1524  // Invoking wait on a task collection resets the state of the task collection. This means that
1525  // if the task collection itself were canceled, or had encountered an exception, only the first
1526  // call to wait will receive this status. However, both cancellation and exceptions flowing through
1527  // tasks set state in the task impl itself.
1528 
1529  // When it returns cancelled, either work chore or the cancel thread should already have set task's state
1530  // properly -- cancelled state or completed state (because there was no interruption point).
1531  // For tasks with unwrapped tasks, we should not change the state of current task, since the unwrapped task are still running.
1533  _CATCH(details::_Interruption_exception&)
1534  // The _TaskCollection will never be an interruption point since it has a none token.
1535  _ASSERTE(false);
1536  _CATCH(task_canceled&)
1537  // task_canceled is a special exception thrown by cancel_current_task. The spec states that cancel_current_task
1538  // must be called from code that is executed within the task (throwing it from parallel work created by and waited
1539  // upon by the task is acceptable). We can safely assume that the task wrapper _PPLTaskHandle::operator() has seen
1540  // the exception and canceled the task. Swallow the exception here.
1541  _ASSERTE(_IsCanceled());
1542  _CATCH_ALL
1543  // It's possible the task body hasn't seen the exception; if so we need to cancel with exception here.
1544  if(!_HasUserException())
1545  {
1547  }
1548  // Rethrow will mark the exception as observed.
1549  _M_exceptionHolder->_RethrowUserException();
1550  _CATCH_END
1551 
1552  // If the lambda body for this task (executed or waited upon in _RunAndWait above) happened to return a task
1553  // which is to be unwrapped and plumbed to the output of this task, we must not only wait on the lambda body, we must
1554  // wait on the **INNER** body. It is in theory possible that we could inline such if we plumb a series of things through;
1555  // however, this takes the tact of simply waiting upon the completion signal.
1556  if (_M_fUnwrappedTask)
1557  {
1559  }
1560  }
1561  }
1562 
1563  if (_HasUserException())
1564  {
1565  _M_exceptionHolder->_RethrowUserException();
1566  }
1567  else if (_IsCanceled())
1568  {
1569  return canceled;
1570  }
1571  _ASSERTE(_IsCompleted());
1572  return completed;
1573  }
std::shared_ptr< _ExceptionHolder > _M_exceptionHolder
Definition: ppltasks.h:2026
bool _IsCompleted()
Definition: ppltasks.h:1656
bool _HasUserException()
Definition: ppltasks.h:1666
void _RunAndWait()
Definition: pplwin.h:213
#define _TRY_BEGIN
Definition: xstddef:60
#define _CATCH(x)
Definition: xstddef:61
bool _IsCanceled()
Definition: ppltasks.h:1661
#define _CATCH_END
Definition: xstddef:63
::Concurrency::details::_TaskCollection_t _M_TaskCollection
Definition: ppltasks.h:2040
bool _CancelWithException(const std::exception_ptr &_Exception)
Definition: ppltasks.h:1608
#define _THROW_NCEE(x, y)
Definition: xstddef:78
The tasks queued to the task_group or structured_task_group object completed successfully.
Definition: pplinterface.h:115
The task_group or structured_task_group object was canceled. One or more tasks may not have executed...
Definition: pplinterface.h:121
#define false
Definition: stdbool.h:16
#define _CATCH_ALL
Definition: xstddef:62
bool _M_fUnwrappedTask
Definition: ppltasks.h:2021
bool _M_fFromAsync
Definition: ppltasks.h:2019
static _CRTIMP2 bool __cdecl _IsNonBlockingThread()
if(__pUnknown!=*__ppTargetUnknown)
Definition: vccorlib.h:399
exception_ptr current_exception() _NOEXCEPT
Definition: exception:359
void _Wait()
Definition: pplwin.h:218
_Task_impl_base const& Concurrency::details::_Task_impl_base::operator= ( _Task_impl_base const &  )
private

Member Data Documentation

_ContinuationList Concurrency::details::_Task_impl_base::_M_Continuations
std::mutex Concurrency::details::_Task_impl_base::_M_ContinuationsCritSec
std::shared_ptr<_ExceptionHolder> Concurrency::details::_Task_impl_base::_M_exceptionHolder
bool Concurrency::details::_Task_impl_base::_M_fFromAsync
bool Concurrency::details::_Task_impl_base::_M_fUnwrappedTask
_CancellationTokenRegistration* Concurrency::details::_Task_impl_base::_M_pRegistration
_TaskCreationCallstack Concurrency::details::_Task_impl_base::_M_pTaskCreationCallstack
_CancellationTokenState* Concurrency::details::_Task_impl_base::_M_pTokenState
::Concurrency::details::_TaskCollection_t Concurrency::details::_Task_impl_base::_M_TaskCollection
_TaskEventLogger Concurrency::details::_Task_impl_base::_M_taskEventLogger
volatile _TaskInternalState Concurrency::details::_Task_impl_base::_M_TaskState

The documentation for this struct was generated from the following file: