I’ve been working lately on my own thread pool implementation, and it works fine( pretty much). The problem is it takes almost all CPU resources.
Please, take a look on my implementation:
ThreadPool.h
#include <vector>
#include <list>
#include <Windows.h>
const int DefaultThreadsNumber = 5;
class thread_pool
{
typedef void ( *Task )( );
void* m_hEvent;
CRITICAL_SECTION m_hExecuteFunc;
CRITICAL_SECTION m_hRunFunc;
std::vector<void*> m_ThreadHandles;
std::list<Task> m_TasksQueue;
int m_nThreadInQueue;
static unsigned __stdcall Run( void* thisParam );
public:
thread_pool( int nMaxThreadNo );
~thread_pool();
void Execute( Task task );
};
ThreadPool.cpp
#include "thread_pool.h"
#include <process.h>
void* g_hTaskFinishedEvent;
thread_pool::thread_pool( int nMaxThreadNo )
{
if ( nMaxThreadNo <= 0 )
nMaxThreadNo = DefaultThreadsNumber;
m_nThreadInQueue = nMaxThreadNo;
for( int i = 0; i < nMaxThreadNo; ++i )
{
m_ThreadHandles.push_back((void*)_beginthreadex(NULL, 0, &Run, (void*)this, 0, 0 ));
}
InitializeCriticalSection( &m_hExecuteFunc );
InitializeCriticalSection( &m_hRunFunc );
}
thread_pool::~thread_pool()
{
for ( std::vector<void*>::iterator it = m_ThreadHandles.begin();
it != m_ThreadHandles.end();
++it )
{
CloseHandle( *it );
}
DeleteCriticalSection( &m_hExecuteFunc );
DeleteCriticalSection( &m_hRunFunc );
}
void thread_pool::Execute( Task task )
{
EnterCriticalSection( &m_hExecuteFunc );
m_TasksQueue.push_back( task );
LeaveCriticalSection( &m_hExecuteFunc );
m_hEvent = CreateEvent(NULL, true, false, NULL);
SetEvent( m_hEvent ); // TODO: what if setEvent will fail???
}
unsigned __stdcall thread_pool::Run(void* thisParam )
{
thread_pool *This = (thread_pool*)thisParam;
while(true)
{
WaitForSingleObject( This->m_hEvent, INFINITE );
while(!This->m_TasksQueue.empty())
{
EnterCriticalSection( &This->m_hExecuteFunc );
if ( !This->m_TasksQueue.empty() )
{
This->m_TasksQueue.front()();
This->m_TasksQueue.pop_front();
g_hTaskFinishedEvent = CreateEvent(NULL, true, false, NULL);
SetEvent( g_hTaskFinishedEvent );
}
LeaveCriticalSection( &This->m_hExecuteFunc );
}
}
return 0;
}
How can it be improved?
Thanks on advance.
In CreateEvent, bManualReset is set to true, but you’re not calling
ResetEventanywhere. Thus, once signalled, the event is remains set forever and WaitForSingleObject returns immediatelly. Make it an auto-reset event, or callResetEventafter all workers are done.