// // Simple program demonstrating the use of threads to // sum the integers 1 through N. // // Command-line arguments are N and P (number of threads). // // This program replaces the global variables of the first // version with variables local to main and passed to the // threads as parameters. // #include #include // has setprecision() #include // has exit(), etc. #include // has pthread_ routines #include // has STL plus, minus, etc. #include "threads-timer.h" // has timer() #include "threads-sharedVar.h" // has sharedVar class #include "threads-threadWrapper.h" // has threadWrapper class // ---- Class for thread --------------------------------------------- class sumThreadObj { public: typedef sumThreadObj * ptr; // member variables are parameters for thread int myID; int N; int P; sharedVar * sum; // will contain (global) sum sumThreadObj(const int myID, const int N, const int P, sharedVar * const sum) { this->myID = myID; this->N = N; this->P = P; this->sum = sum; } // this member function is the code the thread should execute void run(void) { // Computes partial sum of N/P of the elements (starting with // myID+1 and summing every P-th element) and adds it to sum. // Calculate partial sum. double partialSum = 0; for (int i = myID; i <= N; i += P) partialSum += i; // Add to global sum (safeUpdate() uses a lock to ensure that // only one thread at a time has access). sum->safeUpdate(plus(), partialSum); } }; // ---- Main program ------------------------------------------------- int main(int argc, char* argv[]) { int N; // number of numbers to sum int P; // number of threads sharedVar sum(0.0); // sum (double to avoid overflow) // Process command-line arguments. if (argc < 3) { cerr << "Usage: " << argv[0] << " highestNum numThreads\n"; exit(EXIT_FAILURE); } N = atoi(argv[1]); P = atoi(argv[2]); cout << "Summing the first " << N << " positive integers using " << P << " threads:\n"; // Set up to time things. double startTime = timer(); // Initialize sum (no need to lock since only one thread active). sum.data = 0.0; // Start P new threads, each running a wrapper function, with // a sumThreadObj object as parameter. (The wrapper function // just invokes the object's "run()" method.) sumThreadObj::ptr * threadObj = new sumThreadObj::ptr[P]; // parameters for threads pthread_t * threads = new pthread_t[P]; // "handles" for threads for (int i = 0; i < P; ++i) { threadObj[i] = new sumThreadObj(i, N, P, &sum); if (pthread_create(&threads[i], NULL, threadWrapper::run, (void *) threadObj[i]) != 0) cerr << "Unable to create thread " << i << endl; } // Wait for all threads to complete. for (int i = 0; i < P; ++i) { if (pthread_join(threads[i], NULL) != 0) cerr << "Unable to perform join on thread " << i << endl; } // Print results (again, no need to lock since only one thread // active). cout << "Sum = " << setprecision(40) << sum.data << endl; double endTime = timer(); cout << "Elapsed time (seconds) = " << setprecision(4) << endTime - startTime << endl; // Free everything allocated with "new" in this function. for (int i = 0; i < P; ++i) delete threadObj[i]; delete [] threadObj; delete [] threads; return EXIT_SUCCESS; }