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?
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);
}
}
}
Condition variables are supposed to be used to signal a change in the state of some (mutex-protected) shared data. You can't use them on their own. Consider what would happen if a thread signals a condition before there is another thread waiting for that condition.
I don't see where you create any threads. I'll assume you create the threads.
swap_buffers() and fill_back_buffer() do contain the classic deadlock implementation. When swap_buffers() is waiting on theBackBufferFull, it has locked theBackMutex. Meanwhile, fill_back_buffer() is waiting on theBackMutex before it sets the signal theBackBufferFull. Therefore, theBackBufferFull will never be signaled, because theBackMutex cannot be released. This is the classic deadlock condition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With