Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A thread pool implementation

0.00/5 (No votes)
25 Apr 2003 1  
A simple thread pool

Introduction

This article is about a re-usable class for thread pooling. It controls the number of threads used to a prescribed level and schedules the requests to jobs to any of the thread in the pool.

Background

While I was writing an application which has many number of threads, I found it difficult to manage a lot of threads. I thought I should limit the number of threads to a certain level and queue the jobs to the threads. So I decided to implement this re-usable thread pooling class.

Using the code

  1. Insert ThreadPool.cpp & ThreadPool.h in project.
  2. Project Settings
    • On the Project menu, Click Settings.
    • In the Project Settings dialog box, click the C/C++ tab.
    • Select Code Generation from the Category drop-down list box.
    • From the Use Run-Time Library drop-down box, select MULTITHREADED.
    • Click OK.
  3. Call Initialize() with required thread count; Default value is 1. Maximum number of threads and tasks can be recommended. The tasks list size will grow if required. Default values are 24 threads and 1024 task information.
  4. Whenever a job is to be assigned, call AssignTask() with a _cdecl function pointer of the client.
  5. Function will be executed from any of the free thread in thread pool.
  6. If DATA members need to be sync, in the submitted function in client, that has to be done by the client.
  7. When thread count need to be increased/decreased, just call Initialize again. NO Resource/Memory LEAK. The current threads finishes execution; then it will be aborted.
  8. To destroy the thread pool, without deleting threadpool object, call UnInitialize(). This will delete all resources. If threads are still working, after WM_QUIT posting and a small waiting, it terminates all threads.
  9. UnInitialize() is also called from destructor.

In the demo application, use the "work" menu to assign sample jobs to thread pool.

/* S A M P L E - C O D E*/
CMyTestView::CMyTestView()
{
    m_Pool.Initialize(10,  /* Required number of threads */ 
                    20,  /* Max threads expected; Default = 24*/ 
                    2000 /* Max tasks expected at a time; Default=1024 */); 
    // Now only 10 thread will be in the pool; 

    // Second param 20 is just for internal memory allocation.

}

void CMyTestView::OnFirstJob() 
{
    THREAD_POOL_TASK taskInfo = {TEST_DO_TASK1, DoFirstJob, LPVOID(this)};
    m_Pool.AssignTask(&taskInfo );
}

// task submitter second

void CMyTestView::OnSecondJob() 
{
    THREAD_POOL_TASK taskInfo = {TEST_DO_TASK2, DoSecondJob, LPVOID(this)};
    m_Pool.AssignTask(&taskInfo );
}

// Thread pool call back. - for first task

bool DoFirstJob(UINT taskId, LPVOID pData)
{
    CMyTestView *pView = (CMyTestView*)pData;
    return pView->DoJob(taskId);
}

// Thread pool call back. - for second task

bool DoSecondJob(UINT taskId, LPVOID pData)
{
    CMyTestView *pView = (CMyTestView*)pData;
    return pView->DoJob(taskId);
}

// Actual execution goes here.

bool CMyTestView::DoJob(UINT taskId)
{
    switch(taskId)
    {
        case TEST_DO_TASK1:
        {
            m_Message = _T("Doing FIRST job");
            Invalidate(0);
            int nCount = 1;
            while (nCount--)
            {
                Sleep(1000);    
                Beep(100, 1000);
            }
        }
        break;
        case TEST_DO_TASK2:
        {
            m_Message = _T("Doing SECOND job");
            Invalidate(0);
            int nCount = 2;
            while (nCount--)
            {
                Sleep(2000);    
                Beep(200, 2000);
            }
        }
    }
    return true;
}

void CMyTestView::OnResetWorkLoad() 
{
    m_Message = _T("On Reset Work Load");
    Invalidate(0);
    m_Pool.Initialize(5,   /* Required number of threads */  
            20,  /* Max threads expected; Default = 24*/ 
            2000 /* Max tasks expected at a time; Default=1024 */);    
    // Now only 5 thread will be in the pool; 

    // Out of previous TEN, FIVE will be removed.

}

Points of Interest

I learned the usefulness of thread pooling. The annoying thing is that global functions are needed for callback functions. I managed it with the help of static functions within the classes.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here