void *starsToCaret(void *s){ printf("Thread_3: starsToCaret \n"); thread_Producer_Consumer_init *p = s; bool isStarLast = false; char processingTank; while (1) { withdrawalCirBuf(&processingTank, p->buffer_C); if (isStarLast) { //Last input is sta if (processingTank == '*') { processingTank = '^'; } else { depositCirBuf(p->buffer_P, '*'); } isStarLast = false; } else if(processingTank == '*') { isStarLast = true; continue; } depositCirBuf(p->buffer_P, processingTank); if (processingTank == EOF) { break; } } printf("Thread 3: starsToCaret Existing\n"); st_thread_exit(NULL); }
void *print80CharLines(void *t){ ThreadInit *init = t; char theCharacter; char toPrint[LINE_TO_PRINT_SIZE + 1] = ""; // +1 for null-termination int index = 0; int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)){ toBreak = 1; } } if (toBreak == 0){ down(init->bin_sem); //deadlock on consume unless extra produce in asterisk theCharacter = consume(init->from); printf("consumed: [%c]\n", theCharacter); toPrint[index] = theCharacter; index++; if (index == LINE_TO_PRINT_SIZE){ toPrint[80] = '\0'; // terminates string printf("%s\n", toPrint); toPrint[0] = '\0'; // resets string } up(init->bin_sem); } } // done, exit thread printf("EXIT PRINT\n"); st_thread_exit(NULL); }
//second processor function: takes in a character and checks if it's an asterisk. If not, it just passes the character //If so, pulls in another character and check if it's another //asterisk. If so, it will pass along a carat symbol, if not it just passes both characters. Ends at EOF after passing // //Modifier void *secondproc_thread_func(void *s){ ThreadInit *i = s; /* use a buffer system to check for double-asteriks */ int c = 0; //if c is not an asterisk, just produce it int char_buff = 0; int carat = '^'; //convenience while(1) { //assert there must be at least one full buff if full buffers down passes //so read has run at least once and called full buffers up c = consumeChar(i); if (c == '*'){//if c is a asterisk, get another character to check char_buff = consumeChar(i); if (char_buff == '*'){ //we can assert that we know the buffer isn't full //by similar logic as the above. This is the only thread that //writes to it and if empty buffers passes, output thread function has run produceChar (i, carat); //if both are asterisks, produce carat } else{ produceChar (i, c); //if only one is asterisk, produce both produceChar (i, char_buff); } } else produceChar (i, c); //if not asterisks, produce c if (c == EOF || char_buff == EOF) break; } st_thread_exit(NULL); }
/* * Asynchronous DNS host name resolution. This program creates one * ST thread for each host name (specified as command line arguments). * All threads do host name resolution concurrently. */ int main(int argc, char *argv[]) { int i; if (argc < 2) { fprintf(stderr, "Usage: %s <hostname1> [<hostname2>] ...\n", argv[0]); exit(1); } if (st_init() < 0) { perror("st_init"); exit(1); } for (i = 1; i < argc; i++) { /* Create a separate thread for each host name */ if (st_thread_create(do_resolve, argv[i], 0, 0) == NULL) { perror("st_thread_create"); exit(1); } } st_thread_exit(NULL); /* NOTREACHED */ return 1; }
//The output thread: Takes in characters and jams them in an array to wait. Once the thread reaches 80 characters, it outputs the array. //Exciting. //Ends at EOF; doesn't output it because it's a weird lookin character. // //Observer, kinda void *output_thread_func (void *s){ IOThreadInit *i = s; //80 char array to be output char output[81]; int c = 0; //printf("%c",'\n'); while(1) { //code saving functions dont take IOThreadInit :/ //has to be written explicitly down(i->fullbuffs); down(i->mutex); c = cbConsume(i->buffer); up(i->mutex); up(i->emptybuffs); output[strlen(output)] = c; if (strlen(output) == output_size){ printf("%s", output); printf("%c", '\n'); memset(output, '\0', strlen(output) * sizeof(char)); } if (c == EOF) break; } st_thread_exit(NULL); }
CAMLprim value caml_thread_exit(value unit) /* ML */ { struct longjmp_buffer * exit_buf = NULL; if (curr_thread == NULL) invalid_argument("Thread.exit: not initialized"); /* In native code, we cannot call pthread_exit here because on some systems this raises a C++ exception, and ocamlopt-generated stack frames cannot be unwound. Instead, we longjmp to the thread creation point (in caml_thread_start) or to the point in caml_main where caml_termination_hook will be called. Note that threads created in C then registered do not have a creation point (exit_buf == NULL). */ #ifdef NATIVE_CODE exit_buf = curr_thread->exit_buf; #endif caml_thread_stop(); if (exit_buf != NULL) { /* Native-code and (main thread or thread created by Caml) */ siglongjmp(exit_buf->buf, 1); } else { /* Bytecode, or thread created from C */ st_thread_exit(); } return Val_unit; /* not reached */ }
void *outputProcessing(void *s){ printf("Thread_4: outputProcessing \n"); thread_Producer_Consumer_init *p = s; char processingTank[2 * OUTPUT_SIZE]; int tankLevel = 0; while (1) { for (tankLevel = 0; tankLevel < OUTPUT_SIZE; tankLevel++) { withdrawalCirBuf(&processingTank[tankLevel], p->buffer_C); if (processingTank[tankLevel]==EOF) { tankLevel++; break; } } processingTank[tankLevel]='\0'; if (processingTank[tankLevel-1]==EOF) { break; } if (tankLevel>=OUTPUT_SIZE) { printf("Output: \n%s\n%s\n%s\n",ruler, processingTank, ruler); tankLevel = 0; continue; } printf("ERROR:===IMPOSSIBLE TO BE HERE\n"); } printf("Thread 4: outputProcessing Existing\n"); st_thread_exit(NULL); }
void _st_thread_main(void) { st_thread_t *thread = _ST_CURRENT_THREAD(); /* Run thread main */ thread->retval = (*thread->start)(thread->arg); /* All done, time to go away */ st_thread_exit(thread->retval); }
void* SrsThread::thread_fun(void* arg) { SrsThread* obj = (SrsThread*)arg; srs_assert(obj); obj->thread_cycle(); st_thread_exit(NULL); return NULL; }
int main (int argc, const char * argv[]) { thread_Producer_Consumer_init inputProcessing_init; thread_Producer_Consumer_init carriageToSpace_init; thread_Producer_Consumer_init starsToCaret_init; thread_Producer_Consumer_init outputProcessing_init; if (st_init()<0) { perror("st_init"); exit(1); } circularBuffer buf1, buf2, buf3; newBuffer(&buf1, BUFFER_SIZE); //for buffer inputProcessing & carriageToSpace newBuffer(&buf2, BUFFER_SIZE); //for buffer carriageToSpace & starsToCaret newBuffer(&buf3, BUFFER_SIZE); //for buffer starsToCaret & outputProcessing inputProcessing_init.buffer_C = NULL; inputProcessing_init.buffer_P = &buf1; carriageToSpace_init.buffer_C = &buf1; carriageToSpace_init.buffer_P = &buf2; starsToCaret_init.buffer_C = &buf2; starsToCaret_init.buffer_P = &buf3; outputProcessing_init.buffer_C = &buf3; outputProcessing_init.buffer_P = NULL; if (st_thread_create(inputProcessing, &inputProcessing_init, 0, 0)==NULL) { perror("st_thread_create \n"); exit(1); } if (st_thread_create(carriageToSpace, &carriageToSpace_init, 0, 0)==NULL) { perror("st_thread_create \n"); exit(1); } if (st_thread_create(starsToCaret, &starsToCaret_init, 0, 0)==NULL) { perror("st_thread_create \n"); exit(1); } if (st_thread_create(outputProcessing, &outputProcessing_init, 0, 0)==NULL) { perror("st_thread_create \n"); exit(1); } printf("Hello World~~~~~~\n"); fflush(stdout); st_thread_exit(NULL); return 0; }
// creates two threads using ST, one of which increments a shared counter, // and one of which decrements it. The counter's value is printed to stdout // after each operation. After a certain number of operations the program // terminates. int main (int argc, char const *argv[]) { // initialize the ST library runtime st_init(); // store an arbitrary integer int value = 0; // create a binary semaphore initialized to 1 semaphore bin_sem; createSem(&bin_sem, 1); // which output stream to use FILE *output = DEFAULT_OUT; // create our init data struct ThreadInit thread_init = { output, &bin_sem, &value }; //JSR int semValue = 1; int i; for (i = 0; i < 5; i++){ semValue++; up(thread_init.bin_sem); printf("semValue= %d\n", semValue); } /* // create the increment thread if (st_thread_create(increment_thread_func, &thread_init, 0, 0) == NULL) { perror("st_thread_create for increment thread failure"); exit(1); } // create the decrement thread if (st_thread_create(decrement_thread_func, &thread_init, 0, 0) == NULL) { perror("st_thread_create for decrement thread failure"); exit(1); } */ // main thread exits st_thread_exit(NULL); return 0; }
//thread to change asterisks to carats void *asterisksToCarat(void *t){ ThreadInit *init = t; char theCharacter; char nextCharacter; char carat = '^'; //used for produce() if it needs a carat int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break down(init->from_bin_sem); if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)) toBreak = 1; } if (toBreak == 0){ up(init->from_bin_sem); theCharacter = consume(init->from); if (theCharacter == '*'){ nextCharacter = consume(init->from); if (nextCharacter == '*'){ // if two successive asterisks down(init->to_bin_sem); produce(init->to, &carat); } else { // if they're not both asterisks down(init->to_bin_sem); produce(init->to, &theCharacter); produce(init->to, &nextCharacter); } } else { //the character was not an asterisk down(init->to_bin_sem); produce(init->to, &theCharacter); } up(init->to_bin_sem); } up(init->from_bin_sem);// releases from if toBreak == 1 } // lets next buffer know when to stop consuming down(init->to_bin_sem); *(init->to->doneInserting) = 1; up(init->to_bin_sem); // done, exit thread st_thread_exit(NULL); }
// thread to change newlines to spaces void *newlineToSpace(void *t){ printf("in newline\n"); ThreadInit *init = t; char theCharacter; char space = ' '; //used for produce() in the case it needs a space int toBreak = 0; //toBreak is boolean initialized to FALSE int printed = 0; //printf("input's numElements: %d\n", *(init->from->numElements)); while(toBreak == 0) { printf("in newline while\n"); //if "from" is done inserting, and there are no elements, break if( *(init->from->doneInserting) == 1){ printf("in first if\n"); if( (*init->from->numElements == 0)){ printf("input's numElements = 0\n"); toBreak = 1; } } printf("after nested if's\n"); down(init->bin_sem); printf("in bin_sem and before consume\n"); if (toBreak != 1){ theCharacter = consume(init->from); } printf("after consume\n"); if (theCharacter == '\n'){ produce(init->to, &space); } else{ produce(init->to, &theCharacter); } up(init->bin_sem); printf("out of bin_sem\n"); printf("exit else if\n"); } printf("exit while\n"); // lets next buffer know when to stop consuming *(init->to->doneInserting) = 1; //done, exit thread printf("EXIT NL\n"); st_thread_exit(NULL); }
void *carriageToSpace(void *s){ printf("Thread_2: carriageToSpace \n"); thread_Producer_Consumer_init *p = s; char processingTank; while (1) { withdrawalCirBuf(&processingTank, p->buffer_C); if (processingTank =='\n') { processingTank = ' '; } depositCirBuf(p->buffer_P, processingTank); if (processingTank==EOF) { break; } } printf("Thread 2: carriageToSpace Existing\n"); st_thread_exit(NULL); }
void _st_thread_main(void) { _st_thread_t *thread = _ST_CURRENT_THREAD(); /* * Cap the stack by zeroing out the saved return address register * value. This allows some debugging/profiling tools to know when * to stop unwinding the stack. It's a no-op on most platforms. */ MD_CAP_STACK(&thread); /* Run thread main */ thread->retval = (*thread->start)(thread->arg); /* All done, time to go away */ st_thread_exit(thread->retval); }
void *print80CharLines(void *t){ ThreadInit *init = t; char theCharacter; char toPrint[LINE_TO_PRINT_SIZE + 1] = ""; // +1 for null-termination int index = 0; int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break // printf("from done inserting?[%d]\n", *(init->from->doneInserting)); // printf("from numElements?[%d]\n", *(init->from->numElements)); down(init->from_bin_sem); if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)){ toBreak = 1; } } if (toBreak == 0){ //extra consume called after asterisk is called up(init->from_bin_sem); //deadlock here printf("about to call consume\n"); //don't want to call consume if asterisks is done and //nothing is there... theCharacter = consume(init->from); printf("consumed: [%c]\n", theCharacter); toPrint[index] = theCharacter; // printf("char[%c], index[%d]\n", theCharacter, index); index++; if (index == LINE_TO_PRINT_SIZE){ toPrint[80] = '\0'; // terminates string printf("%s\n", toPrint); toPrint[0] = '\0'; // resets string index = 0; } } } // done, exit thread printf("EXIT PRINT\n"); st_thread_exit(NULL); }
void *asterisksToCarat(void *t){ ThreadInit *init = t; char theCharacter; char nextCharacter; char carat = '^'; //used for produce() if it needs a carat char null = '\0'; int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)) toBreak = 1; } if (toBreak == 0){ down(init->bin_sem); theCharacter = consume(init->from); if (theCharacter == '*'){ nextCharacter = consume(init->from); if (nextCharacter == '*'){ produce(init->to, &carat); } else { produce(init->to, &theCharacter); produce(init->to, &nextCharacter); } } else{ printf("producing: [%c]\n", theCharacter); produce(init->to, &theCharacter); } up(init->bin_sem); } } // lets next buffer know when to stop consuming down(init->bin_sem); *(init->to->doneInserting) = 1; up(init->bin_sem); // done, exit thread printf("EXIT ASTERISK\n"); st_thread_exit(NULL); }
// thread to get input from stdin void *getInput(void *t){ ThreadInit *init = t; int theCharacter; int count = 0; while(theCharacter != EOF){ down(init->bin_sem); theCharacter = getchar(); produce(init->to, &theCharacter); count++; up(init->bin_sem); } // lets next buffer know when to stop consuming *(init->to->doneInserting) = 1; // done, exit thread printf("EXIT INPUT\n"); st_thread_exit(NULL); }
// function called by the increment thread // increments the counter, prints the current value, and then // sleeps for some time. void *increment_thread_func(void *s) { ThreadInit *init = s; // cast the void pointer to keep compiler happy int num_inc; for (num_inc = 0; num_inc < DEFAULT_NUM_ITERS; num_inc++) { // decrement the semaphore down(init->bin_sem); // dereference the value pointer, then increment it (*(init->value_ptr))++; // print the current value fprintf(init->output_stream, "%d\n", (*(init->value_ptr))); fflush(init->output_stream); // increment the semaphore up(init->bin_sem); // wait some time st_usleep(INC_SLEEP_TIME); } // all done - thread exits st_thread_exit(NULL); }
void *pong(void *s) { thread_init *p = s; /* p has the proper type instead of void */ char sync_char[1]; bool forever = true; while (forever) { BB_get(sync_char); if (quit) break; assert(sync_char[0] == 'S'); printf("%s\n", p->my_call); } printf("Pong exiting\n"); fflush(stdout); st_thread_exit(NULL); }
void *print80CharLines(void *t){ ThreadInit *init = t; char theCharacter; char toPrint[LINE_TO_PRINT_SIZE + 1] = ""; // +1 for null-termination int index = 0; int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break down(init->from_bin_sem); if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)){ toBreak = 1; } } if (toBreak == 0){ up(init->from_bin_sem); //only call consume if there are elements to be consumed if(*(init->from->numElements) != 0){ theCharacter = consume(init->from); //puts character in the buffer to print if(theCharacter != EOF){ toPrint[index] = theCharacter; index++; } if (index == LINE_TO_PRINT_SIZE){ toPrint[80] = '\0'; // terminates string printf("%s\n", toPrint); toPrint[0] = '\0'; // resets string index = 0; } } } } // done, exit thread st_thread_exit(NULL); }
//the first of the two processing functions: takes in a character in ascii and processes whether the character is a newline //and if it is, it will pass along a space otherwise it passes the character. Ends on EOF after passing it along // //Modifier void *firstproc_thread_func (void *s){ ThreadInit *i = s; int c = 0; int space = 32; while(1) { //assert there must be at least one full buff if full buffers down passes //so read has run at least once and called full buffers up c = consumeChar(i); //do our processing, pass the space if we meet a newline if (c == '\n') produceChar(i, space); //we can assert that we know the buffer isn't full //by similar logic as the above. This is the only thread that //writes to it and if empty buffers passes, second process thread function has run else produceChar(i ,c); if (c == EOF) break; } st_thread_exit(NULL); }
// thread to change newlines to spaces void *newlineToSpace(void *t){ ThreadInit *init = t; char theCharacter; char space = ' '; // used for produce() in the case it needs a space int toBreak = 0; // toBreak is boolean initialized to FALSE while(toBreak == 0) { //if "from" is done inserting, and there are no elements, break down(init->from_bin_sem); if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)){ toBreak = 1; } } if (toBreak == 0){ // do only if toBreak is FALSE theCharacter = consume(init->from); down(init->to_bin_sem); if (theCharacter == '\n'){ produce(init->to, &space); } else{ produce(init->to, &theCharacter); } // printf("elements after nl produce: [%d]\n", *init->to->numElements); up(init->to_bin_sem); } up(init->from_bin_sem); } // lets next buffer know when to stop consuming down(init->to_bin_sem); *(init->to->doneInserting) = 1; up(init->to_bin_sem); //done, exit thread printf("EXIT NL\n"); st_thread_exit(NULL); }
void *ping(void *s) { thread_init *p = s; /* p has the proper type instead of void */ int i; int sleep_time; char sync[1] = {'S'}; unsigned int rand_seed = p->my_seed; for (i = 0; i < p->count; i++) { sleep_time = 1 + (rand_r(&rand_seed) % p->max_sleep); printf("%s (Delay %d seconds before & after Pong thread)\n", p->my_call, sleep_time); st_sleep(sleep_time); BB_put(sync); st_sleep(sleep_time); /* give pong a chance to run */ } quit = true; printf("Ping exiting\n"); BB_put(sync); fflush(stdout); st_thread_exit(NULL); }
void *inputProcessing(void *s){ thread_Producer_Consumer_init *p = s; char inputReceiver = 0; printf("%s\n%s\n%s\n",ruler,"Welcome to Duo's HW4 ([email protected]) ",ruler); printf("Thread_1: inputProcessing \n"); printf("Please Enter: \n"); while (1) { if (fscanf(stdin, "%1c", &inputReceiver)==EOF) { inputReceiver = EOF; } depositCirBuf(p->buffer_P, inputReceiver); //Semaphore and mutex included if (inputReceiver==EOF) { break; } if (inputReceiver=='\n') { st_sleep(WAIT_TIME); printf("Please Continue to Enter: \n"); } } printf("Thread 1: inputProcessing Existing\n"); st_thread_exit(NULL); }
void *print80CharLines(void *t){ ThreadInit *init = t; char theCharacter; char toPrint[LINE_TO_PRINT_SIZE + 1] = ""; // +1 for null-termination int index = 0; int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)) toBreak = 1; } else { printf("in print while\n"); down(init->bin_sem); printf("in print bin_sem\n"); theCharacter = consume(init->from); printf("after print consume\n"); toPrint[index] = theCharacter; index++; if (index == LINE_TO_PRINT_SIZE){ toPrint[80] = '\0'; // terminates string printf("%s\n", toPrint); toPrint[0] = '\0'; // resets string } up(init->bin_sem); printf("exit print bin_sem\n"); } } // done, exit thread printf("EXIT PRINT\n"); st_thread_exit(NULL); }
//**See documentation above for produces and consumes** // //Define these functions //read function: takess in raw characters and turns them into ascii code which it passes //to the first-processing thread. Ends at EOF asfter passing it along // //Observer void *read_thread_func (void *s){ IOThreadInit *i = s; //keep the compiler from whining about void stuf int c; while (1){ //we can assert that there's a empty buffer for two reasons //first, this is the only thread that produces to it so no other one can touch it //second, if the empty buffers semaphore here passes its down, it means the first processing //thread has run empty buffers up so at least one caracter has to have been consumed c = fgetc(INPUT); down(i->emptybuffs); down(i->mutex); cbProduce(i->buffer, c); up(i->mutex); up(i->fullbuffs); if (c == EOF) break; //by ending at EOF, we will pass the final WOF character which we'll use to end the program //This also helps assert when the threads should end because we can say that after EOF has //passed through the previous thread, we know there's no more to be processed } st_thread_exit(NULL); }
main(){ // initialize the ST library runtime, necessary for up() and down() st_init(); //BoundedBuffer into which input from stdin is stored BoundedBuffer theInput; createBuffer(&theInput, MAX_BUFF_SIZE); // create a binary semaphore for use with input thread semaphore input_sem; createSem(&input_sem, 1); ThreadInit getInputThread = { NULL, // no input buffer for getInput thread, comes from stdin &theInput, // puts data from stdin into BoundedBuffer theInput NULL, //no "from" semaphore &input_sem //mutual exclusion for input buffer }; // create input thread if (st_thread_create(getInput, &getInputThread, 0, 0) == NULL){ perror("st_thread_create for getInput failure"); exit(1); } // BoundedBuffer into which processed data w/o newlines are stored BoundedBuffer newLinesProcessed; createBuffer(&newLinesProcessed, MAX_BUFF_SIZE); // create binary semaphore for use with newline thread semaphore nl_sem; createSem(&nl_sem, 1); ThreadInit nlToSpaceThread = { &theInput, // processes input from the BoundedBuffer theInput &newLinesProcessed, // puts processed data into BB newLinesProcessed &input_sem, //mutual exclusion for input buffer &nl_sem // mutual exclusion for processed newlines buffer }; //create newline processing thread if (st_thread_create(newlineToSpace, &nlToSpaceThread,0,0) == NULL){ perror("st_thread_create for newlineToSpace failure"); exit(1); } // BoundedBuffer into which processed data after asterisks are handled go BoundedBuffer caratsProcessed; createBuffer(&caratsProcessed, MAX_BUFF_SIZE); // create binary semaphore for use with newline thread semaphore carat_sem; createSem(&carat_sem, 1); ThreadInit caratThread = { &newLinesProcessed, // buffer from wich input is processed &caratsProcessed, // puts processed data into BB caratsProcessed &nl_sem, // for mutual exclusion in previous buffer &carat_sem // for mutual exclusion in processed carat buffer }; // create asterisks to carat processing thread if (st_thread_create(asterisksToCarat, &caratThread,0,0) == NULL){ perror("st_thread_create for newlineToSpace failure"); exit(1); } ThreadInit printThread = { &caratsProcessed, // buffer from which input is processed NULL, // no output buffer, just printing to stdout &carat_sem, // for mutual exclusion in previous buffer NULL // no mutex needed, just printing to stdout }; // create print thread if (st_thread_create(print80CharLines, &printThread,0,0) == NULL){ perror("st_thread_create for print80CharLines failure"); exit(1); } // exit main thread st_thread_exit(NULL); }
//thread to change asterisks to carats void *asterisksToCarat(void *t){ ThreadInit *init = t; char theCharacter; char nextCharacter; char carat = '^'; //used for produce() if it needs a carat int toBreak = 0; while(toBreak == 0) { //if from is done inserting and there are no elements, break down(init->from_bin_sem); //printf("ast. done inserting?[%d]\n", *(init->from->doneInserting)); //printf("ast. numElements?[%d]\n", *(init->from->numElements)); if( *(init->from->doneInserting) == 1){ if( (*init->from->numElements == 0)) toBreak = 1; } if (toBreak == 0){ up(init->from_bin_sem); theCharacter = consume(init->from); if (theCharacter == '*'){ nextCharacter = consume(init->from); if (nextCharacter == '*'){ // if two successive asterisks printf("producing: [%c]\n", carat); down(init->to_bin_sem); produce(init->to, &carat); } else { // if they're not both asterisks down(init->to_bin_sem); printf("producing: [%c]\n", theCharacter); produce(init->to, &theCharacter); printf("producing: [%c]\n", nextCharacter); produce(init->to, &nextCharacter); } } else { //the character was not an asterisk down(init->to_bin_sem); printf("ast. producing: [%c]\n", theCharacter); produce(init->to, &theCharacter); //pretty sure produce context switches to waiting print func. //so this is always 0, even though it's being updated right printf("elems. after ast. produce: [%d]\n", *(init->to->numElements)); } up(init->to_bin_sem); } up(init->from_bin_sem); } // lets next buffer know when to stop consuming down(init->to_bin_sem); *(init->to->doneInserting) = 1; up(init->to_bin_sem); char theNull = '\0'; produce(init->to, &theNull); // done, exit thread printf("EXIT ASTERISK\n"); st_thread_exit(NULL); }
int main(int argc, char *argv[]) { int loop_count; int sleep_secs; int buffer_size; const int ping_arg = 1; const int pong_arg = 2; const int loop_arg = 3; const int sleep_arg = 4; const int size_arg = 5; thread_init ping_init; thread_init pong_init; /* validity check parameter count */ if (argc != NUM_ARGS) { printf("Bad parameter count %d\n", argc); printf("Positional parameters: ping & pong strings, loop count, sleep limit, buffer size\n"); exit (ERR_RETURN); } /* the loop count is the third positional parameter */ loop_count = atoi(argv[loop_arg]); /* atoi converts string to integer */ /* the sleep limit seconds is the fourth positional */ sleep_secs = atoi(argv[sleep_arg]); /* atoi converts string to integer */ if (sleep_secs > MAX_SLEEP) { printf("Sleep of %d exceeds maximum %d\n", sleep_secs, MAX_SLEEP); exit (ERR_RETURN); } /* the buffer size is the fifth positional */ buffer_size = atoi(argv[size_arg]); /* atoi converts string to integer */ /* This call is required to initialize the thread library */ if (st_init() < 0) { perror("st_init"); exit(1); } /* This call is required to initialize the bounded buffer. * The size (in characters) may be set to any value between * one and MAX_BUFFER (defined in BB.h). The call must be * made AFTER the st_init() call and BEFORE any producers or * consumers using the bounded buffer are started. */ if (BB_init(buffer_size) != 0) { printf("Buffer size initializer %d not in valid range\n", buffer_size); exit(-1); } /* Create a separate thread for each of ping and pong */ /* create an initializer for pong thread */ pong_init.my_call = argv[pong_arg]; pong_init.my_seed = 0; /* not used by pong */ pong_init.count = 0; /* not used by pong */ pong_init.max_sleep = 0; /* not used by pong */ /* start it first so it will block first * The first parameter is the initial function executed in * the thread. The second is the only allowed parameter to * the initial function and must be a pointer to any type. */ if (st_thread_create(pong, &pong_init, 0, 0) == NULL) { perror("st_thread_create"); exit(1); } /* create an initializer for ping thread */ ping_init.my_call = argv[ping_arg]; ping_init.my_seed = (unsigned int) getpid(); /* unique random seed each run */ ping_init.count = loop_count; ping_init.max_sleep = sleep_secs; if (st_thread_create(ping, &ping_init, 0, 0) == NULL) { perror("st_thread_create"); exit(1); } /* causes the main thread to exit with others still running */ printf("Main thread exiting\n"); fflush(stdout); st_thread_exit(NULL); }