/*
* Copyright 2011 Steven Gribble
*
* This file is part of the UW CSE 333 course project sequence
* (333proj).
*
* 333proj is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 333proj is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 333proj. If not, see .
*/
#ifndef _HW3_THREADPOOL_H_
#define _HW3_THREADPOOL_H_
extern "C" {
#include // for the pthread threading/mutex functions
}
#include // for uint32_t, etc.
#include // for std::list
namespace hw3 {
// A ThreadPool is, well, a pool of threads. ;) A ThreadPool is an
// abstraction that allows customers to dispatch tasks to a set of
// worker threads. Tasks are queued, and as a worker thread becomes
// available, it pulls a task off the queue and invokes a function
// pointer in the task to process it. When it is done processing the
// task, the thread returns to the pool to receive and process the next
// available task.
class ThreadPool {
public:
// Construct a new ThreadPool with a certain number of worker
// threads. Arguments:
//
// - num_threads: the number of threads in the pool.
explicit ThreadPool(uint32_t num_threads);
virtual ~ThreadPool();
// This inner class defines what a Task is. A worker thread will
// pull a task off the task queue and invoke the thread_task_fn
// function pointer inside of it, passing it the Task* itself as an
// argument. The thread_task_fn takes ownership of the Task and
// must arrange to delete the task when it is done. Customers will
// probably want to subclass Task to add task-specific fields to it.
class Task;
typedef void (*thread_task_fn)(Task *arg);
class Task {
public:
// "f" is the task function that a worker thread should invoke to
// process the task.
explicit Task(thread_task_fn f) : f_(f) { }
// The dispatch function.
thread_task_fn f_;
};
// Customers use Dispatch() to enqueue a Task for dispatch to a
// worker thread.
void Dispatch(Task *t);
private:
friend void *ThreadLoop(void *tpool);
// A lock and condition variable that worker threads and the
// Dispatch function use to guard the Task queue.
pthread_mutex_t qlock_;
pthread_cond_t qcond_;
// The queue of Tasks waiting to be dispatched to a worker thread.
std::list work_queue_;
// This should be set to "true" when it is time for the worker
// threads to kill themselves, i.e., when the ThreadPool is
// destroyed. A worker thread will check this variable before
// picking up its next piece of work; if it is true, the worker
// threads will kill themselves off.
bool killthreads_;
// This variable stores how many threads are currently running. As
// worker threads are born, they increment it, and as worker threads
// kill themselves, they decrement it.
uint32_t num_threads_running_;
// The pthreads pthread_t structures representing each thread.
pthread_t *thread_array_;
};
} // namespace hw3
#endif // _HW3_THREADPOOL_H_