I have a C pthread program that creates N threads in main that update a global variable. Main also calls pthread_join on all of these update threads to wait for them to finish. I also have 2 watcher threads that use pthread condition variables to check to see if the global variable goes above or below certain numbers, and if so, it kills all update threads and the other watcher thread. However, I'm having trouble with this last part..killing the other threads. My program does what it is supposed to do but never completes... it just gets stuck. Calling exit(0) at the end of each watcher thread works but I feel like that's too lazy of a solution, I'd really like to learn how to kill other threads from a separate thread and return to main.
Here's my code:
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void *update(void *i);
void *watchIncrease();
void *watchDecrease();
//init globals
double marketValue;
int numThreads;
double *stocks;
double ceiling;
double floor_;
int flag;
pthread_t *threads;
pthread_t watchIncreaseThread;
pthread_t watchDecreaseThread;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t threshold_ceiling;
pthread_cond_t threshold_floor_;
int main(int argc, char **argv){
numThreads = atoi(argv[1]);
int level = atoi(argv[2]);
marketValue = 100 * numThreads;
//initialize personal stocks for threads
stocks = (double *) malloc(sizeof(double) * numThreads);
int i;
for(i = 0; i < numThreads; i++) stocks[i] = 100;
//initialize floor/ceiling
double percent = (double) level / 100;
double cap = marketValue * percent;
ceiling = marketValue + cap;
floor_ = marketValue - cap;
//seed rand()
srand(time(NULL));
//create threads
pthread_cond_init(&threshold_ceiling,NULL);
pthread_cond_init(&threshold_floor_,NULL);
int rc = pthread_create(&watchIncreaseThread,NULL,watchIncrease,NULL);
assert(rc == 0);
rc = pthread_create(&watchDecreaseThread,NULL,watchDecrease,NULL);
assert(rc == 0);
threads = (pthread_t *)malloc(sizeof(pthread_t) * numThreads);
assert(threads != NULL);
for(i = 0; i < numThreads; i++){
int rc = pthread_create(&threads[i],NULL,update,(void *)i);
assert(rc == 0);
}
int j;
for(j = 0; j < numThreads; j++){
pthread_join(threads[j],NULL);
}
return 0;
}
void *update(void *i){
int index = (int)i;
double max = 2;
double val;
while(1){
int rc = pthread_mutex_lock (&lock);
assert(rc == 0);
val = max * ((double)rand()/(double)RAND_MAX - 0.5);
stocks[index] += val;
marketValue += val;
pthread_cond_signal (&threshold_ceiling);
pthread_cond_signal (&threshold_floor_);
pthread_mutex_unlock(&lock);
}
}
void *watchIncrease(){
int rc = pthread_mutex_lock(&lock);
assert(rc == 0);
while(marketValue < ceiling){
pthread_cond_wait(&threshold_ceiling, &lock);
}
printf("Market Up to %.2f\n",marketValue);
int i;
double sum = 0;
for(i = 0; i < numThreads; i++){
sum += stocks[i];
}
printf("Total Market Price of %d stocks: %.2f\n",numThreads,sum);
for(i = 0; i < numThreads; i++){
rc = pthread_cancel(threads[i]);
assert(rc == 0);
}
pthread_cancel(watchDecreaseThread);
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
//exit(0);
}
void *watchDecrease(){
int rc = pthread_mutex_lock(&lock);
assert(rc == 0);
while(marketValue > floor_){
pthread_cond_wait(&threshold_floor_, &lock);
}
printf("Market Down to %.2f\n",marketValue);
int i;
double sum = 0;
for(i = 0; i < numThreads; i++){
sum += stocks[i];
}
printf("Total Market Price of %d stocks: %.2f\n",numThreads,sum);
for(i = 0; i < numThreads; i++){
rc = pthread_cancel(threads[i]);
assert(rc == 0);
}
pthread_cancel(watchIncreaseThread);
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
//exit(0);
}