Step 2: Implement adder, multiplier, and degrouper
--------------------------------------------------
Write the code to implement these functions. They should only
consider
the current expression, which is the first expression in the
buffer, or,
equivilently, everything up until the first semicolon. Do not
implement
synchronization and mutual exclusion yet.
Tip: See sentinel() for an example invocation of strcpy() that
shifts
the characters in a string to the left.
Tip: If you are not certain which stdlib functions to use
for
string/number manipulation, feel free to use the provided
utility
functions (string2int, int2string, isNumeric).
Pseudocode for adder/multiplier:
a. Scan through current expression looking for a number.
b. Check each number to see if it is followed by a +/*, and then
a
numeric character (indicating the start of another number).
c. If it is, add/multiply the two numbers, and replace the
addition/multiplication subexpression with the result, e.g.,
"34+22"
becomes "56".
Pseudocode for degrouper:
a. Scan through current expression looking for a '('.
b. Check if the next character is numeric (indicating the start of
a
number).
c. If it is, check if the number is immediately followed by a
')'.
d. If so, we have something like "(32432)". Now remove the '(' and
')'
we've just located from the expression.
The above pseudocode is only a suggestion; your code may
work
differently. For example, you could hunt for + or * in the
expression,
then check that there are "naked" numbers to the left and
right.
HERE IS THE C FILE:
/* 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\n", 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;
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;
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
if(buffer[i] == '(')
{
if(isNumeric(buffer[i+1])
&& buffer[i+2] == ')' )
{
for (int j =
i+2; j < bufferlen; j++)
buffer[j] = buffer[j+1];
for (int k = i;
k < bufferlen; k++)
buffer[k] = buffer[k+1];
}
}
}
// 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;
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\n",
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] == '\n') {
/* 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_join(readerThread, &arg);
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\n",
num_ops);
return EXIT_SUCCESS;
}
HERE IS H FILE:
/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/
#include
#include
#include
#include
#include
#include
#include
#include
#define LENGTH(a) ( sizeof(a) / sizeof(*(a)) )
#define BUF_SIZE 500
extern char buffer[BUF_SIZE];
extern int num_ops;
void *adder(void *arg);
void *multiplier(void *arg);
void *degrouper(void *arg);
void *sentinel(void *arg);
void *reader(void *arg);
int smp3_main(int argc, char **argv);
Implement adder function. Thank you
/* As requested, the adder function alone has been implemented */
/* 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, sum, operlength ;
char *operand;
while(1) {
startOffset = remainderOffset = -1;
value1 = value2 = -1;
sum = 0;
if (timeToFinish()) {
return NULL;
}
/* storing this prevents having to recalculate it in the loop
*/
bufferlen = strlen(buffer);
operand = (char *)malloc(bufflen * sizeof(char));
for (i = 0; i < bufferlen; i++)
{
// Look for a '+' in the expression.
if(buffer[i] == '+')
{
// Look for the beginning of the left operand
for(startOffset = i; startOffset -1
>=0 && isNumeric(buffer[startOffset-1]);
--startOffset);
// If the left operand is not a
naked number, proceed with finding the next '+'
if( startOffset == i)
continue;
// Look for the beginning of the
right operand
for(remainderOffset = i;
remainderOffset +1 < bufferlen &&
isNumeric(buffer[remainderOffset+1]); ++remainderOffset);
// If the right operand is not a
naked number, proceed with finding the next '+'
if( remainderOffset == i)
continue;
// Now we have a naked number on
both the left and right sides
// Let us now convert the operands
to numbers
// Left operand
strncpy(operand,
&buffer[startOffset], i-startOffset);
operand[i-startOffset] =
'\0';
string2int(value1, operand);
// Right operand
strncpy(operand,
&buffer[remainderOffset], remainderOffset - i);
operand[remainderOffset - i] =
'\0';
string2int(value2, operand);
// add the two operands
sum = value1 + value2;
// convert the numeric sum to a
string
sprint(operand, "%d", sum);
operlength = strlen(operand);
// write the string sum back into
the buffer
strncpy( &buffer[startOffset],
operand, operlength);
// Shift the remaining characters
to the left
strcpy( &buffer[operlength],
&buffer[remainderOffset+1]);
// Accordingly reset the buffer length
bufferlen = bufferlen -
(remainderOffset - startOffset + 1) + operlength;
}
}
free(operand);
}
}
Step 2: Implement adder, multiplier, and degrouper -------------------------------------------------- Write the code to implement these functions. They...
Read the following code, threaded recursive calculation of Fibonacci number of n: #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *fib(void *arg); int main(int argc, char **argv){ int n = atoi(argv[1]); printf("%d\n", (int)fib(n)); } void *fib(void *arg){ int n; pthread_t thread1; pthread_t thread2; void *a; void *b; int c; n = (int)arg; if (n <= 0) return 0; if (n == 1) return 1; pthread_create(&thread1, NULL, fib, n-1); ...
/* myloggerd.c * Source file for thread-lab * Creates a server to log messages sent from various connections * in real time. * * Student: */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <sys/socket.h> #include <sys/un.h> #include <stdlib.h> #include <pthread.h> #include "message-lib.h" // forward declarations int usage( char name[] ); // a function to be executed by each thread void * recv_log_msgs( void * arg ); // globals int log_fd; // opened by main() but accessible...
I am supposed to write documentation and report for the code below but I am new to operating system concepts I will appreciate if someone can help make a detailed comment on each line of code for better understanding. Thanks #include <pthread.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <ctype.h> #define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) struct thread_info...
In c programming The Consumer Submits processing requests to the producer by supplying a file name, its location and a character. It also outputs the contents of the file provided by the producer to the standard output. The Producer Accepts multiple consumer requests and processes each request by creating the following four threads. The reader thread will read an input file, one line at a time. It will pass each line of input to the character thread through a queue...
Concurrent Key-Value Database Implement a non-persistent, concurrent key-value database using the Reader/Writers algorithm. - Use a hashmap as the underlying data structure. Inspiration is ok, however the implementation must be yours. The hashmap must be able to grow to fit new elements, but it does not need to reduce its size. -- Linked lists? Positional arrays? All are fine. - Keys and values are strings (char *) - Operations are: get, put Provided files: - Implement the contract set in...
Read given code and write all possible outputs of the program. Assume there will be no thread creation or joining failures or mutex failures. If you believe there i only one possible output, you just need to write that output. Code: #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <errno.h> sem_t s1; int c[2] = {0,1}; void *UpdateC1(void *arg) { int i; for(i=0;i<1000000;i++) { sem_wait(&s1); c[0]=(c[0]+1)%2; c[1]=(c[1]+1)%2; sem_post(&s1); } return NULL; } void *UpdateC2(void *arg) { int i; for(i=0;i<2000000;i++)...
Read given code RaceOrNot1.c and write all possible outputs of the program. Assume there will be no thread creation or joining failures or mutex failures. If you believe there is only one possible output, you just need to write that output. #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t count_mutex3 = PTHREAD_MUTEX_INITIALIZER; int c[2] = {1,0}; void *UpdateC1(void *arg) { int i; for(i=0;i<1000000;i++) { pthread_mutex_lock(&count_mutex); c[0]=(c[0]+1)%2; c[1]=(c[1]+1)%2; pthread_mutex_unlock(&count_mutex); } return NULL; } void *UpdateC2(void *arg) { int...
Read given code RaceOrNot1.c and write all possible outputs of the program. Assume there will be no thread creation or joining failures or mutex failures. If you believe there is only one possible output, you just need to write that output. #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t count_mutex3 = PTHREAD_MUTEX_INITIALIZER; int c[2] = {1,0}; void *UpdateC1(void *arg) { int i; for(i=0;i<1000000;i++) { pthread_mutex_lock(&count_mutex); c[0]=(c[0]+1)%2; c[1]=(c[1]+1)%2; ...
1. (50 pts) Write a C or C++ program A6p1.c(pp) that accepts one command line argument which is an integer n between 2 and 6 inclusive. Generate a string of 60 random upper case English characters and store them somewhere (e.g. in a char array). Use pthread to create n threads to convert the string into a complementary string ('A'<>'Z', 'B'<->'Y', 'C''X', etc). You should divide this conversion task among the n threads as evenly as possible, Print out the...
Read given code RaceOrNot3.c and write all possible outputs of the program. Assume there will be no thread creation or joining failures or semaphore failures. If you believe there is only one possible output, you just need to write that output. #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <errno.h> sem_t s1; int c=0,x=0; void *UpdateC1(void *arg) { int i; for(i=0;i<2000000;i++) { sem_wait(&s1); c++; x++; sem_post(&s1); } } void *UpdateC2(void *arg) { int i,x=0; for(i=0;i<2999999;i++) { sem_wait(&s1); c++; x++; ...