HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Concurrent stack in C

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
concurrentstackstackoverflow

Problem

(See also the follow-up question.)

I was in the mood for pthread.h and decided to write a concurrent stack data structure. My requirements:

  • the stack has maximum capacity,



  • pushing an element,



  • removing the top element without returning it,



  • peeking the top element,



  • client is blocked whenever popping from an empty stack,



  • client is blocked whenever pushing to a full stack.



My codez looks like this:

concurrent_stack.h

```
#ifndef CONCURRENT_STACK_H
#define CONCURRENT_STACK_H

#include

typedef struct concurrent_stack
{

/***
The number of elements stored in this stack.
***/
size_t size;

/
The maximum number of elements this stack can hold.
/
size_t capacity;

/
The actual array holding the data of the stack.
/
void** storage;

/****
The mutual exclusion lock for updating the stack.
****/
pthread_mutex_t mutex;

/*****
Guards against an empty stack.
*****/
pthread_cond_t empty_condition_variable;

/***
Guards against a full stack.
***/
pthread_cond_t full_condition_variable;
}
concurrent_stack;

/*
Initializes a new, empty concurrent stack.
*/
void concurrent_stack_init(concurrent_stack* stack, size_t capacity);

/
Pushes a datum onto the top of the stack.
/
void concurrent_stack_push(concurrent_stack stack, void datum);

/*

Solution

Issues:

Failed to check the return value of all these system calls:

stack->storage = malloc(sizeof(void*) * stack->capacity);
pthread_mutex_init(&stack->mutex, NULL);
pthread_cond_init(&stack->empty_condition_variable, NULL);
pthread_cond_init(&stack->full_condition_variable, NULL);
pthread_mutex_lock(&stack->mutex);
pthread_cond_wait(&stack->full_condition_variable, &stack->mutex);
pthread_cond_signal(&stack->empty_condition_variable);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_lock(&stack->mutex);
pthread_cond_wait(&stack->empty_condition_variable, &stack->mutex);
pthread_cond_signal(&stack->full_condition_variable);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_lock(&stack->mutex);
pthread_cond_wait(&stack->empty_condition_variable, &stack->mutex);
pthread_cond_signal(&stack->full_condition_variable);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_lock(&stack->mutex);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_destroy(&stack->mutex);
pthread_cond_destroy(&stack->empty_condition_variable);
pthread_cond_destroy(&stack->full_condition_variable);


You may be destroying objects that are currently in use in another thread.

void concurrent_stack_free(concurrent_stack* stack)
{
    free(stack->storage);
    pthread_mutex_destroy(&stack->mutex);
    pthread_cond_destroy(&stack->empty_condition_variable);
    pthread_cond_destroy(&stack->full_condition_variable);
}


Before you can start freeing the resources you have to make sure that no other thread is using these resources. This means you have to force a flush and make sure there are no threads in your object.

Code Snippets

stack->storage = malloc(sizeof(void*) * stack->capacity);
pthread_mutex_init(&stack->mutex, NULL);
pthread_cond_init(&stack->empty_condition_variable, NULL);
pthread_cond_init(&stack->full_condition_variable, NULL);
pthread_mutex_lock(&stack->mutex);
pthread_cond_wait(&stack->full_condition_variable, &stack->mutex);
pthread_cond_signal(&stack->empty_condition_variable);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_lock(&stack->mutex);
pthread_cond_wait(&stack->empty_condition_variable, &stack->mutex);
pthread_cond_signal(&stack->full_condition_variable);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_lock(&stack->mutex);
pthread_cond_wait(&stack->empty_condition_variable, &stack->mutex);
pthread_cond_signal(&stack->full_condition_variable);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_lock(&stack->mutex);
pthread_mutex_unlock(&stack->mutex);
pthread_mutex_destroy(&stack->mutex);
pthread_cond_destroy(&stack->empty_condition_variable);
pthread_cond_destroy(&stack->full_condition_variable);
void concurrent_stack_free(concurrent_stack* stack)
{
    free(stack->storage);
    pthread_mutex_destroy(&stack->mutex);
    pthread_cond_destroy(&stack->empty_condition_variable);
    pthread_cond_destroy(&stack->full_condition_variable);
}

Context

StackExchange Code Review Q#151657, answer score: 7

Revisions (0)

No revisions yet.