In this homework, you will implement a naive thread pool. A thread pool is a very common design, aims to reuse threads to avoid the overhead of creating and destroying threads.
Download the starter code here.
Before start working with pthread
, we must first learn a data structure named ringbuffer
.
A ringbuffer is a circular queue with a fixed maximum size. See ringbuffer.h
ringbuffer_t *ringbuffer_create(size_t size);
size
and return the pointer of ringbuffer created.void ringbuffer_destroy(ringbuffer_t *ringbuffer);
ringbuffer
. Release all the memory allocated.
bool ringbuffer_is_empty(ringbuffer_t *ringbuffer);
true
if the ringbuffer ringbuffer
is empty, otherwise return false
.
bool ringbuffer_is_full(ringbuffer_t *ringbuffer);
true
if the ringbuffer ringbuffer
is full, otherwise return false
.
bool ringbuffer_push(ringbuffer_t *ringbuffer, threadpool_task_t value);
value
into the ringbuffer ringbuffer
.true
if the push is successful, otherwise return false
.
bool ringbuffer_pop(ringbuffer_t *ringbuffer, threadpool_task_t *value);
ringbuffer
and store it in value
.true
if the operation is successful, otherwise return false
.
Now we are ready to implement the threadpool. See threadpool.h
We harness ringbuffer to store tasks added with threadpool_add_task
.
Instead of directly initiate task functions, which cause thread creation overhead for every task, we run a worker function (static void *threadpool_thread(void *threadpool);
) as a
thread,
it remains idle until destroyed by signals or fetch a new task.
threadpool_t *threadpool_create(size_t thread_count, size_t queue_size, bool sync);
thread_count
threads and a ringbuffer with size queue_size
.bool threadpool_destroy(threadpool_t *threadpool);
threadpool
. Release all the memory allocated.sync == true
when the threadpool was created, wait until all tasks are finished.true
if the threadpool is successfully destroyed, otherwise return false
.
bool threadpool_add_task(threadpool_t *pool, void (*func)(void *), void *args);
func
and argument args
into the threadpool pool
.true
if the task is successfully added, otherwise return false
.false
if the threadpool is full.
Simply run make submit
, and submit the tarball named hw6_threadpool.tar
generated to autolab.
They might be a little intimidating, but rather helpful for debugging!
One possible solution:
ringbuffer.c | 18 ++++--------------
threadpool.c | 42 +++++++++++++-----------------------------
2 files changed, 17 insertions(+), 43 deletions(-)
Note that there are lots of TODO
s in the code, which is the cause of most of the deletion.
You can generate your own statistics by running diff -uN template answer | diffstat
, where template
and answer
are the directories of template given and your answer respectively.