110 lines
3.3 KiB
C
110 lines
3.3 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* limited_resources.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: ruiferna <ruiferna@student.42porto.com> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2025/10/08 19:31:58 by ruiferna #+# #+# */
|
|
/* Updated: 2025/10/09 10:25:31 by ruiferna ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include <stdio.h>
|
|
#include <pthread.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#define STUDENTS 10
|
|
|
|
/*
|
|
- 3 computers (limited access)
|
|
- Only 3 students can use the PC at same time
|
|
- Implement a "semaphore" (using mutex, counter and condictions)
|
|
*/
|
|
|
|
typedef struct s_shared
|
|
{
|
|
int pcs_available;
|
|
int students;
|
|
pthread_mutex_t pcs_available_mutex;
|
|
pthread_mutex_t students_mutex;
|
|
} t_shared;
|
|
|
|
void *student_routine(void *arg)
|
|
{
|
|
/*
|
|
Print when students:
|
|
- Arrive at the library
|
|
- Get a computer
|
|
- Finish using the computer
|
|
- Leave the library
|
|
*/
|
|
t_shared *shared;
|
|
int student_id;
|
|
shared = (t_shared *) arg;
|
|
/* Use a reentrant RNG (rand_r) with a per-thread seed to avoid
|
|
data races when using rand()/srand() from multiple threads. */
|
|
unsigned int seed = (unsigned int)time(NULL) ^ (unsigned int)(unsigned long)pthread_self();
|
|
pthread_mutex_lock(&shared->students_mutex);
|
|
shared->students += 1;
|
|
student_id = shared->students;
|
|
printf("[%i] Student %i arrived at the library.\n", student_id, student_id);
|
|
pthread_mutex_unlock(&shared->students_mutex);
|
|
while (1)
|
|
{
|
|
pthread_mutex_lock(&shared->pcs_available_mutex);
|
|
if (shared->pcs_available > 0)
|
|
{
|
|
shared->pcs_available -= 1;
|
|
printf("[%i] Student %i got a computer.\n", student_id, student_id);
|
|
pthread_mutex_unlock(&shared->pcs_available_mutex);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pthread_mutex_unlock(&shared->pcs_available_mutex);
|
|
usleep(100);
|
|
}
|
|
}
|
|
int use_time = 2 + (rand_r(&seed) % 4);
|
|
usleep(use_time * 1000000);
|
|
pthread_mutex_lock(&shared->pcs_available_mutex);
|
|
shared->pcs_available += 1;
|
|
printf("[%i] Student %i finished using a computer.\n", student_id, student_id);
|
|
pthread_mutex_unlock(&shared->pcs_available_mutex);
|
|
printf("[%i] Student %i left the library.\n", student_id, student_id);
|
|
return (NULL);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
pthread_t *students;
|
|
t_shared shared;
|
|
|
|
shared.pcs_available = 3;
|
|
shared.students = 0;
|
|
pthread_mutex_init(&shared.pcs_available_mutex, NULL);
|
|
pthread_mutex_init(&shared.students_mutex, NULL);
|
|
students = (pthread_t *) malloc (sizeof(pthread_t) * STUDENTS);
|
|
|
|
int i = 0;
|
|
while (i < STUDENTS)
|
|
{
|
|
pthread_create(&students[i], NULL, student_routine, &shared);
|
|
i++;
|
|
}
|
|
i = 0;
|
|
while (i < STUDENTS)
|
|
{
|
|
pthread_join(students[i], NULL);
|
|
i++;
|
|
}
|
|
pthread_mutex_destroy(&shared.pcs_available_mutex);
|
|
pthread_mutex_destroy(&shared.students_mutex);
|
|
free(students);
|
|
return (0);
|
|
} |