Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

There's a problem with the code below: it quits as soon as any input is typed, or possibly before, depending on your thread scheduler. The

There's a problem with the code below: it quits as soon as any input is typed, or possibly before, depending on your thread scheduler. The reason is that the main thread (thread running in the smp3_main() function) is falling through to the end prematurely. You need to join onto one, and only one, of the five subthreads so that the program will only be able to terminate once all input has been processed and all results output. Identify the correct thread and fix this problem.

Here are the five subthreads:

1. reader_thread. This thread reads lines from stdin and appends them to the buffer. If there is not enough space remaining in the buffer[], reader blocks until there is.

2&3. adder_thread and multiplier_thread. These look for "+" and "*" signs, respectively, surrounded by two "naked" numbers, e.g., "4+3" or "2*6", but NOT something "9+(2)" or "(5*(2))*8". The corresponding operation on the two numbers is performed, replacing the subexpression with the result, e.g., "4+3" becomes "7".

4. degrouper. It looks for a single number surrounded by parentheses, e.g. "(8)", and removes said parentheses.

5. sentinel. This thread checks the buffer to see if the currently processed expression has been reduced to a single number; if it has, it prints the number to stdout and removes it from the buffer as described above.

Here is the code:

/* calc.c - Multithreaded calculator */

#include "calc.h"

pthread_t adderThread;

pthread_t degrouperThread;

pthread_t multiplierThread;

pthread_t readerThread;

pthread_t sentinelThread;

char buffer[BUF_SIZE];

int num_ops;

/* Utiltity functions provided for your convenience */

/* int2string converts an integer into a string and writes it in the

passed char array s, which should be of reasonable size (e.g., 20

characters). */

char *int2string(int i, char *s)

{

sprintf(s, "%d", i);

return s;

}

/* string2int just calls atoi() */

int string2int(const char *s)

{

return atoi(s);

}

/* isNumeric just calls isdigit() */

int isNumeric(char c)

{

return isdigit(c);

}

/* End utility functions */

void printErrorAndExit(char *msg)

{

msg = msg ? msg : "An unspecified error occured!";

fprintf(stderr, "%s ", msg);

exit(EXIT_FAILURE);

}

int timeToFinish()

{

/* be careful: timeToFinish() also accesses buffer */

return buffer[0] == '.';

}

/* Looks for an addition symbol "+" surrounded by two numbers, e.g. "5+6"

and, if found, adds the two numbers and replaces the addition subexpression

with the result ("(5+6)*8" becomes "(11)*8")--remember, you don't have

to worry about associativity! */

void *adder(void *arg)

{

int bufferlen;

int value1, value2;

int startOffset, remainderOffset;

int i;

return NULL; /* remove this line */

while (1) {

startOffset = remainderOffset = -1;

value1 = value2 = -1;

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

// do we have value1 already? If not, is this a "naked" number?

// if we do, is the next character after it a '+'?

// if so, is the next one a "naked" number?

// once we have value1, value2 and start and end offsets of the

// expression in buffer, replace it with v1+v2

}

// something missing?

}

}

/* Looks for a multiplication symbol "*" surrounded by two numbers, e.g.

"5*6" and, if found, multiplies the two numbers and replaces the

mulitplication subexpression with the result ("1+(5*6)+8" becomes

"1+(30)+8"). */

void *multiplier(void *arg)

{

int bufferlen;

int value1, value2;

int startOffset, remainderOffset;

int i;

return NULL; /* remove this line */

while (1) {

startOffset = remainderOffset = -1;

value1 = value2 = -1;

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

// same as adder, but v1*v2

}

// something missing?

}

}

/* Looks for a number immediately surrounded by parentheses [e.g.

"(56)"] in the buffer and, if found, removes the parentheses leaving

only the surrounded number. */

void *degrouper(void *arg)

{

int bufferlen;

int i;

return NULL; /* remove this line */

while (1) {

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

// check for '(' followed by a naked number followed by ')'

// remove ')' by shifting the tail end of the expression

// remove '(' by shifting the beginning of the expression

}

// something missing?

}

}

/* sentinel waits for a number followed by a ; (e.g. "453;") to appear

at the beginning of the buffer, indicating that the current

expression has been fully reduced by the other threads and can now be

output. It then "dequeues" that expression (and trailing ;) so work can

proceed on the next (if available). */

void *sentinel(void *arg)

{

char numberBuffer[20];

int bufferlen;

int i;

return NULL; /* remove this line */

while (1) {

if (timeToFinish()) {

return NULL;

}

/* storing this prevents having to recalculate it in the loop */

bufferlen = strlen(buffer);

for (i = 0; i < bufferlen; i++) {

if (buffer[i] == ';') {

if (i == 0) {

printErrorAndExit("Sentinel found empty expression!");

} else {

/* null terminate the string */

numberBuffer[i] = '\0';

/* print out the number we've found */

fprintf(stdout, "%s ", numberBuffer);

/* shift the remainder of the string to the left */

strcpy(buffer, &buffer[i + 1]);

break;

}

} else if (!isNumeric(buffer[i])) {

break;

} else {

numberBuffer[i] = buffer[i];

}

}

// something missing?

}

}

/* reader reads in lines of input from stdin and writes them to the

buffer */

void *reader(void *arg)

{

while (1) {

char tBuffer[100];

int currentlen;

int newlen;

int free;

fgets(tBuffer, sizeof(tBuffer), stdin);

/* Sychronization bugs in remainder of function need to be fixed */

newlen = strlen(tBuffer);

currentlen = strlen(buffer);

/* if tBuffer comes back with a newline from fgets, remove it */

if (tBuffer[newlen - 1] == ' ') {

/* shift null terminator left */

tBuffer[newlen - 1] = tBuffer[newlen];

newlen--;

}

/* -1 for null terminator, -1 for ; separator */

free = sizeof(buffer) - currentlen - 2;

while (free < newlen) {

// spinwaiting

}

/* we can add another expression now */

strcat(buffer, tBuffer);

strcat(buffer, ";");

/* Stop when user enters '.' */

if (tBuffer[0] == '.') {

return NULL;

}

}

}

/* Where it all begins */

int smp3_main(int argc, char **argv)

{

void *arg = 0; /* dummy value */

/* let's create our threads */

if (pthread_create(&multiplierThread, NULL, multiplier, arg)

|| pthread_create(&adderThread, NULL, adder, arg)

|| pthread_create(°rouperThread, NULL, degrouper, arg)

|| pthread_create(&sentinelThread, NULL, sentinel, arg)

|| pthread_create(&readerThread, NULL, reader, arg)) {

printErrorAndExit("Failed trying to create threads");

}

/* you need to join one of these threads... but which one? */

pthread_detach(multiplierThread);

pthread_detach(adderThread);

pthread_detach(degrouperThread);

pthread_detach(sentinelThread);

pthread_detach(readerThread);

/* everything is finished, print out the number of operations performed */

fprintf(stdout, "Performed a total of %d operations ", num_ops);

return EXIT_SUCCESS;

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Big Data Concepts, Theories, And Applications

Authors: Shui Yu, Song Guo

1st Edition

3319277634, 9783319277639

More Books

Students also viewed these Databases questions