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, lock2; //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, 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.
int id; //Lift id to be printed in output
void *lift(void *vargp) //Consumer
{
pthread_mutex_lock(&lock2);
while (length <= 0)
{
printf("Waiting for request\n");
pthread_cond_wait(&empty, &lock2); //buffer is empty
}
sleep(sec); //Simulate time of elevator movement
printf("lifting information\n");
id++;
//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;
//Now write the information
fprintf(((share_t*)vargp)->out, "Lift-%d Operation\n", id);
fprintf(((share_t*)vargp)->out, "Previous position: Floor %d\n", write1.p);
fprintf(((share_t*)vargp)->out, "Request: Floor %d to Floor %d\n", write1.rf, write1.rt);
fprintf(((share_t*)vargp)->out, "Detail operations:\n");
fprintf(((share_t*)vargp)->out, " Go from Floor %d to Floor %d\n", write1.p, write1.rf);
fprintf(((share_t*)vargp)->out, " Go from Floor %d to Floor %d\n", write1.rf, write1.rt);
fprintf(((share_t*)vargp)->out, " #movement for this request: %d\n", write1.m);
write1.total_r[id] = write1.total_r[id] + 1;
fprintf(((share_t*)vargp)->out, " #request: %d\n", write1.total_r[id]);
write1.total_m[id] = write1.total_m[id] + 1;
fprintf(((share_t*)vargp)->out, " Total #movement: %d\n", write1.total_m[id]);
fprintf(((share_t*)vargp)->out, "Current Position: Floor %d\n", write1.c);
fprintf(((share_t*)vargp)->out, "\n");
fprintf(((share_t*)vargp)->out, "----------------------------\n");
write1.p = write1.c; //for next statement
length--;
out_i = (out_i + 1) % size;
if (id < 3)
{
id = 0;
}
if (length == size-1)
{
printf("Signalling Request\n");
pthread_cond_signal(&full);
}
pthread_mutex_unlock(&lock2);
return NULL;
}
void *request_t(void *vargp) //producer
{
pthread_mutex_lock(&lock); //Now only request can operate (mutual exclusion)
//read the input line by line and into the buffer
while (fscanf(((share_t*)vargp)->in, "%d %d\n", &A[in].from, &A[in].to) != EOF) //Stores values in buffer
{
while (length >= size) //buffer is full
{
printf("Waiting for lift\n");
pthread_cond_wait(&full, &lock);
}
printf("Requesting information\n");
//If requests go out of bounds, they will be automatically registered as either
//maximum level or minimum level
if (A[in].to > 20)
{
A[in].to = 20;
}
else if (A[in].to < 1)
{
A[in].to = 1;
}
else if (A[in].from > 20)
{
A[in].from = 20;
}
else if (A[in].from < 1)
{
A[in].from = 1;
}
//Print buffer information to sim_output
fprintf(((share_t*)vargp)->out, "New Lift Request from Floor %d to Floor %d \n", A[in].from, A[in].to);
fprintf(((share_t*)vargp)->out, "Request No %d \n", counter++);
fprintf(((share_t*)vargp)->out, "----------------------------\n");
length++;
in = (in + 1) % size;
if (length == 1)
{
printf("Signalling Lift\n");
pthread_cond_signal(&empty);
}
}
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
void main(int argc, char *argv[]) // to avoid segmentation fault
{
//establish values for use (convert argv to int values)
counter = 1;
share_t *share = (share_t *)malloc(sizeof(share_t)); //Allow multiple arguments in pthread
in = 0, out_i = 0, id = 0, length = 0; //All slots are empty
long arg = strtol(argv[1], NULL, 10);
size = arg;
if (size <= 1)
{
printf("buffer size too small\n");
exit(0);
}
else
{
//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)
{
printf("insufficient time\n");
exit(0);
}
FILE *out = fopen("sim_output.txt", "w");
FILE *in = fopen("sim_input.txt", "r");
if (in == NULL && out == NULL) //Check if files exists before we can use them
{
printf("Input file empty\n");
exit(0);
}
else //Load files into share for transporting.
{
share->out = out;
share->in = in;
}
//Create threads
printf("Creating threads\n");
pthread_t Lift_R, lift_1, lift_2, lift_3;
assert(pthread_cond_init(&full, NULL) == 0);
assert(pthread_cond_init(&empty, NULL) == 0);
assert(pthread_mutex_init(&lock, NULL) == 0);
assert(pthread_mutex_init(&lock2, NULL) == 0);
assert(pthread_create(&Lift_R, NULL, request_t, share) == 0);
share->id = 1;
assert(pthread_create(&lift_1, NULL, lift, share) == 0);
share->id = 2;
assert(pthread_create(&lift_2, NULL, lift, share) == 0);
share->id = 3;
assert(pthread_create(&lift_3, NULL, lift, share) == 0);
assert(pthread_join(Lift_R, NULL) == 0);
assert(pthread_join(lift_1, NULL) == 0);
assert(pthread_join(lift_2, NULL) == 0);
assert(pthread_join(lift_3, NULL) == 0);
//pthread_mutex_destroy(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, "\n");
fprintf(out, "Total number of requests %d \n", sum_r);
fprintf(out, "Total number of movememts %d \n", sum_t);
fclose(in);
fclose(out);
}