Click here to Skip to main content
15,897,518 members
Articles / Programming Languages / C++

Effective Threads in C++ - Part 2: The ExitableThread Class

Rate me:
Please Sign up or sign in to vote.
2.18/5 (5 votes)
22 Nov 20062 min read 25K   616   11  
Wrapping the Win32 Thread API into a C++-friendly class.
#if !defined(_EXITABLETHREAD_H_)
#define _EXITABLETHREAD_H_

#include "Thread.h"

namespace Lib
{
	// --------------------------------------------
	//  ExitableThread class
	// --------------------------------------------
	template<class T, class P>
	class ExitableThread : public Thread<T, P>
	{
	public:
		typedef void (T::*ThreadFunc)( P );

		ExitableThread();
		virtual ~ExitableThread();

		// ExitThread methods - Called within the context of an
		// external thread to instruct the embedded (running)
		// thread to exit.  
		//
		// ExitThread() - Signals the event and immediately 
		// returns.  
		//
		// ExitThreadAndWait() - Signals the event and waits 
		// until the thread actually exits or the timeout
		// expires.  Returns true if the thread exited, or
		// false if the timeout expired
		void ExitThread();
		bool ExitThreadAndWait( DWORD timeoutMS = 5000 );

		// IsExitEventSet - Called by the embedded (running)
		// thread to test if the exit event is set.  Returns
		// true if the event has been set, and the thread
		// should exit, and false otherwise
		bool IsExitEventSet();

	protected:		
		// Handle to the Exit Event
		HANDLE m_hExitThreadEvent;
	};

	// ------------------------------------------------------
	template<class T, class P>
	ExitableThread<T, P>::ExitableThread()
		: m_hExitThreadEvent( NULL )
	{
		// Create the Exit Event - Should the args to CreateEvent be
		// customizable?  What should be done if CreateEvent() fails?
		// NOTE: Since we will have only one consumer of the exit event,
		// it is safe to make the event an auto-reset event
		m_hExitThreadEvent = ::CreateEvent( NULL, false, false, NULL );
	}

	// ------------------------------------------------------
	template<class T, class P>
	ExitableThread<T, P>::~ExitableThread()
	{
		if ( m_hExitThreadEvent )
		{
			::CloseHandle( m_hExitThreadEvent );
			m_hExitThreadEvent = NULL;
		}
	}

	// ------------------------------------------------------
	template<class T, class P>
	void ExitableThread<T, P>::ExitThread()
	{
		::SetEvent( m_hExitThreadEvent );
	}

	// ------------------------------------------------------
	template<class T, class P>
	bool ExitableThread<T, P>::ExitThreadAndWait( DWORD timeoutMS )
	{
		// Set the event telling the thread to exit
		::SetEvent( m_hExitThreadEvent );

		// Wait for the thread to actually exit
		DWORD result = ::WaitForSingleObject( m_hThread, timeoutMS );

		// Cleanup handle
		::CloseHandle( m_hThread );
		m_hThread = NULL;

		return ( result == WAIT_OBJECT_0 );
	}

	// ------------------------------------------------------
	template<class T, class P>
	bool ExitableThread<T, P>::IsExitEventSet()
	{
		DWORD res = ::WaitForSingleObject( m_hExitThreadEvent, 0 );
		return ( res == WAIT_OBJECT_0 );
	}
}

#endif

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
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions