C ++ thread pool implementation

Source: Internet
Author: User

Multi-threaded programming can significantly improve the program running speed. Because the current operating system is multi-core, a multi-threaded program, because the system kernel is round-robin based on time slice, therefore, the time required for multi-threaded programs to use the system kernel is greatly increased, and the tasks completed are faster.

 

Thread Pool header file:

 

// Define # ifndef CworkQueueH # define CworkQueueH // ----------------------------------------------------------------------------- # include <queue> # include <vcl. h> class CWorkQueue;/** usage principle: implemented through the dowork method of WorkItemBase In the derived class. The thread processing task is created by the create task, these threads keep waiting for event listening in the for loop. Once the data in the task stack triggers the thread to execute the task. ** // * Worker WorkItemBasethis is the basic WorkItem that the Work Queue Use its interfaceThis class shocould be inherited and these virtual abstract functionsimplemented. doWork () virtual abstract function is the function that is called when thework item turn has came to be poped out of the queue and be processed. abort () This function is c Alled, when the Destroy function is called, for each of the WorkItemsThat are left in the queue. optional */class WorkItemBase {virtual void DoWork (void * pThreadContext) = 0; virtual void Abort () = 0; friend CWorkQueue;}; typedef std :: queue <WorkItemBase *> WorkItemQueue, * PWorkItemQueue ;/*----------------------------------------------------- ----------------- CWorkQueueThis is the WorkOueue class also known as thread pool, the basic idea of this class is creating thread that are waiting on a queueof work item when the queue is inserted with items the threads wake up andperform the requered work and go to sleep again. ------------------------------------------------------------------------ */class CWorkQueue {public: virtual ~ CWorkQueue () {}; bool Create (const unsigned int nNumberOfThreads, void ** pThreadDataArray = NULL); bool InsertWorkItem (WorkItemBase * pWorkItem); void Destroy (int iWairSecond ); int GetThreadTotalNum (); private: static unsigned long _ stdcall ThreadFunc (void * pParam); WorkItemBase * RemoveWorkItem (); int trim (); enum {ABORT_EVENT_INDEX = 0, SEMAPHORE_INDEX, callback,}; // The applied thread PHANDLE m_phThreads; unsigned int callback; void * m_pThreadDataArray; HANDLE callback [callback]; CRITICAL_SECTION m_CriticalSection; PWorkItemQueue m_pWorkItemQueue;}; # endif

CPP implementation

// ----------------------------------------------------------------------------- # Pragma hdrstop # include "CworkQueue. h "// ------------------------------------------------------------------------------- # include <assert. h> typedef struct _ THREAD_CONTEXT {CWorkQueue * pWorkQueue; void * pThreadData;} THREAD_CONTEXT, * PTHREAD_CONTEXT;/* define create multi-thread nNum BerOfThreads multithreading number ThreadData the parameter executor */bool CWorkQueue for thread function execution: Create (const unsigned int nNumberOfThreads, void ** ThreadData/* = NULL */) {// create a task queue to store the subsequent tasks m_pWorkItemQueue = new WorkItemQueue (); if (NULL = m_pWorkItemQueue) {return false ;} // m_phSincObjectsArray saves the semaphores and events of the thread pool. // m_phSincObjectsArray [ABORT_EVENT_INDEX] Stores events. It is used when the user sets the exit event // M_phSincObjectsArray [SEMAPHORE_INDEX] saves semaphores. When you set the task to be executed, use // create semaphores for multithread synchronization.)/* We define two operations on semaphores: Wait waiting) and Release ). When a thread calls the Wait operation, it either gets the resource and then reduces the semaphore by one, or waits until it is placed in the blocking Queue) until the semaphore is greater than or equal to a moment. Release) is actually the addition operation on the semaphore */m_phSincObjectsArray [SEMAPHORE_INDEX] = CreateSemaphore (NULL, 0, LONG_MAX, NULL); if (m_phSincObjectsArray [SEMAPHORE_INDEX] = NULL) {delete m_pWorkItemQueue; m_pWorkItemQueue = NULL; return false;} // The creation event is set to manual, and only one entry can be made at a time. False indicates that the operation is not in the running state and is not used for multi-thread synchronization) m_phSincObjectsArray [ABORT_EVENT_INDEX] = CreateEvent (NULL, TRUE, FALSE, NULL); if (m_phSincObjectsArray [ABORT_EVENT_INDEX] = NULL) {delete m_pWork ItemQueue; m_pWorkItemQueue = NULL; CloseHandle (m_phSincObjectsArray [SEMAPHORE_INDEX]); return false;} // InitializeCriticalSection (& m_CriticalSection ); // create a thread array m_phThreads = new HANDLE [nNumberOfThreads]; if (m_phThreads = NULL) {delete m_pWorkItemQueue; m_pWorkItemQueue = NULL; CloseHandle (handler [SEMAPHORE_INDEX]); closeHandle (m_phSincObjectsArray [ABORT_EVENT_INDEX]); DeleteC RiticalSection (& m_CriticalSection); return false;} unsigned int I; blocks = nNumberOfThreads; DWORD dwThreadId; PTHREAD_CONTEXT pThreadsContext; // create all threads for (I = 0; I <nNumberOfThreads; I ++) {// The parameter pThreadsContext = new THREAD_CONTEXT; pThreadsContext-> pWorkQueue = this; pThreadsContext-> pThreadData = ThreadData = NULL? NULL: ThreadData [I]; // creation thread m_phThreads [I] = CreateThread (NULL, 0, CWorkQueue: ThreadFunc, pThreadsContext, 0, & dwThreadId ); if (m_phThreads [I] = NULL) {delete pThreadsContext; m_nNumberOfThreads = I; Destroy (5); return false ;}} return true ;} /* The worker adds the task execution class to the task queue by inheriting the basic class WorkItemBase and then using the multi-state function DoWork to complete the real task ------------------------------------------- ----------------------------- */Bool CWorkQueue: InsertWorkItem (WorkItemBase * pWorkItem) {assert (pWorkItem! = NULL); // multi-thread mutex access, entering the critical section EnterCriticalSection (& m_CriticalSection); // Insert the task into the queue m_pWorkItemQueue-> push (pWorkItem ); // leave the critical section LeaveCriticalSection (& m_CriticalSection); // release the semaphores so that the semaphores increase by 1, prompting the subsequent Wailt operations to execute if (! ReleaseSemaphore (m_phSincObjectsArray [SEMAPHORE_INDEX], 1, NULL) {assert (false); return false;} return true;}/* remove objects from the work queue, and return the removed objects worker */WorkItemBase * CWorkQueue: RemoveWorkItem () {WorkItemBase * pWorkItem; // multi-thread access mutex, entering the critical section EnterCriticalSection (& m_CriticalSection); // remove the pair Like pWorkItem = m_pWorkItemQueue-> front (); m_pWorkItemQueue-> pop (); // leave the critical section. Other waiting threads can enter the critical section LeaveCriticalSection (& m_CriticalSection); assert (pWorkItem! = NULL); return pWorkItem;}/* functions executed by the worker thread. The actual execution is the DoWork () Worker */unsigned long _ stdcall CWorkQueue in the task queue :: threadFunc (void * pParam) {// The parameter PTHREAD_CONTEXT pThreadContext = (PTHREAD_CONTEXT) pParam passed in when the thread is created; WorkItemBase * pWorkItem = NULL; CWorkQueue * pWorkQueue = pThreadCont Ext-> pWorkQueue; void * pThreadData = pThreadContext-> pThreadData; DWORD dwWaitResult; (;;) {// WaitForMultipleObjects wait for pWorkQueue-> m_phSincObjectsArray semaphore array two tasks // One is the release semaphore of the execution task, one is the abnormal release semaphore // when WaitForMultipleObjects waits for Multiple kernel objects, if its bWaitAll parameter is set to false. // The return value minus WAIT_OBJECT_0 is the serial number of the lpHandles array. If multiple kernel objects are triggered at the same time, // This function returns only the one with the smallest sequence number. If this parameter is set to TRUE, the system waits until all semaphores are executed. // FALSE: execute the following command when one of the semaphores is valid) // This document describes the WaitForMultipleObjects semaphores waiting for the task to be executed and the events that exit the task information destruction. // when a new task is added to the task queue, set the semaphores for the task to be executed, trigger task execution // destroy the task information when the exit event is set. Because no event reset information is set for all threads, dwWaitResult = WaitForMultipleObjects (NUMBER_OF_SYNC_OBJ, pWorkQueue-> m_phSincObjectsArray, FALSE, INFINITE); // WaitForMultipleObjects returns the array pWorkQueue-> m_phSincObjectsArray Number switch (dwWaitResult-WAIT_OBJECT_0) {// returns the exception number case ABORT_EVENT_INDEX: delete pThreadCont Ext; return 0; // return the execution task number case SEMAPHORE_INDEX: // obtain a task from the task queue to execute pWorkItem = pWorkQueue-> RemoveWorkItem (); if (pWorkItem = NULL) {assert (false); break;} // execute the real task pWorkItem-> DoWork (pThreadData); break; default: assert (false); delete pThreadContext; return 0 ;}} // delete the thread parameter delete pThreadContext; return 1;}/** get the total number of threads **/int CWorkQueue: GetThreadTotalNum () {return m_nNumberOfThreads ;} /** get the task pool size **/int CWorkQueue: GetWorekQueu ESize () {// The access between multiple threads is mutually exclusive and enters the EnterCriticalSection (& m_CriticalSection); int iWorkQueueSize = m_pWorkItemQueue-> size (); // exit the critical partition (& m_CriticalSection ); return iWorkQueueSize;}/* Destroy thread pool queue */void CWorkQueue: Destroy (int iWairSecond) {// to prevent subthread tasks from being completed, The main thread destroys the thread pool and adds a waiting function while (0! = GetWorekQueueSize () {// The main thread waits for the thread pool to complete all tasks Sleep (iWairSecond * 1000);} // sets the exit event. All threads do not set event reset information, therefore, if (! SetEvent (m_phSincObjectsArray [ABORT_EVENT_INDEX]) {assert (false); return;} // wait for all the threads to endWaitForMultipleObjects (m_nNumberOfThreads, m_phThreads, true, INFINITE ); // clean queuewhile (! M_pWorkItemQueue-> empty () {m_pWorkItemQueue-> front ()-> Abort (); m_pWorkItemQueue-> pop ();} delete m_pWorkItemQueue; m_pWorkItemQueue = NULL; closeHandle (response [SEMAPHORE_INDEX]); CloseHandle (response [ABORT_EVENT_INDEX]); DeleteCriticalSection (& m_CriticalSection); // close all threads handlesfor (int I = 0; I <response; I ++) CloseHandle (m_phThreads [I]); delete [] m_phThreads;} # pragma package (smart_init)

 

 

Usage:

// ----------------------------------------------------------------------------- # Ifndef CworkItemH # define CworkItemH # include "CworkQueue. h "# include" OprateEXCEL. h "// define class CworkItem: public WorkItemBase {public: void DoWork (void * pThreadContext); void Abort (); void SetWriteContent (const vTExcelSheetDate & tvTExcelSheetDate ); void SetExcelPath (const String & ExcelPath); private: // vTExcelSheetDate m_vTExcelSheetDate; // The Path to the Excel file String m_ExcelPath ;}; # endif // ----------------------------------------------------------------------------- # pragma hdrstop # include "CworkItem. h "// users "//---------------------------------------------------------------------------/********************************** **************************************** * *** function: save the Excel writing content ************************************ *** Author: time: 2013.6.30 *************************************** **************************************** */void CworkItem:: SetWriteContent (const vTExcelSheetDate & tvTExcelSheetDate) {m_vTExcelSheetDate.clear (); vTExcelSheetDate (). swap (m_vTExcelSheetDate); m_vTExcelSheetDate = tvTExcelSheetDate ;} /*************************************** * ************************************ Function function: save the Excel save path ************************************ *** Author: time: 2013.6.30 *************************************** **************************************** */void CworkItem:: SetExcelPath (const String & ExcelPath) {m_ExcelPath = ExcelPath ;} /*************************************** * ************************************ Function function: how to Implement the base class ********************************** * *****: time: 2013.6.30 *************************************** **************************************** */void CworkItem:: DoWork (void * pThreadContext) {OperateExcel taOperateExcel; String sError; taOperateExcel. writeDateToExcel (m_ExcelPath, m_vTExcelSheetDate, sError); // after the work is completed, delete this;} void CworkItem: Abort () {delete this ;}

 

 

 

CworkItem * pCworkItem = new CworkItem (); pCworkItem-> SetWriteContent (tvTExcelSheetDate); pCworkItem-> SetExcelPath (sFilePath); worker (pCworkItem); pCworkItem = new CworkItem (); pCworkItem-> SetWriteContent (tvTExcelSheetDate); sFilePath = "F: \ Project \ multi-threaded write excel \ song1.xls"; pCworkItem-> SetExcelPath (sFilePath); cancel (pCworkItem ); m_CWorkQueue.Destroy (5 );

 

This article is from the "Feng qing yang song" blog, please be sure to keep this source http://2309998.blog.51cto.com/2299998/1264085

Related Article

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.