Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include "list.h"
pthread_cond_t full, empty; //declare thread conditions
pthread_mutex_t lock_full, lock_empty; //declare mutex to lock functions
int counter; //number of requests made
static int size; //buffer size (must only change once at beginning)
static int sec; //Time in seconds, needed for lift to execute operation
int length; //Number of values in buffer
unsigned int in_i, out_i; //tail and head of buffer
buffer_t *A; //the circular queue, is initialized in main due to size declared by user input
write_t write1; //Used for printing the information from buffer.
void *lift(void *vargp) //Consumer
{
share_t* share = vargp;
pthread_mutex_lock(&lock_empty);
while (true)
{
printf("%d\n", length);
while (length <= 0)
{
printf("Waiting for request\n");
pthread_cond_wait(&empty, &lock_empty); //buffer is empty
}
sleep(sec); //Simulate time of elevator movement
printf("lifting information\n");
//gather information to print
if (write1.p == 0) //only for when system begins (Assign Previous to the first record `from` value)
{
write1.p = A[out_i].from;
}
write1.rf = A[out_i].from;
write1.rt = A[out_i].to;
write1.m = (write1.p - A[out_i].from) + (A[out_i].to - A[out_i].from);
write1.c = A[out_i].to;
int id = share->id;
//Now write the information
write1.total_r[id] = write1.total_r[id] + 1;
write1.total_m[id] = write1.total_m[id] + write1.m;
fprintf(share->out, "Lift-%d Operation\n"
"Previous position: Floor %d\n"
"Request: Floor %d to Floor %d\n"
"Detail operations:\n"
" Go from Floor %d to Floor %d\n"
" Go from Floor %d to Floor %d\n"
" #movement for this request: %d\n"
" #request: %d\n"
" Total #movement: %d\n"
"Current Position: Floor %d\n"
"\n"
"----------------------------\n", id, write1.p, write1.rf, write1.rt, write1.p, write1.rf,
write1.rf, write1.rt, write1.m, write1.total_r[id],
write1.total_m[id], write1.c);
write1.p = write1.c; //for next statement
length--;
out_i = (out_i + 1) % size;
if (length == size - 1)
{
printf("Signalling Request\n");
pthread_cond_signal(&full);
}
}
pthread_mutex_unlock(&lock_empty);
}
void *request_t(void *vargp) //producer
{
share_t * share = vargp;
pthread_mutex_lock(&lock_full); //Now only request can operate (mutual exclusion)
//read the input line by line and into the buffer
while (1){
while (length >= size) //buffer is full
{
printf("Waiting for lift\n");
pthread_cond_wait(&full, &lock_full);
}
printf("Requesting information\n");
if (fscanf(share->in, "%d %d\n", &A[in_i].from, &A[in_i].to) == EOF)
{
break;
}
//Stores values in buffer
//If requests go out of bounds, they will be automatically registered as either
//maximum level or minimum level
if (A[in_i].to > 20)
{
A[in_i].to = 20;
}
else if (A[in_i].to < 1)
{
A[in_i].to = 1;
}
else if (A[in_i].from > 20)
{
A[in_i].from = 20;
}
else if (A[in_i].from < 1)
{
A[in_i].from = 1;
}
//Print buffer information to sim_output
fprintf(share->out, "New Lift Request from Floor %d to Floor %d \n"
"Request No %d \n"
"----------------------------\n", A[in_i].from, A[in_i].to, counter++);
length++;
in_i = (in_i + 1) % size;
if (length == 1) //is causing system to crash.
{
printf("Signalling Lift\n");
pthread_cond_signal(&empty);
}
}
pthread_mutex_unlock(&lock_full);
pthread_exit(NULL);
}
int main(int argc, char * argv[]) // to avoid segmentation fault
{
if (argc != 3)
{
perror("Insufficient arguements\n");
exit(EXIT_FAILURE);
}
//establish values for use (convert argv to int values)
counter = 1;
share_t share[4]; //Allow multiple arguments in pthread
in_i = 0, out_i = 0, length = 0; //All slots are empty at first
long arg = strtol(argv[1], NULL, 10);
size = arg;
if (size <= 1)
{
perror("buffer size too small\n");
exit(EXIT_FAILURE);
}
//initialize Buffer as empty array.
A = calloc(size, sizeof *A);
arg = strtol(argv[2], NULL, 10);
sec = arg; //time required by each lift to serve a request
if (sec <= 0)
{
perror("insufficient time\n");
exit(EXIT_FAILURE);
}
FILE *out_t = fopen("sim_output.txt", "w");
FILE *in_t = fopen("sim_input.txt", "r");
if (in_t == NULL && out_t == NULL) //Check if files exists before we can use them
{
perror("Invalid files\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < 4; i++)//Load files into share for transporting.
{
share[i].in = in_t;
share[i].out = out_t;
share[i].id = i;
}
//Create threads
printf("Creating threads\n");
pthread_t Lift_R, lift_1, lift_2, lift_3;
pthread_cond_init(&full, NULL);
pthread_cond_init(&empty, NULL);
pthread_mutex_init(&lock_full, NULL);
pthread_mutex_init(&lock_empty, NULL);
int LR = pthread_create(&Lift_R, NULL, request_t, &share[0]);
if (LR != 0)
{
perror("error");
exit(EXIT_FAILURE);
}
int l1 = pthread_create(&lift_1, NULL, lift, &share[1]);
if (l1 != 0)
{
perror("error");
exit(EXIT_FAILURE);
}
int l2 = pthread_create(&lift_2, NULL, lift, &share[2]);
if (l2 != 0)
{
perror("error");
exit(EXIT_FAILURE);
}
int l3 = pthread_create(&lift_3, NULL, lift, &share[3]);
if (l3 != 0)
{
perror("error");
exit(EXIT_FAILURE);
}
pthread_join(lift_1, NULL);
pthread_join(lift_2, NULL);
pthread_join(lift_3, NULL);
pthread_join(Lift_R, NULL);
int sum_r = write1.total_r[1] + write1.total_r[2] + write1.total_r[3],
sum_t = write1.total_m[1] + write1.total_m[2] + write1.total_m[3];
fprintf(out_t, "\n"
"Total number of requests %d \n"
"Total number of movememts %d \n", sum_r, sum_t);
fclose(in_t);
fclose(out_t);
printf("finished\n");
return 0;
}