Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C++11

A Simple Worker Thread

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
15 Mar 2016CPOL1 min read 37.6K   928   20   4
A worker thread gives you parallel processing power

Introduction

Sometimes, we need an extra thread to do a task for us in parallel or to just unblock main thread. For better performance, we would not like to create a new thread every time. Also, we need little more control over the thread. In this article, we will implement a thread with the below abilities.

  • You need not define a thread procedure, rather you can submit any function using lambda
  • Implemented purely in C++11, compatible with any OS
  • Submit a task to be executed asynchronously
  • Submit a task to be executed synchronously (but on worker thread)
  • Automatically wait for task to complete
  • Implementation uses C++ 11 extensively (thread, lambda, condition variables)

Using the Code

The below sample code lists usages of worker thread:

C++
#include <iostream>
#include <chrono>
#include <thread>
#include "workerthread.h"

int main()
{
    std::cout << "Hi, Welcome to demo of worker thread" << std::endl;

    {
        // Create two worker threads
        WorkerThread thread;
        WorkerThread thread2;

        // Example of a synchronous task
        thread.doSync([]{    std::cout << "First - blocking call" << std::endl;    });

        for (int i = 1; i < 100; i++)
        {
            auto& t = i % 2 == 0 ? thread : thread2;
            if (i == 10) // Another synchronous task in between
            {
                thread.doSync([]{    
                std::cout << "Second - blocking call" << std::endl;    });
            }
            // Multiple asynchronous tasks queued
            t.doAsync([i]
            {
                std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(200));
                std::cout << (i % 2 == 0 ? "thread-" : "thread2-") 
                << "iteration number: " << i << std::endl;
            });
        }
    
        thread.doSync([]{    std::cout << "Last - blocking call";    });
    }// Added extra scope to demo destruction of worker thread
    std::cout << "This must be last line\n";

}

Implementation of worker thread:

  • Use C++ function construct to store submitted task
  • Finish the present queue and wait for signal for new work
C++
void WorkerThread::startThread()
{
    std::unique_lock<std::mutex> l(mutex);
    do
    {
        while (isRunning && tasks.empty())
            itemInQueue.wait(l);

        while (!tasks.empty())
        {
            auto size = tasks.size();
            printf("Number of pending task are %d\n", size);
            const std::function<void()> t = tasks.front();
            tasks.pop_front();
            l.unlock();
            t();
            l.lock();
        }
        itemInQueue.notify_all();

    } while (isRunning);
    itemInQueue.notify_all();
}

An asynchronous task is just queued and calling thread not blocked:

C++
void WorkerThread::doAsync(const std::function<void()>& t)
{
    std::lock_guard<std::mutex> _(mutex);
    tasks.push_back(t);
    itemInQueue.notify_one();
}

Synchronous task is little trickier, we need to block calling thread until all tasks queued before the submitted task and submitted task completes.

C++
void WorkerThread::doSync(const std::function<void()>& t)
{
    std::condition_variable event;
    bool finished = false;

    std::unique_lock<std::mutex> l(mutex);
    auto lambda = [this, &t, &finished, &event]
    {
        t();
        std::lock_guard<std::mutex> l(mutex);

        finished = true;
        event.notify_one();
    };
    tasks.push_back(lambda);
    itemInQueue.notify_one();

    while (!finished)
        event.wait(l);
}

With minor changes, this class can be used to take priority base task.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
Australia Australia
A developer and a learner. Most of the times in code in C/C++ and C#.
I would like to learn more and more languages.

I have worked in the medical domain and understand DICOM, IHE well.

Comments and Discussions

 
QuestionSuspend/Resume or Stop async thread on demand. Pin
oleg6331-Mar-16 11:38
professionaloleg6331-Mar-16 11:38 
AnswerRe: Suspend/Resume or Stop async thread on demand. Pin
Satbir S28-Apr-16 0:43
professionalSatbir S28-Apr-16 0:43 
QuestionTask that return results? Pin
wilsonsuryajaya17-Mar-16 22:20
wilsonsuryajaya17-Mar-16 22:20 
AnswerRe: Task that return results? Pin
Satbir S19-Mar-16 0:23
professionalSatbir S19-Mar-16 0:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.