//*************************************************************** // From the book "Win32 System Services: The Heart of Windows 98 // and Windows 2000" // by Marshall Brain // Published by Prentice Hall // // Copyright 1995, by Prentice Hall. // // This code multi-threads the mandelbrot application so that // one thread handles the user interface while multiple // threads handle redrawing, depending on the number of // processors. //*************************************************************** // mandel2.cpp #include #include "menus.h" #define NUM_ITERATIONS 64 const double left = -1.0; const double right = 1.0; const double top = -1.0; const double bottom = 1.0; DWORD colors[64]; BOOL quit; typedef struct { double real; double imag; } complex; typedef struct { double xstep; double ystep; WORD height; double startpoint; WORD startpos; } mandelParams; // Define the application object class class CManApp : public CWinApp { public: virtual BOOL InitInstance(); }; // Define the edit window class class CManWindow : public CFrameWnd { private: DWORD numThreads; HANDLE *threadHandles; BOOL initialized; public: CManWindow(); void RunMandel(); void SetPix(int x, int y, WORD iter); afx_msg void OnPaint(); afx_msg void OnDoDraw(); afx_msg void OnExit(); DECLARE_MESSAGE_MAP() }; // Create an instance of the application object CManApp manApp; // member function which sets pixel colors // in the window void CManWindow::SetPix(int x, int y, WORD iter) { CClientDC dc(this); dc.SetPixel(x, y, colors[iter]); } // thread function which draws on the window DWORD MandelThread(mandelParams *p) { double x, y; int i,j; WORD iter; complex k; complex z; double real, imag, spread; for (y=p->startpoint, j=p->startpos; y <= (p->startpoint + p->height*p->ystep); y += p->ystep, j++) { for (x=left, i=0; x<=right; x += p->xstep, i++) { k.real = x; k.imag = y; z.real=z.imag=0.0; for (iter=0; iter 4.0) break; } ((CManWindow *)manApp.m_pMainWnd)-> SetPix(i, j, iter); if (quit) { GlobalFree(p); return(0); } } } return(0); } // member function which instigates the thread(s) void CManWindow::RunMandel() { DWORD threadID; SYSTEM_INFO sysInfo; CRect r; WORD n; WORD height; double xstep, ystep; mandelParams *params; GetSystemInfo(&sysInfo); numThreads=sysInfo.dwNumberOfProcessors; if (numThreads==1) numThreads=4; quit=FALSE; threadHandles=(HANDLE *) GlobalAlloc(GPTR, (sizeof(HANDLE)*numThreads)); GetClientRect(&r); xstep=(right - left)/double(r.Width()); ystep=(bottom - top)/double(r.Height()); height=r.Height()/(WORD)numThreads; for(n=0; nxstep=xstep; params->ystep=ystep; params->height=height; params->startpoint=top + height*ystep*n; params->startpos=height*n; threadHandles[n]=CreateThread(0, 0, (LPTHREAD_START_ROUTINE) MandelThread, params, 0, &threadID); } } // The message map BEGIN_MESSAGE_MAP(CManWindow, CFrameWnd) ON_WM_PAINT() ON_COMMAND(IDM_DODRAW, OnDoDraw) ON_COMMAND(IDM_EXIT, OnExit) END_MESSAGE_MAP() // Handler for the Start/Stop menu option void CManWindow::OnDoDraw() { if (!initialized) { initialized=TRUE; RunMandel(); } else { WORD n; // wait for and stop all existing threads quit=TRUE; WaitForMultipleObjects(numThreads, threadHandles, TRUE, INFINITE); for (n=0; n ShowWindow( m_nCmdShow ); m_pMainWnd -> UpdateWindow(); return TRUE; }