/* * 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 _HW4_THREADPOOL_H_ #define _HW4_THREADPOOL_H_ extern "C" { #include // for the pthread threading/mutex functions } #include // for uint32_t, etc. #include // for std::list namespace hw4 { // A ThreadPool is, well, a pool of threads. ;) A ThreadPool is an // abstraction that allows customers to dispatch asynchronous 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: // When a thread is born, but before it joins the pool, the newborn // thread will invoke a customer-supplied initialization function. // This initialization function takes a (void *) as an argument and // returns a (void *). The returned (void *) is memorized by the // ThreadPool and passed in to that thread via the Task structure // whenever it the thread is dispatched to do some work. typedef void *(*thread_init_fn)(void *arg); // Construct a new ThreadPool with a certain number of worker // threads. Arguments: // // - num_threads: the number of threads in the pool. // // - f: an initialization function that worker threads invoke // when they are born but before they join the thread pool. // If NULL, "f" is not invoked. // // - v: a (void *) passed as an argument to the initialization // function for each newly born thread. ThreadPool(uint32_t num_threads, thread_init_fn f = NULL, void *v = NULL); ~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_; // "thread_init_return" is the (void *) that the dispatched thread // had returned from its initialization function. For example, if // a worker thread creates a QueryProcessor object during // initialization, it can return a (void *) to that object and // then pick it up here during task dispatch. void *thread_init_return; }; // Customers use Dispatch() to enqueue a Task for dispatch to a // worker thread. void Dispatch(Task *t); // 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_; private: // The pthreads pthread_t structures representing each thread. pthread_t *thread_array_; }; } // namespace hw4 #endif // _HW4_THREADPOOL_H_