📄 concrt.h
字号:
/***
* ==++==
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* concrt.h
*
* Main public header file for ConcRT. This is the only header file a C++ program should
* have to include in order to avail itself of the core concurrency runtime features.
*
* Agents and PPL live in separate headers.
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include <crtdefs.h>
#if !(defined (_M_AMD64) || defined (_M_IX86))
#error ERROR: Concurrency Runtime is supported only on X64 and X86 architectures.
#endif /* !(defined (_M_AMD64) || defined (_M_IX86)) */
#if defined (_M_CEE)
#error ERROR: Concurrency Runtime is not supported when compiling /clr.
#endif /* defined (_M_CEE) */
#ifndef __cplusplus
#error ERROR: Concurrency Runtime is supported only for C++.
#endif /* __cplusplus */
#include <exception>
#include <sal.h>
#include <limits.h>
#include <crtdbg.h>
#include <guiddef.h>
#include <intrin.h>
#include <new>
#pragma pack(push,_CRT_PACKING)
// Forward declare structs needed from windows headers
struct _SECURITY_ATTRIBUTES;
typedef _SECURITY_ATTRIBUTES* LPSECURITY_ATTRIBUTES;
// Define essential types needed from windows headers
typedef unsigned long DWORD;
typedef long HRESULT;
typedef void * HANDLE;
// Undefine Yield that is possibly defined by windows.h, and _YieldProcessor just in case
#undef Yield
#undef _YieldProcessor
#define _YieldProcessor _mm_pause
// Make sure exchange pointer intrinsics work on x86
#if defined (_M_IX86)
#undef _InterlockedExchangePointer
#undef _InterlockedCompareExchangePointer
#define _InterlockedExchangePointer(_Target, _Value) reinterpret_cast<void *>(static_cast<__w64 long>(_InterlockedExchange( \
static_cast<long volatile *>(reinterpret_cast<__w64 long volatile *>(static_cast<void * volatile *>(_Target))), \
static_cast<long>(reinterpret_cast<__w64 long>(static_cast<void *>(_Value))))))
#define _InterlockedCompareExchangePointer(_Target, _Exchange, _Comparand) reinterpret_cast<void *>(static_cast<__w64 long>(_InterlockedCompareExchange( \
static_cast<long volatile *>(reinterpret_cast<__w64 long volatile *>(static_cast<void * volatile *>(_Target))), \
static_cast<long>(reinterpret_cast<__w64 long>(static_cast<void *>(_Exchange))), \
static_cast<long>(reinterpret_cast<__w64 long>(static_cast<void *>(_Comparand))))))
#define _InterlockedIncrementSizeT(_Target) _InterlockedIncrement(reinterpret_cast<long volatile *>(_Target))
#define _InterlockedDecrementSizeT(_Target) _InterlockedDecrement(reinterpret_cast<long volatile *>(_Target))
#define _InterlockedCompareExchangeSizeT(_Target, _Exchange, _Comparand) _InterlockedCompareExchange( \
reinterpret_cast<long volatile *>(_Target), \
static_cast<long>(_Exchange), \
static_cast<long>(_Comparand))
#else /* defined (_M_IX86) */
#define _InterlockedIncrementSizeT(_Target) _InterlockedIncrement64(reinterpret_cast<__int64 volatile *>(_Target))
#define _InterlockedDecrementSizeT(_Target) _InterlockedDecrement64(reinterpret_cast<__int64 volatile *>(_Target))
#define _InterlockedCompareExchangeSizeT(_Target, _Exchange, _Comparand) _InterlockedCompareExchange64( \
reinterpret_cast<__int64 volatile *>(_Target), \
static_cast<__int64>(_Exchange), \
static_cast<__int64>(_Comparand))
#endif /* defined (_M_IX86) */
// Used internally to represent the smallest unit in which to allocate hidden types
typedef void * _CONCRT_BUFFER;
/// <summary>
/// The <c>Concurrency</c> namespace provides classes and functions that give you access to the Concurrency Runtime,
/// a concurrent programming framework for C++. For more information, see <see cref="Concurrency Runtime"/>.
/// </summary>
/**/
namespace Concurrency
{
/// <summary>
/// Pauses the current context for a specified amount of time.
/// </summary>
/// <param name="_Milliseconds">
/// The number of milliseconds that the current context should be paused for. If the <paramref name="_Milliseconds"/> parameter is set to
/// the value <c>0</c>, it indicates that the current context should yield execution to other runnable contexts before continuing.
/// </param>
/// <remarks>
/// If this method is called on a Concurrency Runtime scheduler context, the scheduler will find a different context to run on the underlying
/// resource. Since the scheduler is cooperative in nature, this context may not resume exactly after the number of milliseconds specified.
/// If the scheduler is busy executing other tasks that do not cooperatively yield to the scheduler in a hurry, the wait period could be
/// indefinite.
/// </remarks>
/**/
_CRTIMP void __cdecl wait(unsigned int _Milliseconds);
/// <summary>
/// Allocates a block of memory of the size specified from the Concurrency Runtime's Caching Suballocator.
/// </summary>
/// <param name="_NumBytes">
/// The number of bytes of memory to allocate.
/// </param>
/// <returns>
/// A pointer to newly allocated memory.
/// </returns>
/// <remarks>
/// For more information on what scenarios in your application could benefit from using the Caching Suballocator,
/// see <see cref="Task Scheduler (Concurrency Runtime)"/>.
/// </remarks>
/// <seealso cref="Concurrency::Free Function"/>
/**/
_CRTIMP void * __cdecl Alloc(size_t _NumBytes);
/// <summary>
/// Frees a block of memory previously allocated by the <c>Alloc</c> method to the Concurrency Runtime's Caching Suballocator.
/// </summary>
/// <param name="_PAllocation">
/// A pointer to memory previously allocated by the <c>Alloc</c> method which is to be freed. If the parameter <paramref name="_PAllocation"/>
/// is set to the value <c>NULL</c>, this method will ignore it and return immediately.
/// </param>
/// <remarks>
/// For more information on what scenarios in your application could benefit from using the Caching Suballocator,
/// see <see cref="Task Scheduler (Concurrency Runtime)"/>.
/// </remarks>
/// <seealso cref="Concurrency::Alloc Function"/>
/**/
_CRTIMP void __cdecl Free(void * _PAllocation);
/// <summary>
/// Concurrency::details contains definitions of support routines in the public namespaces and some macros.
/// Users should not directly interact with this internal namespace.
/// </summary>
/**/
namespace details
{
//
// Forward declarations:
//
class ContextBase;
class _TaskCollectionBase;
//
// A utility to hide operator delete from certain objects while still allowing the runtime to delete them internally.
//
template<class _T>
void _InternalDeleteHelper(_T * _PObject)
{
delete _PObject;
}
// This class's purpose is solely to direct allocations of ConcRT classes
// through a single point, using internal allocator.
struct _AllocBase
{
// Standard operator new
void * operator new(size_t _Size)
{
return Concurrency::Alloc(_Size);
}
// Standard operator delete
void operator delete(void * _Ptr) throw()
{
Concurrency::Free(_Ptr);
}
// Standard operator new, no-throw version
void * operator new(size_t _Size, const std::nothrow_t&) throw()
{
void * _Ptr;
try
{
_Ptr = Concurrency::Alloc(_Size);
}
catch(...)
{
_Ptr = NULL;
}
return (_Ptr);
}
// Standard operator delete, no-throw version
void operator delete(void * _Ptr, const std::nothrow_t&) throw()
{
operator delete(_Ptr);
}
// Standard operator new array
void * operator new[](size_t _Size)
{
return operator new(_Size);
}
// Standard operator delete array
void operator delete[](void * _Ptr) throw()
{
operator delete(_Ptr);
}
// Standard operator new array, no-throw version
void * operator new[](size_t _Size, const std::nothrow_t& _No_throw) throw ()
{
return operator new(_Size, _No_throw);
}
// Standard operator delete array, no-throw version
void operator delete[](void * _Ptr, const std::nothrow_t& _No_throw) throw()
{
operator delete(_Ptr, _No_throw);
}
// Standard operator new with void* placement
void * operator new(size_t, void * _Location) throw()
{
return _Location;
}
// Standard operator delete with void* placement
void operator delete(void *, void *) throw()
{
}
// Standard operator new array with void* placement
void * __cdecl operator new[](size_t, void * _Location) throw()
{
return _Location;
}
// Standard operator delete array with void* placement
void __cdecl operator delete[](void *, void *) throw()
{
}
};
//
// Wrappers for atomic access
//
template <size_t _Size>
struct _Subatomic_impl { };
template<>
struct _Subatomic_impl<4> {
template <typename _Ty>
static void _StoreWithRelease(volatile _Ty& _Location, _Ty _Rhs) {
_ReadWriteBarrier();
_Location = _Rhs;
}
template <typename _Ty>
static _Ty _LoadWithAquire(volatile _Ty& _Location) {
_ReadWriteBarrier();
return _Location;
}
template <typename _Ty>
static _Ty _CompareAndSwap(volatile _Ty& _Location, _Ty _NewValue, _Ty _Comperand) {
return (_Ty)_InterlockedCompareExchange((volatile long*)&_Location, (long)_NewValue, (long)_Comperand);
}
template <typename _Ty>
static _Ty _FetchAndAdd(volatile _Ty& _Location, _Ty _Addend) {
return (_Ty)_InterlockedExchangeAdd((volatile long*)&_Location, (long)_Addend);
}
template <typename _Ty>
static _Ty _Increment(volatile _Ty& _Location) {
return (_Ty)_InterlockedIncrement((volatile long*)&_Location);
}
template <typename _Ty>
static _Ty _Decrement(volatile _Ty& _Location) {
return (_Ty)_InterlockedDecrement((volatile long*)&_Location);
}
};
#if defined (_M_X64)
template<>
struct _Subatomic_impl<8> {
template <typename _Ty>
static void _StoreWithRelease(volatile _Ty& _Location, _Ty _Rhs) {
_ReadWriteBarrier();
_Location = _Rhs;
}
template <typename _Ty>
static _Ty _LoadWithAquire(volatile _Ty& _Location) {
_ReadWriteBarrier();
return _Location;
}
template <typename _Ty>
static _Ty _CompareAndSwap(volatile _Ty& _Location, _Ty _NewValue, _Ty _Comperand) {
return (_Ty)_InterlockedCompareExchange64((volatile __int64*)&_Location, (__int64)_NewValue, (__int64)_Comperand);
}
template <typename _Ty>
static _Ty _FetchAndAdd(volatile _Ty& _Location, _Ty _Addend) {
return (_Ty)_InterlockedExchangeAdd64((volatile __int64*)&_Location, (__int64)_Addend);
}
template <typename _Ty>
static _Ty _Increment(volatile _Ty& _Location) {
return (_Ty)_InterlockedIncrement64((volatile __int64*)&_Location);
}
template <typename _Ty>
static _Ty _Decrement(volatile _Ty& _Location) {
return (_Ty)_InterlockedDecrement64((volatile __int64*)&_Location);
}
};
#endif /* defined (_M_X64) */
//
// Wrapper for atomic access. Only works for 4-byte or 8-byte types (e.g., int, long, long long, size_t, pointer).
// Anything else will likely fail to compile.
//
template <typename _Ty>
class _Subatomic {
private:
volatile _Ty _M_value;
public:
operator _Ty() const volatile {
return _Subatomic_impl<sizeof(_Ty)>::_LoadWithAquire(_M_value);
}
_Ty operator=(_Ty _Rhs) {
_Subatomic_impl<sizeof(_Ty)>::_StoreWithRelease(_M_value, _Rhs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -