user3577233
user3577233

Reputation: 11

Code using Thread and Semaphore

what am I doing wrong with this code? it's like a ticket system, where you have different sellers that are selling 34 tickets.

#include <stdio.h>
#include <stdbool.h>
#define NUM_TICKETS 35
#define NUM_SELLERS 4
/**
 * The ticket counter and its associated lock will be accessed
 * all threads, so made global for easy access.
 */

static int numTickets = NUM_TICKETS;
static ticketsLock;


/**
 * Our main is creates the initial semaphore lock in an unlocked state
 * (one thread can immediately acquire it) and sets up all of
 * the ticket seller threads, and lets them run to completion. They
 * should all finish when all tickets have been sold. 
 */
void main(int argc, char **argv)
{
    int i;
    char name[32];
    bool verbose = (argc == 2 && (strcmp(argv[1], "-v") == 0));
    InitThreadPackage(verbose);
    ticketsLock = SemaphoreNew("Tickets Lock", 1);
    for (i = 0; i < NUM_SELLERS; i++) {
        sprintf(name, "Seller #%d", i); // give each thread a distinct name
        ThreadNew(name, SellTickets, 0);
    }
    RunAllThreads(); // Let all threads loose
    SemaphoreFree(ticketsLock); // to be tidy, clean up
    printf("All done!\n");
}

static void SellTickets(void)
{
    bool done = false;
    int numSoldByThisThread = 0; // local vars are unique to each thread
    while (!done) {
        /**
         * imagine some code here which does something independent of
         * the other threads such as working with a customer to determine
         * which tickets they want. Simulate with a small random delay
         * to get random variations in output patterns.
         */
        RandomDelay(500000, 2000000);
        SemaphoreWait(ticketsLock); // ENTER CRITICAL SECTION
        if (numTickets == 0) { // here is safe to access numTickets
            done = true; // a "break" here instead of done variable
                         // would be an error- why?
        } else {
            numTickets--;
            numSoldByThisThread++;
            printf("%s sold one (%d left)\n", ThreadName(), numTickets);
        }
        SemaphoreSignal(ticketsLock); // LEAVE CRITICAL SECTION
    }
    printf("%s noticed all tickets sold! (I sold %d myself) \n",
    ThreadName(), numSoldByThisThread);
}

The output should look like this:

Seller #1 sold one (34 left)
Seller #0 sold one (33 left)
Seller #1 sold one (32 left)
Seller #1 sold one (31 left)
Seller #1 sold one (30 left)
Seller #1 sold one (29 left)
Seller #1 sold one (28 left)
Seller #2 sold one (27 left)
Seller #3 sold one (26 left)
Seller #2 sold one (25 left)
Seller #3 sold one (24 left)
Seller #2 sold one (23 left)
Seller #0 sold one (22 left)
Seller #1 sold one (21 left)
Seller #2 sold one (20 left)
Seller #0 sold one (19 left)
Seller #1 sold one (18 left)
Seller #1 sold one (17 left)
Seller #3 sold one (16 left)
Seller #2 sold one (15 left)
Seller #0 sold one (14 left)
Seller #0 sold one (13 left)
Seller #1 sold one (12 left)
Seller #3 sold one (11 left)
Seller #2 sold one (10 left)
Seller #0 sold one (9 left)
Seller #0 sold one (8 left)
Seller #1 sold one (7 left)
Seller #3 sold one (6 left)
Seller #2 sold one (5 left)
Seller #0 sold one (4 left)
Seller #1 sold one (3 left)
Seller #1 sold one (2 left)
Seller #1 sold one (1 left)
Seller #1 sold one (0 left)
Seller #3 noticed all tickets sold! (I sold 5 myself)
Seller #2 noticed all tickets sold! (I sold 7 myself)
Seller #1 noticed all tickets sold! (I sold 15 myself)
Seller #0 noticed all tickets sold! (I sold 8 myself)
All done!

But the compiler tells me the following: SellTickets() undeclared (first use in this function)

Can anyone help me fix it?

Thank you

This is the error that I get when I switch the order or declare the function before main:

/tmp/ccXC17qT.o: In function `main':
new.c:(.text+0x6b): undefined reference to `InitThreadPackage'
new.c:(.text+0x7f): undefined reference to `SemaphoreNew'
new.c:(.text+0xc7): undefined reference to `ThreadNew'
new.c:(.text+0xd8): undefined reference to `RunAllThreads'
new.c:(.text+0xe5): undefined reference to `SemaphoreFree'
/tmp/ccXC17qT.o: In function `SellTickets':
new.c:(.text+0x132): undefined reference to `RandomDelay'
new.c:(.text+0x13f): undefined reference to `SemaphoreWait'
new.c:(.text+0x16a): undefined reference to `ThreadName'
new.c:(.text+0x18c): undefined reference to `SemaphoreSignal'
new.c:(.text+0x19c): undefined reference to `ThreadName'
collect2: ld returned 1 exit status

Upvotes: 1

Views: 1516

Answers (1)

Keugyeol
Keugyeol

Reputation: 2435

You are missing the function prototype of SellTickets().

Put the function prototype static void SellTickets(void); above function main().

static void SellTickets(void);

void main(int argc, char **argv)
{
   ...
}

static void SellTickets(void)
{
   ...
}

Or you may just change the position of main() and SellTickets().

static void SellTickets(void)
{
   ...
}

void main(int argc, char **argv)
{
   ...
}

For the other functions related to threads, you'll have to #include proper header files for them. After that, it might pass the compiler but you'll also have to link with the proper library, or compile and link the source code, of those thread-related functions. Can you identify the thread library you are using?

Googling shows those thread related functions are from here: http://see.stanford.edu/materials/icsppcs107/22-Thread-Package-Docs.pdf

Assuming it is the thread library you are using, and also assuming both header file and the library file are in the proper paths that the compiler and the linker can find, #include "thread_107.h in your program, and link with libthread_107.a.

Upvotes: 1

Related Questions