I'm working on a larger project including two threads, where one database is shared between them. One threads job is to just count down every active elements timer, when the timer for that element is zero it should set it inactive and zero it out.
The main thread is just manipulating the active element's other variables in some way.
I am not sure how to synchronize these threads, especially as the timer thread cleans up the database element when the timer reaches zero. Right now I believe that the time between unlocking and locking the mutex
in the while(1)
loop in main()
may be too fast?
If the timer thread is waiting for the mutex
to unlock at pthread_mutex_lock()
; and it unlocks in main()
, do we know that the timer thread will be the next one to lock the mutex
or might the main()
be so fast that it locks it again as there is no task between pthread_mutex_unlock()
and pthread_mutex_lock()
?
I have no experience using condition variables, may that be a good idea here?
Here is a minimal working example of my much larger project.
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <time.h>
#define NUM_COMPUTER 10
typedef struct computer
{
unsigned int active;
unsigned int timer;
int x;
}computer_t;
/**
* Function declarations
*/
void activate(computer_t* comp);
void* timerFunction(void* args);
/**
* Global variables
*/
computer_t database[NUM_COMPUTER];
pthread_mutex_t mutex;
main() function
/**
* Main
*/
int main(void)
{
memset(database, 0, sizeof database);
// Initialize some database elements
activate(database);
database[0].x = 5;
activate(database + 3);
database[3].x = 23;
activate(database + 9);
database[9].x = -7;
pthread_t timer_thread;
pthread_create(&timer_thread, NULL, timerFunction, NULL);
while(1)
{
/**
* MAY PROBLEMS OCCUR HERE? UNLOCKING AND LOCKING ALMOST DIRECTLY
*/
// ************* LOCK *************
pthread_mutex_lock(&mutex);
/**
* Manipulate struct members
*/
for (int i = 0; i < NUM_COMPUTER; i++)
{
if (database[i].active)
{
database[i].x += 1;
}
}
// ************* UNLOCK *************
pthread_mutex_unlock(&mutex);
}
return 0;
}
Extra functions
void activate(computer_t* comp)
{
comp->active = 1;
comp->timer = 100;
}
void* timerFunction(void* args)
{
struct timespec ts;
// Sleep interval before checking database again
ts.tv_sec = 1;
ts.tv_nsec = 0;
while(1)
{
// ************* LOCK *************
pthread_mutex_lock(&mutex);
/**
* Go through every database index
*/
for (int index = 0; index < NUM_COMPUTER; index++)
{
if (database[index].active)
{
if (database[index].timer > 0)
{
database[index].timer--;
}
else
{
/**
* Clean up database index
*/
memset(database + index, 0, sizeof database);
}
}
}
// ************* UNLOCK *************
pthread_mutex_unlock(&mutex);
/**
* Sleep 1 sec before checking database again
*/
nanosleep(&ts, NULL);
}
}