0

I'm working on a program which uses threads to act as guests trying to check-in, utilize, and check-out of a Hotel.

In order to keep track of guest data across all threads, I'm using a struct:

struct thread_data
{
    int guest_id;   // id number of guest
    int room;       // room guest utilizes
    int event;      // 0=swim, 1=resturaunt, 2=fitness, 3=business
    int cost;       // final cost of stay (random value)
}

Since there will be multiple guests which use the Hotel, I try to create an array of guest structs:

struct thread_data thread_data_array[NUM_GUESTS]; // array initialization

Question 1: Does this correctly create an array of type struct? Is the name of the array thread_data_array?


Further on, I have my Guest() method in which I try to get and set data from that struct:

void *Guest(void *guestData)
{
    int guestid, guestroom, gevent, gcost;
    struct thread_data *guest_data;

    guestroom = guest_data->room;

    gevent = getRandomLessThan(4);  // activity connected to 0, 1, 2, 3
    guest_data[guestid].event = gevent; // assign to Guest's struct
}

Question 2: Am I correctly "getting" and "setting" from my struct?


In short, I'm a bit consfused as to the correct naming for my three parts:

Struct: struct thread_data;

Array: struct thread_data thread_data_array[NUM_GUESTS];

In Main(): struct thread_data *guest_data;


Here's my whole program, all errors included:

//Hotel Project 
//This project creates a system to simulate a hotel.

#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_GUESTS  10 //10 guests

void *CheckIn(void *); // the two threads
void *CheckOut(void *);

pthread_t guests[NUM_GUESTS];

sem_t roomSem;              //total number of rooms in the hotel
sem_t check_in, check_out;  //reception desks
sem_t s1, s2, s3, s4, s5;   //global semaphores

int rooms[5];   //keep track of availability of each room

int total_guests;       //incremented with each guest check-out
int pool;               //incremented with each guest use pool
int resturant;          //incremented with each guest use resturant
int fitness_center;     //incremented with each guest use fitness center
int business_center;    //incremented with each guest use business center

struct thread_data
{
    int guest_id;   // id number of guest
    int room;       // room guest utilizes
    int event;      // 0=swim, 1=resturaunt, 2=fitness, 3=business
    int cost;       // final cost of stay (random value)
}

struct thread_data thread_data_array[NUM_GUESTS]; // array initialization


void *Guest(void *guestData)
{
int guestNumber = *(int *) guestData; //error?
int guestid, guestroom, gevent, gcost;
struct thread_data *guest_data;

guestid = (struct int) guestData; //error?

//guest_data = (struct thread_data *) guestData;
//guestid = guest_data->guest_id; // guestID stored in the struct

/*output*/ printf("Guest %d waits for room to be available\n", guestid);
sem_wait(&roomSem); // guest wants a room; check to see if one is available

/*output*/ printf("Guest %d waits for check-in\n", guestid);
sem_wait(&check_in); // if there is a room available, guest approaches check_in clerk; making him busy
/*output*/ printf("Guest %d goes to the check-in reservationist\n", guestid);
CheckIn(thread_data_array[guestid]); //check in
sem_post(&s1); // event ordering

sem_wait(&s2);
guestroom = guest_data->room;
/*output*/ printf("Guest %d receives Room %d and completes check-in\n", guestid, room);

sem_post(&check_in); // event ordering. Check-In now available

gevent = getRandomLessThan(4);  // activity connected to 0, 1, 2, 3
guest_data[guestid].event = gevent; // assign to Guest's struct

switch(gevent)
{
    case(0): /*output*/ printf("Guest %d does event: Pool\n", guestid);
            pool++;

    case(1): /*output*/ printf("Guest %d does event: Resturant\n", guestid);
            resturant++;

    case(2): /*output*/ printf("Guest %d does event: Fitness Center\n", guestid);
            fitness_center++;

    case(3): /*output*/ printf("Guest %d does event: Business Center\n", guestid);
            business_center++;
}
/*output*/ printf("Guest %d does event: %d\n", guestid, gevent);

sleep(getRandomLessThan(5) - 1); // sleep for 1 to 3 seconds

gcost = getRandomLessThan(300);     // 0 < cost < 300
guest_data[guestid].cost = gcost;   // maybe should be in CheckOut
//thread_data_array[guest].cost = money;

sem_wait(&check_out); // guest waits for check-out desk to be available
/*output*/ printf("Guest %d goes to the check-out reservationist and returns room %d\n", guestid, room);
sem_post(&s3); // event ordering

printf("Main: Creating CheckOut thread %d", guestid);
rc = pthread_create(&guest[guestid], NULL, CheckOut, (void *)&thread_data_array[guest]);
if (rc){
    printf("ERROR1; return code from pthread_create() is %d\n", rc);
    exit(-1);
}

sem_wait(&s4); // event ordering
total = thread_data_array[guestid].cost;
/*output*/ printf("Guest %d receives the total balance of $%d\n", guestid, total);
/*output*/ printf("Guest %d makes a payment\n", guestid);
total_guests++;
sem_post(&s5); // event ordering

}

int getRandomLessThan(int x)
{
    srand(time(NULL));
    int r = rand() % x;
    printf("Random number: %d\n", r);

    return r;
}

int GetOpenRoom()
{
    for (int i=0; i<rooms.length; i++)
    {
        if (rooms[i] = 1) // room vacant
        {
            rooms[i] = 0; // mark as filled
            return i;
        }
    }
}

void *CheckIn(void *guestData)
{
int guestid, guestroom;
struct thread_data *guest_data;
guest_data = (struct thread_data *) guestData;

guestid = guest_data->guest_id; // guestID stored in the struct
/**/guestroom = guest_data->room; // room stored in the struct
/**/printf("Guestroom: %d", guestroom); // expecting NULL

sem_wait(&s1); // event ordering

/*output*/ printf("The check-in reservationist greets Guest %d\n", guestid);
sem_wait(&roomSem); // use a room
guestroom = GetOpenRoom();
guest_data[guestid].room = guestroom; // mark room number in guest's struct
//thread_data_array[guestid].room = guestroom;
//which do i need?

/*output*/ printf("Assign room %d to Guest %d\n", guestroom, guestid);

sem_post(&s2); // event ordering

pthread_exit(NULL);
}


void *CheckOut(void *guestData)
{
int guestid, guestroom, guestcost;
struct thread_data *guest_data;

guest_data = (struct thread_data *) guestData;
guestid = guest_data->guest_id; // guestID stored in the struct
guestroom = guest_data->room; // room stored in the struct
guestcost = guest_data->cost; // cost stored in the struct

sem_wait(&s3); // event ordering
/*output*/ printf("The check-out greets Guest %d and receives the key from room %d\n", guestid, guestroom);
rooms[guestroom] = 1; // room now available, set back to 1
sem_post(&roomSem); // release a room
/*output*/ printf("Calculate the balance for Guest %d\n", guestid);
//case situation for each event. makes guestcost= different value for each event
thread_data_array[guestid].cost = guestcost;
sem_post(&s4); // event ordering
sem_wait(&s5); // event ordering
/*output*/ printf("Receive $%d from Guest %d and complete the check-out\n", cost, guestid);

pthread_exit(NULL);
}



//Guest
int main (int argc, char *argv[])
{
pthread_t desk[2];
int rc;
int guest;
struct thread_data *guest_data;

sem_init(&roomSem, 1, 5); //not 0 means shared between multiple processes, 5 is initial value
sem_init(&check_in, 1, 1);
sem_init(&check_out, 1, 1);
sem_init(&s1, 1, 0);
sem_init(&s2, 1, 0);
sem_init(&s3, 1, 0);
sem_init(&s4, 1, 0);
sem_init(&s5, 1, 0);

rooms[5] = {1,1,1,1,1};

pthread_create(&desk[0], NULL, CheckIn, NULL);  // Check In runs on it's own now
pthread_create(&desk[1], NULL, CheckOut, NULL); // Check Out runs on it's own now

for(guest = 0; guest < NUM_GUESTS; guest++)
{
    int *guestNumber = malloc(sizeof(*guestNumber);
    guestNumber = guest;
    //thread_data_array[guest].guest_id = guest; // guest ID for each guest thread
    rc = pthread_create(guests[guest], NULL, Guest, guestNumber); //Guest method, guest argument
    //Guest only takes a void argument. Must use thread_data_array?
    if (rc) {
        printf("ERROR; return code from pthread_create(Guest) is %d\n", rc);
        exit(-1);
    }
}

printf("\t\t\tNumber of Customers\n");
printf("Total Guests:\t%d\n", total_guests);
printf("Pool:\t%d\n", pool);
printf("Resturant:\t%d\n", resturant);
printf("Fitness Center:\t%d\n", fitness_center);
printf("Business Center:\t%d\n", business_center);

sem_close(&roomSem);
sem_close(&check_in);
sem_close(&check_out);
sem_close(&s1);
sem_close(&s2);
sem_close(&s3);
sem_close(&s4);
sem_close(&s5);

pthread_exit(NULL);
}

EDIT: I am using void pointers as arguments in my threads because I am using pthread_create()

3
  • 1
    Declaring, allocating, and initializing are three different things. Commented Apr 26, 2016 at 20:14
  • 2
    guestid = (struct int) guestData; makes absolutely no sense. int is not the name of a structure. Commented Apr 26, 2016 at 20:38
  • Note that your definition of struct thread_data is missing a ; at the end. Commented Apr 26, 2016 at 20:54

3 Answers 3

1

Question 1:

Yes, struct thread_data thread_data_array[NUM_GUESTS]; is creating thread_data_array as array with NUM_GUESTS elements of type struct thread_data.

Question 2:

guest_data is a pointer to your struct, but is not initialized (points nowhere):

struct thread_data *guest_data;

guestroom = guest_data->room;
Sign up to request clarification or add additional context in comments.

4 Comments

How is your code for question 2 different from the code in the question?
@Barmar: It's not different. It's just the erroneous part copied to show it.
A useful answer should show how to fix erroneous code, not just parrot it back.
Can you show me how I should correct this? I'm not sure what it means to say that it "points nowhere" when I feel like it's holding all the data, and points (->) to specify what piece of data to get.
1

Question 1

Yes, you define an array of struct thread_data named thread_data_array. However, your comment is not correct. The array is left uninitialized, in other words, is a chunk of memory whose value is random. Definition and Initialization are two things in C. You could combine the two things in one statement. For example,

int a = 0;  // for primitive type
struct thread_data thread_data_array[2] = {
    {0, 0, 0, 0},
    {1, 1, 1, 1}
}; // define and initialize an array of size 2 of your struct type

Question 2: Issue of your second piece of code

struct thread_data *guest_data is uninitialized, which means guest_data is a random pointer, or seriously, dangerous pointer. I guess you intended to set guest_data pointer to input value

guest_data = (struct thread_data *)guestData;

As struct is a chunk of memory, fields defined inside struct will be converted to an offset to the very beginning of memory address of this struct object by compiler in compile-time. void * pointer to any memory address, you can not use it as an representation of an array since dereference void * will get void which has no member field.

Comments

0
  1. You are creating ok, and correct name.
  2. No. guest_data is not initialized.

There is no reason to use void * in the call. You should use the proper type. To pass a pointer to your array, change the signature to:

void *Guest(struct thread_data * thread_data_array)

If you don't give it the right type, then you won't be able to index into the array.

thread_data_array[guestid].event = gevent;

naming of parts:

Struct: struct thread_data; // type name (not a variable)

Array: struct thread_data thread_data_array[NUM_GUESTS]; // array name

struct thread_data *guest_data; // pointer to a struct, which could be part of the array

2 Comments

I use void * because I create the Guest using pthread_create() which I believe requires a void pointer
The argument to pthread_create needs to be a pointer to an existing object. You can pass any pointer to a function taking void *.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.