HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Platform independant thread pool

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
platformpoolthreadindependant

Problem

v2 of this question is here and v3 is here

To get a better understanding of C++11/C++14, I thought I would develop a thread pool, even if it has been done to death!

The only dependency outside of the standard library is boost::lockfree::queue.

threadpool.hpp

```
#ifndef THREADPOOL_H
#define THREADPOOL_H

#include
#include
#include
#include
#include

#include

class threadpool
{
public:
// constructors
//
// calls threadpool(size_t concurrency) with:
//
// concurrency - std::thread::hardware_concurrency()
threadpool();
// calls threadpool(size_t concurrency, size_t queue_size) with:
//
// concurrency - concurrency
// queue_size - 128, arbitary value, should be sufficient for most
// use cases.
threadpool(size_t concurrency);
// creates a threadpool with a specific number of threads and
// a maximum number of queued tasks.
//
// Argument
// concurrency - the guaranteed number of threads used in the
// threadpool, ie. maximum number of tasks worked
// on concurrently.
// queue_size - the maximum number of tasks that can be queued
// for completion, currently running tasks do not
// count towards this total.
threadpool(size_t concurrency, size_t queue_size);

// destructor
//
// Will complete any currently running task as normal, then
// signal to any other tasks that they were not able to run
// through a std::runtime_error exception
~threadpool();

threadpool(const threadpool &) = delete;
threadpool(threadpool &&) = delete;

threadpool & operator=(const threadpool &) = delete;
threadpool & operator=(threadpool &&) = delete;

// run
//
// Runs the given function on one of the thread pool
// threads in First In First Out (FIFO) order
//
// Argument
// task -

Solution

This does not really stop them spinning:

// rather than spinning, give up thread time to other things
std::this_thread::yield();


It may give up the core for another thread (temporarily). But it will come back just as quickly to check for more work. So I am not convinced this actually buys you anything.

I would use a condition variable and block threads on it while there is no work. Then you know they are not taking up any cycles when there is no work.

When creating the work package.

package->task = task;


I would forward the task (remember that named variables can not activate move semantics).

package->task = std::forward>(task);

Code Snippets

// rather than spinning, give up thread time to other things
std::this_thread::yield();
package->task = task;
package->task = std::forward<std::function<void()>>(task);

Context

StackExchange Code Review Q#54858, answer score: 4

Revisions (0)

No revisions yet.