27 #error This header must not be included directly
30 #ifndef _PPLXCANCELLATION_TOKEN_H
31 #define _PPLXCANCELLATION_TOKEN_H
33 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX
34 #error This file must not be included for Visual Studio 12 or later
38 #include "pplx/pplxinterface.h"
40 #pragma pack(push,_CRT_PACKING)
42 #pragma push_macro("new")
85 const char* what() const CPPREST_NOEXCEPT
87 return _message.c_str();
102 std::string _message;
128 const char* what() const CPPREST_NOEXCEPT
130 return _message.c_str();
144 _ASSERTE(_M_refCount == 0);
151 long _Refcount = atomic_increment(_M_refCount);
154 _ASSERTE(_Refcount > 1);
162 long _Refcount = atomic_decrement(_M_refCount);
163 _ASSERTE(_Refcount >= 0);
176 virtual void _Destroy()
182 _RefCounter(
long _InitialCount = 1) : _M_refCount(_InitialCount)
184 _ASSERTE(_M_refCount > 0);
188 atomic_long _M_refCount;
197 static const long _STATE_CLEAR = 0;
198 static const long _STATE_DEFER_DELETE = 1;
199 static const long _STATE_SYNCHRONIZE = 2;
200 static const long _STATE_CALLED = 3;
206 _M_state(_STATE_CALLED),
213 return _M_pTokenState;
220 _ASSERTE(_M_state != _STATE_CLEAR);
223 virtual void _Exec() = 0;
231 long tid = ::pplx::details::platform::GetCurrentThreadId();
232 _ASSERTE((tid & 0x3) == 0);
234 long result = atomic_compare_exchange(_M_state, tid, _STATE_CLEAR);
236 if (result == _STATE_CLEAR)
240 result = atomic_compare_exchange(_M_state, _STATE_CALLED, tid);
242 if (result == _STATE_SYNCHRONIZE)
244 _M_pSyncBlock->set();
250 atomic_long _M_state;
255 template<
typename _Function>
274 _Function _M_function;
307 typedef struct _Node {
319 #if defined(_MSC_VER)
320 #pragma warning(push)
321 #pragma warning(disable: 6001)
323 auto node = _M_begin;
324 while (node !=
nullptr)
327 node = node->_M_next;
330 #if defined(_MSC_VER)
337 std::swap(list._M_begin, _M_begin);
338 std::swap(list._M_last, _M_last);
343 return _M_begin ==
nullptr;
347 void for_each(T lambda)
349 Node* node = _M_begin;
351 while (node !=
nullptr)
353 lambda(node->_M_token);
354 node = node->_M_next;
360 Node* node =
reinterpret_cast<Node*
>(::malloc(
sizeof(Node)));
363 throw ::std::bad_alloc();
366 node->_M_token = token;
367 node->_M_next =
nullptr;
369 if (_M_begin ==
nullptr)
375 _M_last->_M_next = node;
383 Node* node = _M_begin;
384 Node* prev =
nullptr;
386 while (node !=
nullptr)
388 if (node->_M_token == token) {
391 _M_begin = node->_M_next;
395 prev->_M_next = node->_M_next;
398 if (node->_M_next ==
nullptr)
408 node = node->_M_next;
429 static bool _IsValid(_In_opt_ _CancellationTokenState *_PToken)
431 return (_PToken != NULL && _PToken != _None());
434 _CancellationTokenState() :
439 ~_CancellationTokenState()
441 TokenRegistrationContainer rundownList;
443 extensibility::scoped_critical_section_t _Lock(_M_listLock);
444 _M_registrations.swap(rundownList);
447 rundownList.for_each([](_CancellationTokenRegistration * pRegistration)
449 pRegistration->_M_state = _CancellationTokenRegistration::_STATE_SYNCHRONIZE;
450 pRegistration->_Release();
454 bool _IsCanceled()
const
456 return (_M_stateFlag != 0);
461 if (atomic_compare_exchange(_M_stateFlag, 1l, 0l) == 0)
463 TokenRegistrationContainer rundownList;
465 extensibility::scoped_critical_section_t _Lock(_M_listLock);
466 _M_registrations.swap(rundownList);
469 rundownList.for_each([](_CancellationTokenRegistration * pRegistration)
471 pRegistration->_Invoke();
475 _M_cancelComplete.set();
479 _CancellationTokenRegistration *_RegisterCallback(
TaskProc_t _PCallback, _In_
void *_PData,
int _InitialRefs = 1)
481 _CancellationTokenRegistration *pRegistration =
new CancellationTokenRegistration_TaskProc(_PCallback, _PData, _InitialRefs);
482 _RegisterCallback(pRegistration);
483 return pRegistration;
486 void _RegisterCallback(_In_ _CancellationTokenRegistration *_PRegistration)
488 _PRegistration->_M_state = _CancellationTokenRegistration::_STATE_CLEAR;
489 _PRegistration->_Reference();
490 _PRegistration->_M_pTokenState =
this;
496 extensibility::scoped_critical_section_t _Lock(_M_listLock);
501 _M_registrations.push_back(_PRegistration);
507 _PRegistration->_Invoke();
511 void _DeregisterCallback(_In_ _CancellationTokenRegistration *_PRegistration)
513 bool synchronize =
false;
516 extensibility::scoped_critical_section_t _Lock(_M_listLock);
523 if (!_M_registrations.empty())
525 _M_registrations.remove(_PRegistration);
526 _PRegistration->_M_state = _CancellationTokenRegistration::_STATE_SYNCHRONIZE;
527 _PRegistration->_Release();
545 long result = atomic_compare_exchange(
546 _PRegistration->_M_state,
547 _CancellationTokenRegistration::_STATE_DEFER_DELETE,
548 _CancellationTokenRegistration::_STATE_CLEAR
553 case _CancellationTokenRegistration::_STATE_CLEAR:
554 case _CancellationTokenRegistration::_STATE_CALLED:
556 case _CancellationTokenRegistration::_STATE_DEFER_DELETE:
557 case _CancellationTokenRegistration::_STATE_SYNCHRONIZE:
563 if (tid == ::pplx::details::platform::GetCurrentThreadId())
573 extensibility::event_t ev;
574 _PRegistration->_M_pSyncBlock = &ev;
576 long result_1 = atomic_exchange(_PRegistration->_M_state, _CancellationTokenRegistration::_STATE_SYNCHRONIZE);
578 if (result_1 != _CancellationTokenRegistration::_STATE_CALLED)
580 _PRegistration->_M_pSyncBlock->wait(::pplx::extensibility::event_t::timeout_infinite);
592 atomic_long _M_stateFlag;
595 extensibility::event_t _M_cancelComplete;
598 extensibility::critical_section_t _M_listLock;
601 TokenRegistrationContainer _M_registrations;
606 class cancellation_token_source;
607 class cancellation_token;
621 _M_pRegistration(NULL)
632 _Assign(_Src._M_pRegistration);
637 _Move(_Src._M_pRegistration);
645 _Assign(_Src._M_pRegistration);
655 _Move(_Src._M_pRegistration);
662 return _M_pRegistration == _Rhs._M_pRegistration;
667 return !(operator==(_Rhs));
675 _M_pRegistration(_PRegistration)
681 if (_M_pRegistration != NULL)
683 _M_pRegistration->_Release();
685 _M_pRegistration = NULL;
690 if (_PRegistration != NULL)
692 _PRegistration->_Reference();
694 _M_pRegistration = _PRegistration;
699 _M_pRegistration = _PRegistration;
700 _PRegistration = NULL;
731 _Assign(_Src._M_Impl);
734 cancellation_token(cancellation_token&& _Src)
739 cancellation_token& operator=(
const cancellation_token& _Src)
744 _Assign(_Src._M_Impl);
749 cancellation_token& operator=(cancellation_token&& _Src)
759 bool operator==(
const cancellation_token& _Src)
const
761 return _M_Impl == _Src._M_Impl;
764 bool operator!=(
const cancellation_token& _Src)
const
766 return !(operator==(_Src));
769 ~cancellation_token()
782 return (_M_Impl != NULL);
793 return (_M_Impl != NULL && _M_Impl->_IsCanceled());
812 template<
typename _Function>
820 #if defined(_MSC_VER)
821 #pragma warning(suppress: 28197)
824 _M_Impl->_RegisterCallback(_PCallback);
838 _M_Impl->_DeregisterCallback(_Registration._M_pRegistration);
841 _ImplType _GetImpl()
const
846 _ImplType _GetImplValue()
const
848 return (_M_Impl == NULL) ? ::pplx::details::_CancellationTokenState::_None() : _M_Impl;
851 static cancellation_token _FromImpl(_ImplType _Impl)
853 return cancellation_token(_Impl);
858 friend class cancellation_token_source;
871 void _Assign(_ImplType _Impl)
880 void _Move(_ImplType &_Impl)
886 cancellation_token() :
891 cancellation_token(_ImplType _Impl) :
894 if (_M_Impl == ::pplx::details::_CancellationTokenState::_None())
901 _M_Impl->_Reference();
913 typedef ::pplx::details::_CancellationTokenState * _ImplType;
920 _M_Impl = new ::pplx::details::_CancellationTokenState;
925 _Assign(_Src._M_Impl);
938 _Assign(_Src._M_Impl);
955 return _M_Impl == _Src._M_Impl;
960 return !(operator==(_Src));
1014 template<
typename _Iter>
1018 for (_Iter _It = _Begin; _It != _End; ++_It)
1020 _It->register_callback( [newSource](){ newSource.
cancel(); } );
1034 _ImplType _GetImpl()
const
1050 if (_M_Impl != NULL)
1052 _M_Impl->_Release();
1057 void _Assign(_ImplType _Impl)
1061 _Impl->_Reference();
1066 void _Move(_ImplType &_Impl)
1075 if (_M_Impl == ::pplx::details::_CancellationTokenState::_None())
1080 if (_M_Impl != NULL)
1082 _M_Impl->_Reference();
1089 #pragma pop_macro("new")
1092 #endif // _PPLXCANCELLATION_TOKEN_H
void(_pplx_cdecl * TaskProc_t)(void *)
An elementary abstraction for a task, defined as void (__cdecl * TaskProc_t)(void *)...
Definition: pplxinterface.h:59
invalid_operation(_In_z_ const char *_Message)
Constructs an invalid_operation object.
Definition: pplxcancellation_token.h:112
void cancel() const
Cancels the token. Any task_group, structured_task_group, or task which utilizes the token will be ca...
Definition: pplxcancellation_token.h:1029
cancellation_token_source()
Constructs a new cancellation_token_source. The source can be used to flag cancellation of some cance...
Definition: pplxcancellation_token.h:918
Definition: pplxcancellation_token.h:277
void deregister_callback(const cancellation_token_registration &_Registration) const
Removes a callback previously registered via the register method based on the cancellation_token_regi...
Definition: pplxcancellation_token.h:836
::pplx::cancellation_token_registration register_callback(const _Function &_Func) const
Registers a callback function with the token. If and when the token is canceled, the callback will be...
Definition: pplxcancellation_token.h:813
The pplx namespace provides classes and functions that give you access to the Concurrency Runtime...
Definition: pplx.h:81
Definition: pplxcancellation_token.h:138
This class describes an exception thrown by the PPL tasks layer in order to force the current task to...
Definition: pplxcancellation_token.h:56
The cancellation_token_source class represents the ability to cancel some cancelable operation...
Definition: pplxcancellation_token.h:909
bool is_canceled() const
Returns true if the token has been canceled.
Definition: pplxcancellation_token.h:791
task_canceled(_In_z_ const char *_Message)
Constructs a task_canceled object.
Definition: pplxcancellation_token.h:69
static cancellation_token_source create_linked_source(cancellation_token &_Src)
Creates a cancellation_token_source which is canceled when the provided token is canceled.
Definition: pplxcancellation_token.h:993
invalid_operation()
Constructs an invalid_operation object.
Definition: pplxcancellation_token.h:121
Definition: pplxcancellation_token.h:256
The cancellation_token class represents the ability to determine whether some operation has been requ...
Definition: pplxcancellation_token.h:712
The cancellation_token_registration class represents a callback notification from a cancellation_toke...
Definition: pplxcancellation_token.h:616
cancellation_token get_token() const
Returns a cancellation token associated with this source. The returned token can be polled for cancel...
Definition: pplxcancellation_token.h:978
task_canceled()
Constructs a task_canceled object.
Definition: pplxcancellation_token.h:78
Manual reset event
Definition: pplxlinux.h:84
static cancellation_token none()
Returns a cancellation token which can never be subject to cancellation.
Definition: pplxcancellation_token.h:724
Definition: pplxcancellation_token.h:193
static cancellation_token_source create_linked_source(_Iter _Begin, _Iter _End)
Creates a cancellation_token_source which is canceled when one of a series of tokens represented by a...
Definition: pplxcancellation_token.h:1015
Definition: pplxcancellation_token.h:304
bool is_cancelable() const
Returns an indication of whether this token can be canceled or not.
Definition: pplxcancellation_token.h:780
Definition: pplxcancellation_token.h:301
This class describes an exception thrown when an invalid operation is performed that is not more accu...
Definition: pplxcancellation_token.h:99