I am creating a threaded application that uses double buffering and I am trying to avoid a potential deadlock. The main idea is that the swap buffer thread locks out the write and the read thread. However the swap buffer thread is fast so the locks will not stay locked long. The Write and Read threads are slower but share time slices efficiently (the goal) because they lock on different mutexes. My question is there a potential deadlock with this design?
- 3 threads...Thread A, Thread B, and Thread C.
- 2 mutexes...Front Mutex and the Back Mutex.
- Thread A fills the back buffer
- Thread B swaps the buffer.
- Thread C uses the front buffer.
- Thread A takes theBackMutex, fills the back buffer, releases theBackMutex.
- Thread C takes theFrontMutex, uses the front buffer, releases theFrontMutex.
- Thread B takes theBackMutex, theFrontMutex, swaps the buffers, releases theBackMutex,release theFront Mutex
void *fill_back_buffer() {
while(1) {
if (0 != pthread_mutex_lock(&theBackMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
//should we get new data for back buffer?
pthread_cond_wait(&theBackBufferRefresh, &theBackMutex);
//fill back buffer
if (0 != pthread_mutex_unlock(&theBackMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
//hey we done filling the back buffer!
pthread_cond_signal(&theBackBufferFull);
}
}
void *swap_buffers() {
while(1) {
if (0 != pthread_mutex_lock(&theBackMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
if (0 != pthread_mutex_lock(&theFrontkMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
//do we have new data in the back buffer?
pthread_cond_wait(&theBackBufferFull, &theBackMutex);
//swap buffers
char* tmp;
tmp = theBufferAPtr;
theBufferAPtr = theBufferBPtr;
theBufferBPtr = tmp;
if (0 != pthread_mutex_unlock(&theFrontMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
if (0 != pthread_mutex_unlock(&theBackMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
//hey please get more data!
pthread_cond_signal(&theBackBufferRefresh);
//hey you can use front buffer now!
pthread_cond_signal(&theBufferSwapped);
}
}
int main(int argc, char *argv[]) {
//initial fill of the back buffer
pthread_cond_signal(&theBackBufferRefresh);
while(1) {
if (0 != pthread_mutex_lock(&theFrontMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
pthread_cond_wait(&theBufferSwapped, &theFrontMutex);
//use the front buffer and do stuff with it
if (0 != pthread_mutex_unlock(&theFrontMutex)) {
perror("Mutex lock failed (!!):");
exit(-1);
}
}
}