/////////////////////////////////////////////////////////////// // // // evsynch.cpp - demonstration of threads synchronized // // ver 1.0 with an event object // // // // Language: Visual C, ver 6.0 // // Platform: Micron Dual Pentium Pro 200, Win NT 4.0 // // Application: CSE691 Project #1 // // Author: Jim Fawcett, Instructor, CSE691, Fall '99 // // CST 2-187, Syracuse Univ, (315) 443-3948 // // fawcett@ecs.syr.edu // // // /////////////////////////////////////////////////////////////// // build process // /////////////////////////////////////////////////////////////// // required files: // // evsynch.cpp, Win32utils.h, Win32utils.cpp // // // // building in IDE: // // - build Win32 Application project // // - add these files to project // // - change Project\Settings\C/C++\Category: // // Code Generation = Debug Mulitthreaded // // - compile, line, and run // /////////////////////////////////////////////////////////////// /* Maintenance History: ==================== ver 1.0 : 06 Nov 99 - first release */ #include #include #include #include "Win32utils.h" using namespace std; //----< forward reference of windows processing function >----- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // //----< entry point >------------------------------------------ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; // declare handle to window MSG msg; // declare message structure // build window class structure WNDCLASSEX wndclass; static char szAppName[] = "synchronization"; wndclass.cbSize = sizeof (wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION); // register window class RegisterClassEx (&wndclass); // create main window at specified location with specified size hwnd = CreateWindow (szAppName, szAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 200, 200, 550, 200, NULL, NULL, hInstance, NULL); // display window ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); // start message loop while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } // //----< structure for passing arguments to thread function >--- struct thARGS { HWND hwnd; string str; HANDLE hEvent; }; //----< thread function >-------------------------------------- // // here is where shared string text gets corrupted // if there is no program synchronization of access // unsigned int __stdcall thProc(void *args) { static string text; // shared resource thARGS *pArgs = (thARGS*)args; // structure of arguments // each thread adds its own word to string const int RESTART_SIZE = 60; while(1) { WaitForSingleObject(pArgs->hEvent,INFINITE); if(text.size() < RESTART_SIZE) text += pArgs->str; else text = pArgs->str; SetEvent(pArgs->hEvent); // this user-defined message passes a pointer to the // text string and asks windows to repaint client area // // note that we could just do this message's activities // here because we have a handle to the window. However // it is a much better idea to handle all messages in // one place, e.g., in WinProc PostMessage(pArgs->hwnd,WM_USER,(WPARAM)&text,0); Sleep(50); } return 0; } // //----< process messages for main window >--------------------- LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hDC; PAINTSTRUCT ps; RECT rect; GetClientRect(hwnd,&rect); HANDLE thHandle[2]; unsigned int thID1, thID2; static struct thARGS args1, args2; HANDLE hEvent = 0; static string *pString = NULL; char *temp = "synchronization with event object"; switch (iMsg) { case WM_CREATE : hEvent = CreateEvent(0,FALSE,TRUE,0); if(hEvent == NULL) { showSysError("error creating event object: ",GetLastError()); exit(1); } args1.hwnd = hwnd; args1.str = "first "; args1.hEvent = hEvent; args2.hwnd = hwnd; args2.str = "second "; args2.hEvent = hEvent; thHandle[0] = (HANDLE)_beginthreadex(NULL,0,thProc,&args1,0,&thID1); thHandle[1] = (HANDLE)_beginthreadex(NULL,0,thProc,&args2,0,&thID2); return 0; case WM_SIZE : rect.right = LOWORD (lParam); rect.bottom = HIWORD (lParam); return 0; case WM_USER : pString = (string*)wParam; InvalidateRect(hwnd,&rect,TRUE); return 0; case WM_PAINT : hDC = BeginPaint(hwnd,&ps); TextOut(hDC,10,10,temp,strlen(temp)); if(pString == NULL) return 0; WaitForSingleObject(hEvent,INFINITE); TextOut(hDC,30,70,pString->c_str(),pString->size()); SetEvent(hEvent); EndPaint(hwnd,&ps); return 0; case WM_DESTROY : CloseHandle(hEvent); PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); }