intrigued_66
intrigued_66

Reputation: 17258

C++ Windows Thread pool (non-boost/c++11)

Is there any way to create a threadpool only using C++ or Windows C++ functions? I dont have access to boost or any libraries (I can access code project but couldnt find anything non-unix) and I am finding it hard to find a way to implement a threadpool.

I am using VS2010 which doesnt support the C++11 threading yet, hence why I'm a little stuck!

Upvotes: 3

Views: 4806

Answers (4)

Martin James
Martin James

Reputation: 24887

It's fairly easy. You need some classes:

Task class with a 'run' method - something for the pool user to override to build up their own tasks.

A producer-consumer objectQueue for the threads to wait on for work. If you have std::deque, that's fairly easy. If not, you'll have to code up your own queue type. As well as the queue class, you need othe synchro stuff, maybe a CriticalSection/Mutex to protect the queue and a semaphore for the threads to wait on.

A threadPool class - something that contains the P-C queue, submit(TaskClass aTask) method and other stuff.

A pile of threads created in the threadPool ctor - use CreateThread and pass the threadPool instance as the lpParam parameter so that the threads can cast it back again to gain access to the threadPool.

The threads wait on the threadPool->objectQueue for work, eg:

// header

class threadPool;

class task {
friend class threadPool;
private:
      threadPool *myPool;
public:
      virtual void run()=0;
};


class PCSqueue{
private:
    CRITICAL_SECTION access;
    deque<task*> *objectQueue;
    HANDLE queueSema;
public:
    PCSqueue();
    void push(task *ref);
    bool pop(task **ref,DWORD timeout);
};

class threadPool {
private:
    int threadCount;
public:
    PCSqueue *queue;
    threadPool(int initThreads);
    static DWORD _stdcall staticThreadRun(void *param){
        threadPool *myPool=(threadPool *)param;
        task *thisTask;
        while (myPool->queue->pop(&thisTask,INFINITE)){
            thisTask->run();
        }
    }
    void submit(task *aTask);
};

// cpp

PCSqueue::PCSqueue(){
    objectQueue=new deque<task*>;
    InitializeCriticalSection(&access);
    queueSema=CreateSemaphore(NULL,0,MAXINT,NULL);
};

void PCSqueue::push(task *ref){
    EnterCriticalSection(&access);
    objectQueue->push_front(ref);
    LeaveCriticalSection(&access);
    ReleaseSemaphore(queueSema,1,NULL);
};

bool PCSqueue::pop(task **ref,DWORD timeout){
    if (WAIT_OBJECT_0==WaitForSingleObject(queueSema,timeout)) {
        EnterCriticalSection(&access);
        *ref=objectQueue->back();
        objectQueue->pop_back();
        LeaveCriticalSection(&access);
        return(true);
    }
    else
        return(false);
};

threadPool::threadPool(int initThreads){
    queue=new PCSqueue();
    for(threadCount=0;threadCount!=initThreads;threadCount++){
        CreateThread(NULL,0,staticThreadRun,this,0,0);
    };
};

void threadPool::submit(task *aTask){
  aTask->myPool=this;
  queue->push(aTask);
};

Upvotes: 4

BertR
BertR

Reputation: 1697

In case your target is Windows Vista or later you can use this thread pool: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686980%28v=vs.85%29.aspx

The page also has a example in C++.

Upvotes: 4

Lubo Antonov
Lubo Antonov

Reputation: 2318

There is an API for managing thread pools, here is a link: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686766(v=vs.85).aspx. You might want to find a library that wraps it, though, as it is complicated.

Upvotes: 1

Related Questions