home *** CD-ROM | disk | FTP | other *** search
- // mtgdivw.cpp : implementation of the CThreadView class
- //
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
- #include "mtgdi.h"
-
- #include "mtgdidoc.h"
- #include "mtgdivw.h"
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // CThreadView
-
- IMPLEMENT_DYNCREATE(CThreadView, CView)
-
- BEGIN_MESSAGE_MAP(CThreadView, CView)
- //{{AFX_MSG_MAP(CThreadView)
- ON_COMMAND(ID_THREAD_NEWBALL, OnNewball)
- ON_COMMAND(ID_THREAD_KILLTHREADS, OnKillThreads)
- ON_WM_DESTROY()
- ON_COMMAND(ID_THREAD_NEWLINE, OnNewline)
- ON_COMMAND(ID_THREAD_NEWRECTANGLE, OnNewrectangle)
- ON_COMMAND(ID_THREAD_10NEWBALLS, On10newballs)
- ON_COMMAND(ID_THREAD_10NEWLINES, On10newlines)
- ON_COMMAND(ID_THREAD_10NEWRECTANGLES, On10newrectangles)
- ON_WM_CREATE()
- ON_WM_SIZE()
- ON_COMMAND(ID_THREAD_25NEWBALLS, On25newballs)
- ON_COMMAND(ID_THREAD_25NEWLINES, On25newlines)
- ON_COMMAND(ID_THREAD_25NEWRECTANGLES, On25newrectangles)
- ON_COMMAND(ID_THREAD_KILLTHREADSSLOW, OnThreadKillThreadsSlow)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // CThreadView construction/destruction
-
- CThreadView::CThreadView()
- {
- m_pDC = NULL;
- }
-
- CThreadView::~CThreadView()
- {
- }
-
- void CThreadView::UpdateTitle(int nThreads)
- {
- if (nThreads == -1)
- nThreads = m_threadList.GetCount();
-
- CString strCaption;
- if (nThreads != 0)
- {
- CString strFormat; strFormat.LoadString(IDS_CAPTION_FORMAT);
- strCaption.Format(strFormat, nThreads);
- }
- else
- strCaption.LoadString(IDS_CAPTION_NOTHREADS);
-
- GetParentFrame()->SetWindowText(strCaption);
- }
-
- void CThreadView::StartThread(int ThreadID)
- {
- CGDIThread* pThread;
- CPoint Pos(rand()%100,rand()%100);
- CPoint Vel1((rand()%10)+2,(rand()%10)+2);
- CPoint Vel2((rand()%5)+2,(rand()%5)+2);
- CSize Size(((rand()%60)+20),((rand()%60)+20));
- COLORREF Color;
-
- //BLOCK: calculate random color
- {
- int r,g,b;
-
- do
- {
- r = (rand()%3);
- r = (r!=0) ? (r==2) ? 255 : 127 : 0;
-
- g = (rand()%3);
- g = (g!=0) ? (g==2) ? 255 : 127 : 0;
-
- b = (rand()%3);
- b = (b!=0) ? (b==2) ? 255 : 127 : 0;
- }
- while ((r==g) && (g==b));
- // No white(255,255,255), gray(127,127,127), or black(0,0,0) allowed
-
- Color = RGB(r,g,b);
- }
-
- if (rand()%1) Vel1.x*=-1;
- if (rand()%1) Vel1.y*=-1;
- if (rand()%1) Vel2.x*=-1;
- if (rand()%1) Vel2.y*=-1;
-
- switch(ThreadID)
- {
- case 1:
- pThread = new CBallThread(this,
- m_pDC->GetSafeHdc(), Pos, Vel1, Size, Color);
- break;
- case 2:
- pThread = new CRectThread(this,
- m_pDC->GetSafeHdc(), Pos, Vel1, Size, Color);
- break;
- case 3:
- pThread = new CLineThread(this,
- m_pDC->GetSafeHdc(), Pos, Vel1, Vel2, Size, Color);
- break;
- }
-
- if (pThread == NULL)
- return;
-
- ASSERT_VALID(pThread);
- pThread->m_pThreadParams = NULL;
-
- // Create Thread in a suspended state so we can set the Priority
- // before it starts getting away from us
- if (!pThread->CreateThread(CREATE_SUSPENDED))
- {
- delete pThread;
- return;
- }
-
- // since everything is successful, add the thread to our list
- m_threadList.AddTail(pThread);
-
- // If you want to make the sample more sprightly, set the thread priority here
- // a little higher. It has been set at idle priority to keep from bogging down
- // other apps that may also be running.
- VERIFY(pThread->SetThreadPriority(THREAD_PRIORITY_IDLE));
- // Now the thread can run wild
- pThread->ResumeThread();
- }
-
- void CThreadView::OnDraw(CDC*)
- {
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CThreadView diagnostics
-
- #ifdef _DEBUG
- void CThreadView::AssertValid() const
- {
- CView::AssertValid();
- }
-
- void CThreadView::Dump(CDumpContext& dc) const
- {
- CView::Dump(dc);
- }
-
- CThreadDoc* CThreadView::GetDocument() // non-debug version is inline
- {
- return STATIC_DOWNCAST(CThreadDoc, m_pDocument);
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CThreadView message handlers
-
- void CThreadView::OnNewball()
- {
- StartThread(1);
- UpdateTitle();
- }
-
- void CThreadView::On10newballs()
- {
- for (int i = 0; i < 10; i++)
- {
- StartThread(1);
- UpdateTitle();
- }
- }
-
- void CThreadView::On25newballs()
- {
- for (int i = 0; i < 25; i++)
- {
- StartThread(1);
- UpdateTitle();
- }
- }
-
- void CThreadView::OnNewrectangle()
- {
- StartThread(2);
- UpdateTitle();
- }
-
- void CThreadView::On10newrectangles()
- {
- for (int i = 0; i < 10; i++)
- {
- StartThread(2);
- UpdateTitle();
- }
- }
-
- void CThreadView::On25newrectangles()
- {
- for (int i = 0; i < 25; i++)
- {
- StartThread(2);
- UpdateTitle();
- }
- }
-
- void CThreadView::OnNewline()
- {
- StartThread(3);
- UpdateTitle();
- }
-
- void CThreadView::On10newlines()
- {
- for (int i = 0 ;i < 10; i++)
- {
- StartThread(3);
- UpdateTitle();
- }
- }
-
- void CThreadView::On25newlines()
- {
- for (int i = 0; i < 25; i++)
- {
- StartThread(3);
- UpdateTitle();
- }
- }
-
- // A preferred method for killing many threads. Tell them to go away all
- // at once, then wait for them all to be scheduled and to terminate
- // themselves. This is much, much faster than the more straight forward
- // way of asking just one to terminate, then waiting for it to do so.
- // It is also a little bit more complex.
-
- void CThreadView::OnKillThreads()
- {
- // tell all threads to shutdown
- for (POSITION pos = m_threadList.GetHeadPosition(); pos != NULL; )
- {
- CGDIThread* pThread = m_threadList.GetNext(pos);
- VERIFY(SetEvent(pThread->m_hEventKill));
- }
-
- // wait for all threads to finish shutdown
- for (int nThreadsLeft = m_threadList.GetCount(); nThreadsLeft != 0; )
- {
- WaitForSingleObject(CGDIThread::m_hAnotherDead, INFINITE);
- Sleep(nThreadsLeft*2);// 200ms for every 100 threads
- nThreadsLeft = 0;
- for (pos = m_threadList.GetHeadPosition(); pos != NULL; )
- {
- CGDIThread* pThread = m_threadList.GetNext(pos);
- if (WaitForSingleObject(pThread->m_hEventDead, 0) == WAIT_TIMEOUT)
- ++nThreadsLeft;
- }
- UpdateTitle(nThreadsLeft);
- }
-
- // delete all thread objects
- while (!m_threadList.IsEmpty())
- {
- CGDIThread* pThread = m_threadList.RemoveHead();
- VERIFY(WaitForSingleObject(pThread->m_hThread, INFINITE) == WAIT_OBJECT_0);
- delete pThread;
- }
- UpdateTitle();
-
- // invalidate the window since all threads are now gone
- Invalidate();
- }
-
- // KillThreadsSlow is much easier to understand since the process of
- // killing a thread is encapsulated in KillThread. If you get more
- // than 50 threads running, however, you'll notice quite a difference
- // between this method and the one above.
-
- void CThreadView::OnThreadKillThreadsSlow()
- {
- // Iterate through the threads killing each
- // KillThread doesn't return until the Thread is dead
- while (!m_threadList.IsEmpty())
- {
- m_threadList.RemoveHead()->KillThread();
- UpdateTitle();
- }
-
- // Invalidate the window so it blanks the window
- Invalidate();
- }
-
- void CThreadView::OnDestroy()
- {
- OnKillThreads();
-
- delete m_pDC;
- m_pDC = NULL;
-
- CView::OnDestroy();
- }
-
- int CThreadView::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CView::OnCreate(lpCreateStruct) == -1)
- return -1;
-
- // m_pDC must be initialized here instead of the constructor
- // because the HWND isn't created until Create is called.
- m_pDC = new CClientDC(this);
- UpdateTitle();
-
- return 0;
- }
-
- void CThreadView::OnSize(UINT nType, int cx, int cy)
- {
- CView::OnSize(nType, cx, cy);
-
- // Instead of getting the client rect every time we draw, we only
- // update it when it changes.
- for (POSITION pos = m_threadList.GetHeadPosition(); pos != NULL; )
- m_threadList.GetNext(pos)->UpdateBorder();
- }
-