add original source
This commit is contained in:
112
source/listing_9.8.cpp
Normal file
112
source/listing_9.8.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
class thread_pool
|
||||
{
|
||||
typedef function_wrapper task_type;
|
||||
|
||||
std::atomic_bool done;
|
||||
thread_safe_queue<task_type> pool_work_queue;
|
||||
std::vector<std::unique_ptr<work_stealing_queue> > queues;
|
||||
std::vector<std::thread> threads;
|
||||
join_threads joiner;
|
||||
|
||||
static thread_local work_stealing_queue* local_work_queue;
|
||||
static thread_local unsigned my_index;
|
||||
|
||||
void worker_thread(unsigned my_index_)
|
||||
{
|
||||
my_index=my_index_;
|
||||
local_work_queue=queues[my_index].get();
|
||||
while(!done)
|
||||
{
|
||||
run_pending_task();
|
||||
}
|
||||
}
|
||||
|
||||
bool pop_task_from_local_queue(task_type& task)
|
||||
{
|
||||
return local_work_queue && local_work_queue->try_pop(task);
|
||||
}
|
||||
|
||||
bool pop_task_from_pool_queue(task_type& task)
|
||||
{
|
||||
return pool_work_queue.try_pop(task);
|
||||
}
|
||||
|
||||
bool pop_task_from_other_thread_queue(task_type& task)
|
||||
{
|
||||
for(unsigned i=0;i<queues.size();++i)
|
||||
{
|
||||
unsigned const index=(my_index+i+1)%queues.size();
|
||||
if(queues[index]->try_steal(task))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
thread_pool():
|
||||
joiner(threads),done(false)
|
||||
{
|
||||
unsigned const thread_count=std::thread::hardware_concurrency();
|
||||
|
||||
try
|
||||
{
|
||||
for(unsigned i=0;i<thread_count;++i)
|
||||
{
|
||||
queues.push_back(std::unique_ptr<work_stealing_queue>(
|
||||
new work_stealing_queue));
|
||||
threads.push_back(
|
||||
std::thread(&thread_pool::worker_thread,this,i));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
done=true;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
~thread_pool()
|
||||
{
|
||||
done=true;
|
||||
}
|
||||
|
||||
template<typename ResultType>
|
||||
using task_handle=std::unique_future<ResultType>;
|
||||
|
||||
template<typename FunctionType>
|
||||
task_handle<std::result_of<FunctionType()>::type> submit(
|
||||
FunctionType f)
|
||||
{
|
||||
typedef std::result_of<FunctionType()>::type result_type;
|
||||
|
||||
std::packaged_task<result_type()> task(f);
|
||||
task_handle<result_type> res(task.get_future());
|
||||
if(local_work_queue)
|
||||
{
|
||||
local_work_queue->push(std::move(task));
|
||||
}
|
||||
else
|
||||
{
|
||||
pool_work_queue.push(std::move(task));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void run_pending_task()
|
||||
{
|
||||
task_type task;
|
||||
if(pop_task_from_local_queue(task) ||
|
||||
pop_task_from_pool_queue(task) ||
|
||||
pop_task_from_other_thread_queue(task))
|
||||
{
|
||||
task();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user