/* 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;
}