//////////////////////////////////////////////////////////////////// // simpleSync.cpp - demonstrate threads with synchronization // // // // Jim Fawcett, CSE691 - Software Modeling & Analysis, Fall 2000 // //////////////////////////////////////////////////////////////////// #include #include #include #include #include using namespace std; static CRITICAL_SECTION IOcs; //----< synchronized access to standard out >------------------ template void safeOut(T t) { EnterCriticalSection(&IOcs); cout << t; LeaveCriticalSection(&IOcs); } //----< arguments passed to thread function >------------------ struct ThreadArgList { int threadNum; string threadName; }; //----< thread processing function >--------------------------- unsigned int __stdcall threadProc(void *s) { // retrieve threadProc argument type ThreadArgList *pArgs = (ThreadArgList*)s; // make a string composed of a converted integer followed by a string // uses representation conversions of the stream library // display thread number and name int i; for(i=0; i<25; i++) { ostrstream temp; temp << "output #" << i << ": " << ((pArgs->threadName).c_str()) << '\n' << ends; safeOut(temp.str()); } return 0; } // //----< entry point for process >------------------------------ void main() { cout << "\n Demonstrate the Operation of Mult-threaded Code " << "\n using synchronized access to shared resources" << "\n=================================================\n\n"; // initialize critical section to use for synchronizing // access to the standard output stream, cout // (look at safeOut(...) function, above. InitializeCriticalSection(&IOcs); // define arguments to _beginthreadex void* Security = NULL; // no security attributes unsigned int StackSize = 0; // stack size picked by OS unsigned int(__stdcall threadProc)(void*); // name of thread function unsigned int InitFlag = 0; // start running unsigned int ThreadID; // receives thread id void *ArgList; // pointer to argument list // define argument values for thread #1 threadProc ThreadArgList arg1; arg1.threadNum = 1; arg1.threadName = "thread #1"; ArgList = (void*)&arg1; // define an array of handles to threads, needed to wait // for their completion const int NumHandles = 2; HANDLE thHand[NumHandles]; // start first thread thHand[0] = (HANDLE)_beginthreadex( Security, StackSize, threadProc, ArgList, InitFlag, &ThreadID ); // // define argument values for thread #2 threadProc ThreadArgList arg2; arg2.threadNum = 2; arg2.threadName = "thread #2"; ArgList = (void*)&arg2; // start second thread thHand[1] = (HANDLE)_beginthreadex( Security, StackSize, threadProc, ArgList, InitFlag, &ThreadID ); // tell process to wait for both threads to complete // before terminating BOOL fwait = TRUE; // wait for all handles DWORD timeOut = INFINITE; // time out in milliseconds WaitForMultipleObjects(NumHandles, thHand, fwait, timeOut); // return critical section, handles to OS DeleteCriticalSection(&IOcs); CloseHandle(thHand[0]); CloseHandle(thHand[1]); }