Windows Thread Pool

Source: Internet
Author: User

 

Call a function Asynchronously

To use a thread pool to execute a function asynchronously, we need to define a function with the following prototype:

VOID CALLBACK SimpleCallback(
  [in, out]            PTP_CALLBACK_INSTANCE Instance,
  [in, out, optional]  PVOID Context
);

Then, in order for a thread in the thread pool to execute this function, we need to submit a request to the thread pool:

BOOL WINAPI TrySubmitThreadpoolCallback(
  __in          PTP_SIMPLE_CALLBACK pfns,
  __in_out_opt  PVOID pv,
  __in_opt      PTP_CALLBACK_ENVIRON pcbe
);

Note that we never call createthread by ourselves. the system will automatically create a default thread pool for our city, and let a thread in the thread pool call our callback function. in addition, when this thread completes processing a client request, it will not be destroyed immediately, but will return to the thread pool, ready to process any other work items in the queue.

Each callTrysubmitthreadpoolcallbackWhen using a function, the system allocates a work item internally in our name. However, in some cases, such as insufficient memory or quota restrictions,TrysubmitthreadpoolcallbackThe call may fail. This is unacceptable when multiple operations need to be coordinated (for example, when a timer needs to be canceled by a work item.

Therefore, we must manually create a work item when setting the Timer:

PTP_WORK WINAPI CreateThreadpoolWork(
  __in          PTP_WORK_CALLBACK pfnwk,
  __in_out_opt  PVOID pv,
  __in_opt      PTP_CALLBACK_ENVIRON pcbe
);

ParametersPfnwkThe following function prototype must be met:

VOID CALLBACK WorkCallback(
  [in, out]            PTP_CALLBACK_INSTANCE Instance,
  [in, out, optional]  PVOID Context,
  [in, out]            PTP_WORK Work
);

When we want to submit a work item to the thread pool, we can call the following function:

VOID WINAPI SubmitThreadpoolWork(
  __in_out      PTP_WORK pwk
);

If we have another thread, the thread wants to cancel the submitted work item, or the thread will suspend itself to wait for the work item to be processed:

VOID WINAPI WaitForThreadpoolWorkCallbacks(
  __in_out      PTP_WORK pwk,
  __in          BOOL fCancelPendingCallbacks
);

If the ParameterFcancelpendingcallbacksTrueWaitforthreadpoolworkcallbacksWill try to cancel the previously submitted work item. If the thread in the thread pool is processing that work itemWaitforthreadpoolworkcallbacksThe function will wait until the work item has been completed before returning. If the submitted work item has not been processed by any thread, the function marks it as canceled and returns immediately. When the finished port extracts the work item from the queue, the thread pool knows that the callback function is not required, so that the work item will not be executed.

If the ParameterFcancelpendingcallbacksIs falseWaitforthreadpoolworkcallbacksThe call thread will be suspended until the specified work item is processed completely, and the thread processing this work item in the thread pool has been withdrawn and is ready to process the next work item.

Note:

1. If you plan to submit a large number of work items, it would be better to create a work item once for performance and memory usage considerations and then submit it multiple times.

2. If a ptr_work object is used to submit multiple work itemsWaitforthreadpoolworkcallbacks
FunctionFcancelpendingcallbacksIs falseWaitforthreadpoolworkcallbacks
The function waits for the thread pool to process all submitted jobs. IfFcancelpendingcallbacksIf this parameter is set to true, only the running work item is completed.

If you do not need a work item, you can call the following function:

VOID WINAPI CloseThreadpoolWait(
  __in_out      PTP_WAIT pwa
);
Call a function at intervals

To schedule a work item to be executed at a certain time, we must define a callback function. The prototype is as follows:

Void callback timeoutcallback (

Tp_callback_instance instance,

Pvoid context,

Ptp_timer ptimer );

Then, call the following function to notify the thread pool when to call our function:

PTP_TIMER WINAPI CreateThreadpoolTimer(
  __in          PTP_TIMER_CALLBACK pfnti,
  __in_out_opt  PVOID pv,
  __in_opt      PTP_CALLBACK_ENVIRON pcbe
);

When we want to register a timer with the thread pool, we should call the following function:

VOID WINAPI SetThreadpoolTimer(
  __in_out      PTP_TIMER pti,
  __in_opt      PFILETIME pftDueTime,
  __in          DWORD msPeriod,
  __in_opt      DWORD msWindowLength
);

ParametersPftduetimeIndicates the time when the callback function should be called for the first time. We can pass a negative value (in a subtle unit) to specify a relative time, which is relative to the time when setthreadpooltimer is called.

-1 indicates immediate start.

To specify an absolute time, we should pass in a positive value, in the unit of 100 nanoseconds.

If you only want the timer to be triggered once, you canMsperiodInput 0 as the parameter.

If you want the thread pool to call our callback function regularlyMsperiodThe parameter passes a positive value (which indicates the number of milliseconds to wait before calling our timercallback again .)

ParametersMswindowlengthIt is used to add randomness to the execution time of the callback function, so that the callback function will addMswindowlengthTriggered between the specified time.

After a timer is set, we can also callSetthreadpooltimerFunctionPTIInput the previously set timer pointer to modify the existing timer.

We can alsoPftduetimePassing null is equivalent to telling the thread pool to stop calling our timercallback function. This is a good way to pause the timer without destroying the timer object.

We can call the following function to determine whether a timer has been set.PftduetimeThe parameter value is not null.

BOOL WINAPI IsThreadpoolTimerSet(
  __in_out      PTP_TIMER pti
);

Finally, we can call the following functions:

VOID WINAPI WaitForThreadpoolTimerCallbacks(
  __in_out      PTP_TIMER pti,
  __in          BOOL fCancelPendingCallbacks
);
VOID WINAPI CloseThreadpoolTimer(
  __in_out      PTP_TIMER pti
);
Calls a function when a kernel object is triggered.

To register a work item and run it when a kernel object is triggered, you must first create a callback function:

VOID CALLBACK WaitCallback(
  [in, out]            PTP_CALLBACK_INSTANCE Instance,
  [in, out, optional]  PVOID Context,
  [in, out]            PTP_WAIT Wait,
  [in]                 TP_WAIT_RESULT WaitResult
);

Then create a thread pool object:

PTP_WAIT WINAPI CreateThreadpoolWait(
  __in          PTP_WAIT_CALLBACK pfnwa,
  __in_out_opt  PVOID pv,
  __in_opt      PTP_CALLBACK_ENVIRON pcbe
);

Bind a kernel object to this thread pool:

VOID WINAPI SetThreadpoolWait(
  __in_out      PTP_WAIT pwa,
  __in_opt      HANDLE h,
  __in_opt      PFILETIME pftTimeout
);

PWAParameter used to identifyCreatethreadpoolwaitReturned object.

HThe parameter is used to identify a kernel object.

PfttimeoutThe parameter indicates the maximum amount of time the thread pool should spend waiting for the kernel object to be triggered. If the value is 0, no waiting is required. If the value is negative, the relative time is required. If the value is positive, the absolute time is required. If the value is null, the infinite waiting duration is required.

When the kernel object is triggered or exceeds the waiting time, a thread in the thread pool will call our waitcallback function.

Note:

Once a thread in the thread pool calls our callback function, the corresponding wait item enters the inactive state. "Inactive" means that if we want the callback function to be called again, we must callSetthreadpoolwait
Function to register a kernel object again.

Call a function when the asynchronous I/O request is complete.

First, you must compile a function that conforms to the following prototype:

Void callback overlappedcompletionroultine (

Ptp_callback_instance pinstance,

Pvoid pvcontext,

Pvoid poverlapped,

Ulong ioresult,

Ulong_ptr numberofbytestransferred,

Ptp_io PIO );

When an I/O operation is completed, this function is called and a pointer pointing to the overlapped structure is obtained, this pointer is passed in when we call readfile or writefile to send an I/O Request (through the poverlapped parameter.

The operation result is passed in through the ioresult parameter. If I/O is successful, this parameter is no_error.

The number of transmitted bytes is passed in through the numberofbytetransferred parameter.

PIO is a pointer to the I/O items in the thread pool.

Create a thread pool I/O object:

PTP_IO WINAPI CreateThreadpoolIo(
  __in          HANDLE fl,
  __in          PTP_WIN32_IO_CALLBACK pfnio,
  __in_out_opt  PVOID pv,
  __in_opt      PTP_CALLBACK_ENVIRON pcbe
);

ParametersFLThis is the file/device handle associated with the I/O completion port in the thread pool (opened by calling the createfile function using the file_flag_overlapped flag ).

After the thread pool I/O object is created, we call the following function to associate the file/device embedded in the I/O entry with the I/O completion port in the thread pool:

VOID WINAPI StartThreadpoolIo(
  __in_out      PTP_IO pio
);

Note:

Before callingReadfileAndWritefileBefore, we must callStartthreadpoolio. If you do not callStartthreadpoolio, Then ourOverlappedcompletionroultineThe callback function will not be called.

If the thread pool stops calling our callback function after an I/O request is sent:

VOID WINAPI CancelThreadpoolIo(
  __in_out      PTP_IO pio
);

If the request is sent,ReadfileAndWritefileIf the call fails, we still have to callCancelthreadpoolio. For example, if the return values of these two functions are false and the return value of getlasterror isError_io_pending.

After the file/device is used, we should call closehandle to disable it and call the following function to remove its association with the thread pool:

VOID WINAPI CloseThreadpoolIo(
  __in_out      PTP_IO pio
);

We can also call the following function to wait for another thread to complete an I/O request to be processed:

VOID WINAPI WaitForThreadpoolIoCallbacks(
  __in_out      PTP_IO pio,
  __in          BOOL fCancelPendingCallbacks
);

If the parameter is passedFcancelpendingcallbacksIf the value is true, our callback function will not be called when the request is complete. This is the same as callingCancelthreadpoolioFunctions have similar functions.

Customize thread pools

Before callingCreatethreadpoolwork, createthreadpoolioWhen we wait for the function, we give the ParameterPtp_callback_environ
If it is set to null, the work item will be added to the default thread pool of the process. The configuration of the default thread pool can well meet the requirements of most applications.

However, sometimes we want to modify the minimum and maximum number of runable threads in the thread pool. At this time, we can call the following function to create a new thread pool:

PTP_POOL WINAPI CreateThreadpool(
  PVOID reserved
);

ParametersReservedIs retained, so we should pass null.

Set the maximum and minimum number of threads in the thread pool:

VOID WINAPI SetThreadpoolThreadMaximum(
  __in_out      PTP_POOL ptpp,
  __in          DWORD cthrdMost
);
BOOL WINAPI SetThreadpoolThreadMinimum(
  __in_out      PTP_POOL ptpp,
  __in          DWORD cthrdMic
);

The minimum number of thread Pools By default is 1 and the maximum number is 500.

When the application no longer needs a custom thread pool:

VOID WINAPI CloseThreadpool(
  __in_out      PTP_POOL ptpp
);

The threads in the thread pool that are currently processing items in the queue will complete their processing and terminate. All items in the queue of the thread pool that have not been processed will be canceled.

Once we create our own thread pool and specify the minimum and maximum number of threads, We can initializeCallback environment ),ThePtp_callback_environThe data structure to which the type parameter points.

The data structure of the thread pool callback environment is defined in winnt. h as follows:

Typedef struct_ Tp_callback_environ{

Tp_version version;

Ptp_pool pool;

Ptp_cleanup_group cleanupgroup;

Ptp_cleanup_group_cancel_callback cleanupgroupcancelcallback;

Pvoid racedll;

Struct _ activation_context * activationcontext;

Ptp_simple_callback finalizationcallback;

Union {

DWORD flags;

Struct {

DWORD longfunction: 1;

Dword private: 31;

} S;

} U;

} Tp_callback_environ, * ptp_callback_environ;

Initialize the above structure:

VOID InitializeThreadpoolEnvironment(
  __out         PTP_CALLBACK_ENVIRON pcbe
);

When we do not need the callback environment of the thread pool:

VOID DestroyThreadpoolEnvironment(
  __in_out      PTP_CALLBACK_ENVIRON pcbe
);

To add a work item to the queue of the thread pool, the callback environment must indicate which thread pool must process the work item:

VOID SetThreadpoolCallbackPool(
  __in_out      PTP_CALLBACK_ENVIRON pcbe,
  __in          PTP_POOL ptpp
);

If we do not call the above functionTp_callback_environThe pool field is always null. When you use this callback environment to add a work item, the work item will be added to the default thread pool.

Call the following function to tell the callback environment that the work item usually takes a long time to process. This will make the thread pool faster to create a thread:

VOID SetThreadpoolCallbackRunsLong(
  __in_out      PTP_CALLBACK_ENVIRON pcbe
);
Proper thread pool destruction: cleanup Group

The life cycle of the default thread pool is the same as that of the process. When the process is terminated, Windows destroys it and is responsible for all cleanup tasks.

We want to clean up the private thread pool we have created.

First, create a cleanup group:

PTP_CLEANUP_GROUP WINAPI CreateThreadpoolCleanupGroup(void);

Then, the cleanup group is associated withTp_callback_environStructure Association

VOID SetThreadpoolCallbackCleanupGroup(
  __in_out      PTP_CALLBACK_ENVIRON pcbe,
  __in          PTP_CLEANUP_GROUP ptpcg,
  __in_opt      PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng
);

IfPfngIf the parameter value is not null, the callback function must conform to the following prototype:

VOID CALLBACK CleanupGroupCancelCallback(
  [in, out, optional]  PVOID ObjectContext,
  [in, out, optional]  PVOID CleanupContext
);

Destroy thread pool:

VOID WINAPI CloseThreadpoolCleanupGroupMembers(
  __in_out      PTP_CLEANUP_GROUP ptpcg,
  __in          BOOL fCancelPendingCallbacks,
  __in_out_opt  PVOID pvCleanupContext
);

1. IfFcancelpendingcallbacksThe parameter is true and is passedSetthreadpoolcallbackcleanupgroupFunction ParametersPfngThe value isCleanupgroupcancelcallback
Function address, so our callback function will be called for every canceled work item.

2. IfFcancelpendingcallbacksIf the parameter is true, all submitted work items that have not been processed are canceled directly. The function will return after all currently running work items are completed ..

ParametersPvcleanupcontextThe context containing each canceled item is returned. Used in the callCleanupgroupcancelcallbackPassed inCleanupcontext
Value.

3. IfFcancelpendingcallbacksIf the parameter is false, the thread pool takes time to process all the remaining items in the queue before returning the data.PvcleanupcontextThe parameter is null.

.

After all work items are canceled or processed, we call the following function to release the resources occupied by the cleaning group:

VOID WINAPI CloseThreadpoolCleanupGroup(
  __in_out      PTP_CLEANUP_GROUP ptpcg
);

Last call:

VOID DestroyThreadpoolEnvironment(
  __in_out      PTP_CALLBACK_ENVIRON pcbe
);
VOID WINAPI CloseThreadpool(
  __in_out      PTP_POOL ptpp
);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.