Click here to Skip to main content
15,887,683 members
Articles / Desktop Programming / MFC

Smoov Code Project Screen Saver

Rate me:
Please Sign up or sign in to vote.
4.74/5 (25 votes)
24 May 200212 min read 235.9K   4.1K   77  
Asynchronous XML Web Client Animated Screen Saver in Win32/MFC
// Thread.cpp: implementation of the CThread class, revision 2
//
// Copyright (C) 2002 First Objective Software, Inc. All rights reserved
// Go to www.firstobject.com for the latest version and information
// Retain this disclaimer: This software class is provided as is. No warranty
// You may use this class even in commercial applications, enjoy!

#include "stdafx.h"
#include "Thread.h"
#include <process.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//
// CThread
//
// The parent thread is the one that instantiated the CThread object
// The child thread only exists between Start() and Stop()
// Start() and Stop() are called by the parent thread
// The others are all subroutines of the child thread's StartAddress() function
//
// A CEvent is used to synchronize the threads via two simple methods
// CEvent::Lock() is used by one thread to wait on an event
// CEvent::SetEvent() is used by the other thread to signal (i.e. trigger) the event
//

/////////////////////////////////////////////////////////////////////////////
// Parent thread functions

BOOL CThread::Start()
{
	// Start the thread if it hasn't already been started
	if ( ! m_hThread )
	{
		// Reset cleanup event in case previous thread ended on its own
		m_eventWaitForCleanup.ResetEvent();

		// Start child thread and specify controlling function
		/*
		CWinThread* pThread = AfxBeginThread( StartAddress, this );
		m_dwThreadID = pThread->m_nThreadID;
		m_hThread = pThread->m_hThread;
		*/
		m_hThread = (HANDLE)_beginthreadex(
			NULL, // LPSECURITY_ATTRIBUTES
			NULL, // unsigned stack size
			StartAddress, // function pointer
			this, // CThread object pointer
			1, // initflag
			(unsigned*)&m_dwThreadID // identifier
			);
	}

	return ( m_hThread != 0 );
}

void CThread::Stop( BOOL bBlock )
{
	// Signal exit event and wait for Run() to complete
	// Note that the thread may have already stopped on its own (or never started)
	if ( m_hThread )
	{
		m_eventExit.SetEvent();
		if ( bBlock )
		{
			// The parent thread blocks for cleanup
			m_eventWaitForCleanup.Lock();
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// Child thread functions

unsigned int __stdcall CThread::StartAddress(void* pv)
{
	// This is the control function for the child thread
	CThread* pMT = (CThread*)pv;
	CoInitialize( NULL );
	int nReturnCode = pMT->Main();
	CoUninitialize();
	pMT->Release();
	return nReturnCode;
}

UINT CThread::Main()
{
	// Copy and override this function in derived class
	// Do setup and notify service of m_eventService if necessary

	// Loop: Wait() returns after service event, timeout, or exit
	// You can do simple polling by just specifying wait in millisends
	while ( Wait() )
	{
		// Perform service event handling
	}

	// Do cleanup
	// DEADLOCK WARNING:
	// If the parent process is waiting for cleanup (Stop(TRUE)),
	// do not do anything to cause SendMessage() to parent process
	// such as SetWindowText because that calls its WinProc directly.
	return 0;
}

BOOL CThread::WaitOnHandle( HANDLE hObject, DWORD dwMilliSecs )
{
	// This waits on both the specified event and the exit event, or timeout
	// Result of CMultiLock::Lock() is stored in m_dwWaitResult;
	// Returns TRUE if specified event or timeout was triggered, otherwise FALSE
	HANDLE aHandles[2];
	aHandles[0] = hObject;
	aHandles[1] = (HANDLE)m_eventExit;

	// Wait on either of the two objects
	m_dwWaitResult = WaitForMultipleObjects( 2, aHandles, FALSE, dwMilliSecs );

	// Return TRUE if service event or timeout
	if ( m_dwWaitResult == WAIT_OBJECT_0 // service event
			|| m_dwWaitResult == WAIT_TIMEOUT )
		return TRUE;

	return FALSE;
}

BOOL CThread::Wait( DWORD dwMilliSecs )
{
	return WaitOnHandle( (HANDLE)m_eventService, dwMilliSecs );
}

void CThread::Release()
{
	// Release m_eventWaitForCleanup after Run()
	CloseHandle(m_hThread);
	m_hThread = NULL;
	m_eventWaitForCleanup.SetEvent();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
Raised in Southern Ontario Canada. Bachelor of Science from the University of Toronto in Computer Science and Anthropology. Living near Washington D.C. in Virginia, USA.

Comments and Discussions