📄 ppl.h
字号:
/***
* ==++==
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* ppl.h
*
* Parallel Patterns Library
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include <crtdefs.h>
#include <concrt.h>
#include <stdexcept>
#include <iterator>
#include <functional>
#include <type_traits>
#pragma pack(push,_CRT_PACKING)
// Define the level of tracing to use
#define _TRACE_LEVEL_INFORMATION 4
/// <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
{
namespace details
{
_CRTIMP2 size_t __cdecl _GetCombinableSize();
_CRTIMP2 DWORD __cdecl _GetCurrentThreadId();
} // namespace details
class structured_task_group;
class task_group;
/// <summary>
/// The <c>task_handle</c> class represents an individual parallel work item. It encapsulates the instructions and the data required
/// to execute a piece of work.
/// </summary>
/// <typeparam name="_Function">
/// The type of the function object that will be invoked to execute the work represented by the <c>task_handle</c> object.
/// </typeparam>
/// <remarks>
/// <c>task_handle</c> objects can be used in conjunction with a <c>structured_task_group</c> or a more general <c>task_group</c> object,
/// to decompose work into parallel tasks. For more information, see <see cref="Task Parallelism"/>.
/// <para>Note that the creator of a <c>task_handle</c> object is responsible for maintaining the lifetime of the created
/// <c>task_handle</c> object until it is no longer required by the Concurrency Runtime. Typically, this means that the <c>task_handle</c>
/// object must not destruct until either the <c>wait</c> or <c>run_and_wait</c> method of the <c>task_group</c> or
/// <c>structured_task_group</c> to which it is queued has been called.</para>
/// <para><c>task_handle</c> objects are typically used in conjunction with C++ lambdas. Because you do not know the true type of the lambda,
/// the <see cref="make_task Function">make_task</see> function is typically used to create a <c>task_handle</c> object.</para>
/// </remarks>
/// <seealso cref="task_group Class"/>
/// <seealso cref="structured_task_group Class"/>
/// <seealso cref="make_task Function"/>
/// <seealso cref="task_group::run Method"/>
/// <seealso cref="task_group::wait Method"/>
/// <seealso cref="task_group::run_and_wait Method"/>
/// <seealso cref="structured_task_group::run Method"/>
/// <seealso cref="structured_task_group::wait Method"/>
/// <seealso cref="structured_task_group::run_and_wait Method"/>
/**/
template<typename _Function>
class task_handle : public ::Concurrency::details::_UnrealizedChore
{
public:
/// <summary>
/// Constructs a new <c>task_handle</c> object. The work of the task is performed by invoking the function specified as
/// a parameter to the constructor.
/// </summary>
/// <param name="_Func">
/// The function that will be invoked to execute the work represented by the <c>task_handle</c> object. This may be a lambda functor,
/// a pointer to a function, or any object that supports a version of the function call operator with the signature <c>void operator()()</c>.
/// </param>
/**/
task_handle(const _Function& _Func) : _M_function(_Func)
{
m_pFunction = reinterpret_cast <TaskProc> (&::Concurrency::details::_UnrealizedChore::_InvokeBridge<task_handle>);
}
/// <summary>
/// Destroys the <c>task_handle</c> object.
/// </summary>
/**/
~task_handle()
{
//
// We only need to perform a liveness check if the client owns the lifetime of the handle. Doing this for runtime owned handles
// is not only unnecessary -- it is also dangerous.
//
if (_OwningCollection() != NULL && !_GetRuntimeOwnsLifetime())
{
_CheckTaskCollection();
}
}
/// <summary>
/// The function call operator that the runtime invokes to perform the work of the task handle.
/// </summary>
/**/
void operator()() const
{
_M_function();
}
private:
friend class task_group;
friend class structured_task_group;
// The function object invoked to perform the body of the task.
_Function _M_function;
task_handle const & operator=(task_handle const&); // no assignment operator
};
/// <summary>
/// A factory method for creating a <c>task_handle</c> object.
/// </summary>
/// <typeparam name="_Function">
/// The type of the function object that will be invoked to execute the work represented by the <c>task_handle</c> object.
/// </typeparam>
/// <param name="_Func">
/// The function that will be invoked to execute the work represented by the <c>task_handle</c> object. This may be a lambda functor,
/// a pointer to a function, or any object that supports a version of the function call operator with the signature <c>void operator()()</c>.
/// </param>
/// <returns>
/// A <c>task_handle</c> object.
/// </returns>
/// <remarks>
/// This function is useful when you need to create a <c>task_handle</c> object with a lambda expression, because it allows you to
/// create the object without knowing the true type of the lambda functor.
/// </remarks>
/// <seealso cref="task_handle Class"/>
/// <seealso cref="task_group Class"/>
/// <seealso cref="structured_task_group Class"/>
/**/
template <class _Function>
task_handle<_Function> make_task(const _Function& _Func)
{
return task_handle<_Function>(_Func);
}
/// <summary>
/// Describes the execution status of a <c>task_group</c> or <c>structured_task_group</c> object. A value of this type is returned
/// by numerous methods that wait on tasks scheduled to a task group to complete.
/// </summary>
/// <seealso cref="task_group Class"/>
/// <seealso cref="task_group::wait Method"/>
/// <seealso cref="task_group::run_and_wait Method"/>
/// <seealso cref="structured_task_group Class"/>
/// <seealso cref="structured_task_group::wait Method"/>
/// <seealso cref="structured_task_group::run_and_wait Method"/>
/**/
enum task_group_status
{
/// <summary>
/// The tasks queued to the <c>task_group</c> object have not completed. Note that this value is not presently returned by
/// the Concurrency Runtime.
/// </summary>
/**/
not_complete,
/// <summary>
/// The tasks queued to the <c>task_group</c> or <c>structured_task_group</c> object completed successfully.
/// </summary>
/**/
completed,
/// <summary>
/// The <c>task_group</c> or <c>structured_task_group</c> object was canceled. One or more tasks may not have executed.
/// </summary>
/**/
canceled
};
/// <summary>
/// The <c>structured_task_group</c> class represents a highly structured collection of parallel work. You can queue individual parallel tasks to
/// a <c>structured_task_group</c> using <c>task_handle</c> objects, and wait for them to complete, or cancel the task group before they have finished
/// executing, which will abort any tasks that have not begun execution.
/// </summary>
/// <remarks>
/// There are a number of severe restrictions placed on usage of a <c>structured_task_group</c> object in order to gain performance:
/// <list type="bullet">
/// <item>
/// <description>A single <c>structured_task_group</c> object cannot be used by multiple threads. All operations on a <c>structured_task_group</c> object
/// must be performed by the thread that created the object. The two exceptions to this rule are the member functions <c>cancel</c> and
/// <c>is_canceling</c>. The object may not be in the capture list of a lambda expression and be used within a task, unless the task is using one
/// of the cancellation operations.</description>
/// </item>
/// <item>
/// <description>All tasks scheduled to a <c>structured_task_group</c> object are scheduled through the use of <c>task_handle</c> objects which
/// you must explicitly manage the lifetime of.</description>
/// </item>
/// <item>
/// <description>Multiple groups may only be used in absolutely nested order. If two <c>structured_task_group</c> objects are declared, the second
/// one being declared (the inner one) must destruct before any method except <c>cancel</c> or <c>is_canceling</c> is called on the first one
/// (the outer one). This condition holds true in both the case of simply declaring multiple <c>structured_task_group</c> objects within the same
/// or functionally nested scopes as well as the case of a task that was queued to the <c>structured_task_group</c> via the <c>run</c> or
/// <c>run_and_wait</c> methods.</description>
/// </item>
/// <item>
/// <description>Unlike the general <c>task_group</c> class, all states in the <c>structured_task_group</c> class are final. Once you have queued tasks to the
/// group and waited for them to complete, you may not use the same group again.</description>
/// </item>
/// </list>
/// <para>For more information, see <see cref="Task Parallelism"/>.</para>
/// </remarks>
/// <seealso cref="task_group Class"/>
/// <seealso cref="task_handle Class"/>
/**/
class structured_task_group
{
public:
/// <summary>
/// Constructs a new <c>structured_task_group</c> object.
/// </summary>
/// <seealso cref="Task Parallelism"/>
/**/
structured_task_group()
{
}
/// <summary>
/// Destroys a <c>structured_task_group</c> object. You are expected to call either the <c>wait</c> or <c>run_and_wait</c> method on the
/// object prior to the destructor executing, unless the destructor is executing as a result of stack unwinding due to an exception.
/// </summary>
/// <remarks>
/// If the destructor runs as the result of normal execution (e.g.: not stack unwinding due to an exception) and neither the <c>wait</c> nor
/// <c>run_and_wait</c> methods have been called, the destructor may throw a <see cref="missing_wait Class">missing_wait</see> exception.
/// </remarks>
/// <seealso cref="structured_task_group::wait Method"/>
/// <seealso cref="structured_task_group::run_and_wait Method"/>
/**/
~structured_task_group()
{
}
/// <summary>
/// Schedules a task on the <c>structured_task_group</c> object. The caller manages the lifetime of the <c>task_handle</c> object passed
/// in the <paramref name="_Task_handle"/> parameter.
/// </summary>
/// <typeparam name="_Function">
/// The type of the function object that will be invoked to execute the body of the task handle.
/// </typeparam>
/// <param name="_Task_handle">
/// A handle to the work being scheduled. Note that the caller has responsibility for the lifetime of this object. The runtime will
/// continue to expect it to live until either the <c>wait</c> or <c>run_and_wait</c> method has been called on this
/// <c>structured_task_group</c> object.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -