Win32 Thread Pool code (winapi/c++)
Robust, efficient, easy to use, easy to expand, can be used with any C + + compiler
Description, this code I used for a long time, I deleted the automatic sizing code (because he is not mature)
/******************************************************************
* Thread Pool for Win32
* VC + + 6, bc++ 5.5 (free), GCC (free)
* update:2004.6.9 Llbird [email protected]
Use:
1):
void ThreadFunc (void *p)
{
//...
}
ThreadPool TP;
for (i=0; i<100; i++)
Tp. Call (ThreadFunc);
ThreadPool TP (20);//20 is the initial thread pool size
Tp. Call (ThreadFunc, Lppara);
Tp. Adjustsize (50);//Increase 50
Tp. Adjustsize (-30);//Decrease by 30
2):
Class Mythreadjob:public Threadjob//Thread object extended from Threadjob
{
Public
virtual void dojob (void *p)//Custom virtual function
{
//....
}
};
Mythreadjob MT[10];
ThreadPool TP;
for (i=0; i<100 i++)
Tp. Call (Mt + i);//tp. Call (Mt + I, para);
*******************************************************************/
#ifndef _threadpool_h_
#define _threadpool_h_
#pragma warning (disable:4530)
#pragma warning (disable:4786)
#include <cassert>
#include <vector>
#include <queue>
#include <windows.h>
Class Threadjob//working base classes
{
Public
virtual function for thread pool invocation
virtual void dojob (void *ppara) = 0;
};
Class ThreadPool
{
Public
Dwnum Thread pool Size
ThreadPool (DWORD dwnum = 4): _lthreadnum (0), _lrunningnum (0)
{
InitializeCriticalSection (&_csthreadvector);
InitializeCriticalSection (&_csworkqueue);
_eventcomplete = CreateEvent (0, False, False, NULL);
_eventend = CreateEvent (0, True, false, NULL);
_semaphorecall = CreateSemaphore (0, 0, 0x7FFFFFFF, NULL);
_semaphoredel = CreateSemaphore (0, 0, 0x7FFFFFFF, NULL);
ASSERT (_semaphorecall! = INVALID_HANDLE_VALUE);
ASSERT (_eventcomplete! = INVALID_HANDLE_VALUE);
ASSERT (_eventend! = INVALID_HANDLE_VALUE);
ASSERT (_semaphoredel! = INVALID_HANDLE_VALUE);
Adjustsize (dwnum <= 0 4:dwnum);
}
~threadpool ()
{
DeleteCriticalSection (&_csworkqueue);
CloseHandle (_eventend);
CloseHandle (_eventcomplete);
CloseHandle (_semaphorecall);
CloseHandle (_semaphoredel);
Vector<threaditem*>::iterator ITER;
for (iter = _threadvector.begin (); ITER! = _threadvector.end (); iter++)
{
if (*iter)
Delete *iter;
}
DeleteCriticalSection (&_csthreadvector);
}
Adjust thread pool Size
int adjustsize (int iNum)
{
if (INum > 0)
{
Threaditem *pnew;
EnterCriticalSection (&_csthreadvector);
for (int _i=0; _i<inum; _i++)
{
_threadvector.push_back (pnew = new Threaditem (this));
ASSERT (Pnew);
Pnew->_handle = CreateThread (NULL, 0, Defaultjobproc, pnew, 0, NULL);
ASSERT (Pnew->_handle);
}
LeaveCriticalSection (&_csthreadvector);
}
Else
{
INum *=-1;
ReleaseSemaphore (_semaphoredel, INum > _lthreadnum _lthreadnum:inum, NULL);
}
return (int) _lthreadnum;
}
Call Thread pool
void Call (void (*PFUNC) (void *), void *ppara = NULL)
{
ASSERT (PFunc);
EnterCriticalSection (&_csworkqueue);
_jobqueue.push (New Jobitem (PFunc, Ppara));
LeaveCriticalSection (&_csworkqueue);
ReleaseSemaphore (_semaphorecall, 1, NULL);
}
Call Thread pool
inline void Call (Threadjob * p, void *ppara = NULL)
{
Call (Callproc, New Callprocpara (P, Ppara));
}
End the thread pool and wait synchronously
BOOL Endandwait (DWORD dwwaittime = INFINITE)
{
SetEvent (_eventend);
Return WaitForSingleObject (_eventcomplete, dwwaittime) = = Wait_object_0;
}
End thread Pool
inline void End ()
{
SetEvent (_eventend);
}
Inline DWORD Size ()
{
Return (DWORD) _lthreadnum;
}
Inline DWORD getrunningsize ()
{
Return (DWORD) _lrunningnum;
}
BOOL IsRunning ()
{
return _lrunningnum > 0;
}
Protected
Worker threads
Static DWORD WINAPI Defaultjobproc (lpvoid lpparameter = NULL)
{
Threaditem *pthread = static_cast<threaditem*> (Lpparameter);
ASSERT (PThread);
ThreadPool *pthreadpoolobj = pthread->_pthis;
ASSERT (Pthreadpoolobj);
InterlockedIncrement (&pthreadpoolobj->_lthreadnum);
HANDLE Hwaithandle[3];
Hwaithandle[0] = pthreadpoolobj->_semaphorecall;
HWAITHANDLE[1] = pthreadpoolobj->_semaphoredel;
HWAITHANDLE[2] = pthreadpoolobj->_eventend;
Jobitem *pjob;
BOOL Fhasjob;
for (;;)
{
DWORD WR = WaitForMultipleObjects (3, Hwaithandle, False, INFINITE);
Responding to deleting a thread signal
if (WR = = wait_object_0 + 1)
Break
Get user jobs from the queue
EnterCriticalSection (&pthreadpoolobj->_csworkqueue);
if (Fhasjob =!pthreadpoolobj->_jobqueue.empty ())
{
Pjob = Pthreadpoolobj->_jobqueue.front ();
Pthreadpoolobj->_jobqueue.pop ();
ASSERT (Pjob);
}
LeaveCriticalSection (&pthreadpoolobj->_csworkqueue);
Be signaled by the end thread to determine whether to end the thread (end thread signal && whether there is still work)
if (WR = = Wait_object_0 + 2 &&!fhasjob)
Break
if (fhasjob && pjob)
{
InterlockedIncrement (&pthreadpoolobj->_lrunningnum);
Pthread->_dwlastbegintime = GetTickCount ();
pthread->_dwcount++;
Pthread->_fisrunning = true;
Pjob->_pfunc (Pjob->_ppara); Run User jobs
Delete Pjob;
Pthread->_fisrunning = false;
InterlockedDecrement (&pthreadpoolobj->_lrunningnum);
}
}
Delete Self structure
EnterCriticalSection (&pthreadpoolobj->_csthreadvector);
Pthreadpoolobj->_threadvector.erase (Find (Pthreadpoolobj->_threadvector.begin (), pThreadPoolObj->_ Threadvector.end (), pThread));
LeaveCriticalSection (&pthreadpoolobj->_csthreadvector);
Delete PThread;
InterlockedDecrement (&pthreadpoolobj->_lthreadnum);
if (!pthreadpoolobj->_lthreadnum)//end of all threads
SetEvent (Pthreadpoolobj->_eventcomplete);
return 0;
}
Calling the User object virtual function
static void Callproc (void *ppara)
{
Callprocpara *CP = Static_cast<callprocpara *> (Ppara);
ASSERT (CP);
if (CP)
{
Cp->_pobj->dojob (Cp->_ppara);
Delete cp;
}
}
User Object structure
struct Callprocpara
{
threadjob* _pobj;//User Objects
void *_ppara;//User Parameters
Callprocpara (threadjob* p, void *ppara): _pobj (P), _ppara (Ppara) {};
};
User function structure
struct Jobitem
{
void (*_pfunc) (void *);//function
void *_ppara; Parameters
Jobitem (void (*PFUNC) (void *) = null, void *ppara = null): _pfunc (PFunc), _ppara (Ppara) {};
};
Thread structure in a thread pool
struct Threaditem
{
HANDLE _handle; Thread handle
ThreadPool *_pthis; Pointer to the thread pool
DWORD _dwlastbegintime; Last Run Start time
DWORD _dwcount; Number of runs
BOOL _fisrunning;
Threaditem (ThreadPool *pthis): _pthis (pthis), _handle (NULL), _dwlastbegintime (0), _dwcount (0), _fisrunning (false) {};
~threaditem ()
{
if (_handle)
{
CloseHandle (_handle);
_handle = NULL;
}
}
};
Std::queue<jobitem *> _jobqueue; Work queue
Std::vector<threaditem *> _threadvector; Thread data
critical_section _csthreadvector, _csworkqueue; Work queue criticality, thread data criticality
HANDLE _eventend, _eventcomplete, _semaphorecall, _semaphoredel;//end notification, complete event, work signal, delete thread signal
Long _lthreadnum, _lrunningnum; Number of threads, number of threads running
};
#endif//_threadpool_h_
Win32 Thread Pool code (winapi/c++)