/* File: ~liux/public_html/courses/cop4610/examples/simple-pthread.cc Purpose: Demonstrate how to create multiple threads in UNIX for COP4610 Author: Xiuwen Liu On the web: http://www.cs.fsu.edu/~liux/courses/cop4610/examples/simple-pthread.cc Command to complie (Pay attention to -lpthread): g++ -o simple-pthread simple-pthread.cc -lpthread */ #include #include #include #include #include #include //#include #include #include #include int NUM_THREADS; pthread_t *tid; /* array of thread IDs */ int *performed_transactions; int totalTransaction; int *accounts; /* Account balances */ void * RandomTransaction(void *msg); int PerformATransaction(int from, int to, int val); int CheckRunning(void); typedef struct { int acct; } PARA_INFO; int mutex_lock_flag; int main(int argc, char *argv[]) { pthread_attr_t attr; PARA_INFO *info; int i, sum; int c; extern char *optarg; extern int optind; unsigned int seed; mutex_lock_flag = 0; seed = 100; NUM_THREADS = 5; while ((c = getopt(argc, argv, "ms:t:")) != EOF) { switch(c) { case 'm': mutex_lock_flag = 1; break; case 's': seed = atoi(optarg); break; case 't': NUM_THREADS= atoi(optarg); break; default: printf("%c is not valid option.\n"); } } printf("Initializing with seed %d\n", seed); srandom(seed); printf("Total number of threads is %d\n", NUM_THREADS); tid = (pthread_t *)malloc(sizeof(pthread_t) * NUM_THREADS); performed_transactions = (int *)malloc(sizeof(int)*NUM_THREADS); accounts = (int *)malloc(sizeof(int)*NUM_THREADS); info = (PARA_INFO *)malloc(sizeof(PARA_INFO)*NUM_THREADS); totalTransaction = 0; for (i=0; i < NUM_THREADS; i++) { accounts[i] = 1000; performed_transactions[i] = 0; } sum =0; for (i=0; i< NUM_THREADS; i++) { cout << "\n\tInit account " << i+1 << "'s balance: " << accounts[i]; sum += accounts[i]; } cout <<"\n\tTotal initial balance is " << sum << endl; pthread_attr_init(&attr); for (i=0; i < NUM_THREADS; i++) { info[i].acct = i; if (pthread_create(&(tid[i]), &attr, RandomTransaction, (void *)(&(info[i]))) <0) { perror("create thread: "); return -1; } } pthread_attr_destroy(&attr); for (i=0; i < NUM_THREADS; i++) { pthread_join((pthread_t)tid[i], (void **)NULL); } for (i=0; i < NUM_THREADS; i++) { cout << "\nAccount " << i+1 << " performed " << performed_transactions[i]; } cout << "\n"; return 0; } void * RandomTransaction(void *msg) { pthread_t current_thr; int myAcct, toAcct; int amount; PARA_INFO *info; info = (PARA_INFO *)msg; current_thr = pthread_self(); myAcct = info->acct; if (myAcct >= NUM_THREADS) { cerr << "Something must be wrong with the thread IDs.\n"; return (void *)NULL; } cout << "Thread " << pthread_self() << " with account " << myAcct << " is running.\n"; do { /* First figure out my account number */ do { toAcct = ((int)random())%NUM_THREADS; } while (myAcct == toAcct); amount = (int)(random()%10+10); PerformATransaction(myAcct, toAcct, amount); } while(CheckRunning()); return (void *)NULL; } int PerformATransaction(int from, int to, int val) { int i, sum; if (accounts[from] < val) { //pthread_yield(); if (random()&0x01) sleep(1); return -1; } performed_transactions[from]++; totalTransaction++; if ((totalTransaction %1) == 0) { sum =0; cout << "\n from (" << pthread_self() << ") Now " << totalTransaction << " transactions have been completed."; for (i=0; i < NUM_THREADS; i++) { cout << "\n\tAccount " << i+1 << "'s balance: " << accounts[i]; sum += accounts[i]; } cout << "\n\tTotal balance after " << totalTransaction << " transactions is " << sum << endl; } accounts[from] -= val; // pthread_yield(); if (random()%2==0) sleep(1); accounts[to] += val; return 0; } int CheckRunning(void) { int i; i = (int)(totalTransaction < 10); return i; }