From 6923dc7fbaddf392375973fd5d7327ae1e83bedc Mon Sep 17 00:00:00 2001 From: Weicheng Date: Sat, 31 Aug 2024 18:47:02 +0800 Subject: [PATCH] Implement a pool using `pthread_mutex_t`. --- programming/csapp/labs/proxy/pool.c | 60 +++++++++++++++++++++++++++++ programming/csapp/labs/proxy/pool.h | 18 +++++++++ 2 files changed, 78 insertions(+) create mode 100644 programming/csapp/labs/proxy/pool.c create mode 100644 programming/csapp/labs/proxy/pool.h diff --git a/programming/csapp/labs/proxy/pool.c b/programming/csapp/labs/proxy/pool.c new file mode 100644 index 0000000..a1f6c0d --- /dev/null +++ b/programming/csapp/labs/proxy/pool.c @@ -0,0 +1,60 @@ +#include "csapp.h" +#include "pool.h" + +#include + +// For non-static initialization. +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_mutex_t *_mutex; // should be guarded by a mutex, too +void mutex_init() { + pthread_mutex_init(_mutex, NULL); +} + +struct _pool { + /* a FIFO queue */ + int *buf; /* Buffer array */ + int n; /* Maximum number of slots */ + int front; /* buf[(front+1)%n] is first item */ + int rear; /* buf[rear%n] is last item */ + /* queue and counting semaphores */ + pthread_mutex_t queue; /* Protects accesses to the queue. */ + sem_t slots; /* Counts available slots. */ + sem_t items; /* Counts available items. */ +}; + +/* Create an empty, bounded, shared FIFO buffer with n slots */ +void pool_init(pool_t *p, int n) { + p->buf = Calloc(n, sizeof(int)); + p->n = n; /* Buffer holds max of n items */ + p->front = p->rear = 0; /* Empty buffer iff front == rear */ + _mutex = &p->queue; + pthread_once(&once, mutex_init); + Sem_init(&p->slots, 0, n); /* Initially, buf has n empty slots */ + Sem_init(&p->items, 0, 0); /* Initially, buf has zero data items */ +} + +/* Clean up buffer p */ +void pool_deinit(pool_t *p) { + Free(p->buf); + pthread_mutex_destroy(&p->queue); +} + +/* Insert item onto the rear of shared buffer p */ +void pool_insert(pool_t *p, int item) { + P(&p->slots); /* Wait for available slot */ + pthread_mutex_lock(&p->queue); /* Lock the buffer */ + p->buf[(++p->rear)%(p->n)] = item; /* Insert the item */ + pthread_mutex_unlock(&p->queue); /* Unlock the buffer */ + V(&p->items); /* Announce available item */ +} + +/* Remove and return the first item from buffer p */ +int pool_remove(pool_t *p) { + int item; + P(&p->items); /* Wait for available item */ + pthread_mutex_lock(&p->queue); /* Lock the buffer */ + item = p->buf[(++p->front)%(p->n)]; /* Remove the item */ + pthread_mutex_unlock(&p->queue); /* Unlock the buffer */ + V(&p->slots); /* Announce available slot */ + return item; +} diff --git a/programming/csapp/labs/proxy/pool.h b/programming/csapp/labs/proxy/pool.h new file mode 100644 index 0000000..326bbf9 --- /dev/null +++ b/programming/csapp/labs/proxy/pool.h @@ -0,0 +1,18 @@ +/** + * @file pool.h + * @brief Mimic `pool.h` but using `pthread_mutex_t`. + * + */ + +#ifndef __POOL__ +#define __POOL__ + +struct _pool; +typedef struct _pool pool_t; + +void pool_init(pool_t *p, int n); +void pool_deinit(pool_t *p); +void pool_insert(pool_t *p, int item); +int pool_remove(pool_t *p); + +#endif /* __POOL__ */