Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

A comprehensive CE class library to replace ATL and MFC

, 4 Oct 2000
A collection of classes for CE that do not use ATL or MFC, plus an FTP client, database viewer, and sample application that solves beam deflection equations.
kgwince-old.zip
WinCe
BeamEx
app.ico
BeamEx.dsp
BeamEx.dsw
BeamEx.ini
BeamEx.plg
bitmap1.bmp
bmp00001.bmp
bmp00002.bmp
calc.bmp
calc16.bmp
circ_cross.ico
cir_cross.ico
cross_4.ico
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico00005.ico
ico00008.ico
ico00009.ico
ico00010.ico
icon1.ico
icon2.ico
icon4.ico
id_downl.bmp
Install
BeamEx.inf
BeamEx.ini
BeamEx.MIPS_PPCBW.CAB
BeamEx.MIPS_PPCColor.CAB
BeamEx.SH3_PPCColor.CAB
Setup.exe
i_cross.ico
l_cross.ico
magenic.ico
mssccprj.scc
obl_corss.ico
obl_cross.ico
options.bmp
options1.bmp
ping16.bmp
rect_cross.ico
scene_5.ico
scene_6.ico
tri_cross.ico
vssver.scc
CeLib
CeLabel.inl
CeLib.aps
CeLib.dsp
CeLib.dsw
CeLib.old
CeLib.plg
CeLib.vcp
CeMisc.inl
CeProperty.inl
CeTab.inl
CeWnd.inl
mssccprj.scc
vssver.scc
WinLib.dsp
WinLib.dsw
dbView
bitmap1.bmp
bmp00001.bmp
db5.bmp
dbView.aps
DbView.dsp
dbView.dsw
dbView.old
dbView.plg
DbView.vcp
deldb.bp2
deldb5.bmp
delrec.bp2
delrecor.bmp
help16.bmp
help4.bmp
icon1.ico
icon2.ico
Install
dbView.inf
dbView.ini
Setup.exe
magenic.bmp
magenic.ico
mssccprj.scc
vssver.scc
ftpView
appicon.ico
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bmp00001.bmp
bmp00002.bmp
db5.bmp
deldb.bp2
delrec.bp2
FtpView.dsp
ftpView.dsw
FtpView.old
ftpView.plg
FtpView.vcl
FtpView.vcp
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico171.ico
ico35.ico
icon1.ico
icon2.ico
imagelis.bmp
IMAGES.bmp
Install
ftpView.inf
ftpView.ini
Setup.exe
vssver.scc
magenic.bmp
magenic.ico
mssccprj.scc
options.bmp
options1.bmp
seperato.bmp
vssver.scc
Setup
ico101.ico
Setup.aps
Setup.dsp
setup.ico
Setup.plg
WinCe.dsw
WinLib.dsw
kgwince.zip
app.ico
BeamEx.dsp
BeamEx.dsw
BeamEx.ini
BeamEx.plg
BeamEx.vcl
BeamEx.vcp
bitmap1.bmp
bmp00001.bmp
bmp00002.bmp
calc.bmp
calc16.bmp
circ_cross.ico
cir_cross.ico
cross_4.ico
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico00005.ico
ico00008.ico
ico00009.ico
ico00010.ico
icon1.ico
icon2.ico
icon4.ico
id_downl.bmp
BeamEx.inf
BeamEx.ini
Setup.exe
i_cross.ico
l_cross.ico
magenic.ico
mssccprj.scc
obl_corss.ico
obl_cross.ico
options.bmp
options1.bmp
ping16.bmp
rect_cross.ico
scene_5.ico
scene_6.ico
tri_cross.ico
vssver.scc
CeFtp.vcp
CeFtp.vcw
CeLabel.inl
CeLib.aps
CeLib.dsp
CeLib.dsw
CeLib.plg
CeLib.vcl
CeLib.vcp
CeMisc.inl
CeProperty.inl
CeTab.inl
CeWnd.inl
mssccprj.scc
vssver.scc
WinLib.dsp
WinLib.dsw
bitmap1.bmp
bitmap2.bmp
bmp00001.bmp
db5.bmp
DbView.dsp
dbView.dsw
dbView.plg
DbView.vcl
DbView.vcp
deldb.bp2
deldb5.bmp
delrec.bp2
delrecor.bmp
help16.bmp
help4.bmp
icon1.ico
icon2.ico
dbView.inf
dbView.ini
Setup.exe
magenic.bmp
magenic.ico
menu1_5.bmp
mssccprj.scc
vssver.scc
appicon.ico
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bmp00001.bmp
bmp00002.bmp
db5.bmp
deldb.bp2
delrec.bp2
FtpView.dsp
ftpView.dsw
ftpView.plg
FtpView.vcl
FtpView.vcp
FtpView.vcw
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico171.ico
ico35.ico
icon1.ico
icon2.ico
imagelis.bmp
IMAGES.bmp
ftpView.inf
ftpView.ini
Setup.exe
vssver.scc
magenic.bmp
magenic.ico
mssccprj.scc
newmenu.bmp
options.bmp
options1.bmp
rcdata1.bin
seperato.bmp
toolbar1.bmp
vssver.scc
WinCe.dsw
WinCe.vcw
#ifndef __Thread_h__
#define __Thread_h__

//#ifdef _WIN32_WCE
#include "CeDebug.h"
//#endif

#if !defined(_WIN32_WCE) && !defined(_WIN32_DCOM)
# error DCOM must be defined when not in Windows CE
#endif

#include <objidl.h>

#if !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
#include <process.h>
#endif

#ifndef WAIT_OBJECT_1
#define WAIT_OBJECT_1 (WAIT_OBJECT_0 + 1)
#define WAIT_OBJECT_2 (WAIT_OBJECT_0 + 2)
#define WAIT_OBJECT_3 (WAIT_OBJECT_0 + 3)
#endif

#pragma warning(disable: 4018) // signed/unsigned

#ifndef _WIN32_WCE
class CeInProcMarshal
{
private:
	LPSTREAM m_pStream;
	IID m_iidMarshalled;
public:
	CeInProcMarshal() { m_pStream = NULL; }
	~CeInProcMarshal()
	{
		if (NULL != m_pStream)
		{
			IUnknown* pUnk = NULL;
			TRACE(_T("CInProcMarshal: Interface Stream never retrieved, will release now!\n"));
			if (S_OK == Get(m_iidMarshalled, (void**) &pUnk))
				pUnk->Release();
		}
	}

	HRESULT Set(REFIID riid, LPUNKNOWN pUnk)
	{
		if (NULL == pUnk)
			return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);

		HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(riid, pUnk, &m_pStream);
//		if (! SUCCEEDED(hr))
//			TRACE("CoMarshalInterThreadInterfaceInStream failed\n");

		// keep a copy until I can figure out a way to get it from the stream
		m_iidMarshalled = riid;

		return hr;
	}

	HRESULT Get(REFIID riid, LPVOID * ppv)
	{
		if (NULL == m_pStream)
			return S_FALSE;

		if (m_iidMarshalled != riid)
			return E_NOINTERFACE;

		HRESULT hr = ::CoGetInterfaceAndReleaseStream(m_pStream, riid, ppv);
		if (! SUCCEEDED(hr))
			TRACE(_T("CoGetInterfaceAndReleaseStream failed\n"));
		else
			m_pStream = NULL;

		return hr;
	}
};
#endif // ! _WIN32_WCE


class CeCriticalSection
{
public:
	CRITICAL_SECTION m_cs;

	CeCriticalSection() { ::InitializeCriticalSection(&m_cs); }
	~CeCriticalSection() { ::DeleteCriticalSection(&m_cs); }
	operator CRITICAL_SECTION() { return m_cs; }
	void Enter() { ::EnterCriticalSection(&m_cs); }
	void Leave() { ::LeaveCriticalSection(&m_cs); }
	void Lock() { Enter(); }
	void Unlock() { Leave(); }
#if(_WIN32_WINNT >= 0x0401)
	BOOL TryLock() { return ::TryEnterCriticalSection(&m_cs); }
	BOOL TryEnter() { return ::TryEnterCriticalSection(&m_cs); }
#endif
};

class CeWaitableHandle
{
public:
	HANDLE m_handle;
	operator HANDLE()
		{ return m_handle; }

	HANDLE GetHandle() const
		{ return m_handle; }

	DWORD WaitFor(DWORD dwMilliseconds=INFINITE)
		{ return ::WaitForSingleObject(m_handle, dwMilliseconds); }

	DWORD MsgWaitFor(DWORD dwMilliseconds=INFINITE)
	{
		DWORD dwWait;
		while (WAIT_OBJECT_0 + 1 == (dwWait = ::MsgWaitForMultipleObjects(1, &m_handle, FALSE, dwMilliseconds, QS_ALLINPUT)))
		{
			// message to process, process and continue
			MSG msg;

			// just to be careful, i've run into an unexplainable problem
			// where the ::MsgWait... returned with this value, but the
			// GetMessage() hung waiting for a message, so just check first
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				DispatchMessage(&msg);
		}
		return dwWait;
	}

	BOOL Close()
	{
		if (NULL == m_handle)
			return FALSE;
		BOOL bRet = ::CloseHandle(m_handle);
		m_handle = NULL;
		return bRet;
	}
};


//
// Manual reset event, requires Reset in order to unsignal the event
//
class CeManualEvent: public CeWaitableHandle
{
public:
	CeManualEvent(BOOL bSet=FALSE)
	{
		m_handle = ::CreateEvent(NULL, TRUE, bSet, NULL);
	}
	CeManualEvent(LPCTSTR szName, BOOL bSet, LPSECURITY_ATTRIBUTES psa=NULL)
	{
		m_handle = ::CreateEvent(psa, TRUE, bSet, szName);
	}

	~CeManualEvent() { Close(); }
	void Set()		{ ::SetEvent(m_handle); }
	void Reset()	{ ::ResetEvent(m_handle); }
	void Pulse()	{ ::PulseEvent(m_handle); }
	BOOL IsSet()	{ return (WAIT_OBJECT_0 == WaitFor(0)); }
};


//
// Auto reset event, the event is reset once a SINGLE waiting thread
// is release from a wait state
//
class CeAutoEvent: public CeWaitableHandle
{
public:
	CeAutoEvent(BOOL bSet=FALSE)
	{
		m_handle = ::CreateEvent(NULL, FALSE, bSet, NULL);
	}
	CeAutoEvent(LPCTSTR szName, BOOL bSet=FALSE, LPSECURITY_ATTRIBUTES psa=NULL)
	{
		m_handle = ::CreateEvent(psa, FALSE, bSet, szName);
	}

	~CeAutoEvent()	{   Close(); }
	void Set()		{ ::SetEvent(m_handle); }
	void Reset()	{ ::ResetEvent(m_handle); }
	void Pulse()	{ ::PulseEvent(m_handle); }
};


#ifndef _WIN32_WCE
class CeSemaphore: public CeWaitableHandle
{
public:
	CeSemaphore(LONG lMax)
	{
		m_handle = ::CreateSemaphore(NULL, 0, lMax, NULL);
	}
	~CeSemaphore() { Close(); }
	void Release()		{ ::ReleaseSemaphore(m_handle, 1, NULL); }
	LONG Release(LONG lIncr)
	{
		LONG lOldCnt;
		::ReleaseSemaphore(m_handle, lIncr, &lOldCnt);
		return lOldCnt;
	}
};
#endif //_WIN32_WCE


class CeWaitObjects
{
private:
	HANDLE* m_pHandleArray;
	int m_nHandles;

public:
	// empty wait object group
	CeWaitObjects()
	{
		m_pHandleArray = NULL;
		m_nHandles = 0;
	}
	// Simple two item wait
	CeWaitObjects(CeWaitableHandle* pHandle1, CeWaitableHandle* pHandle2)
	{
		_ASSERTE(NULL != pHandle1);
		_ASSERTE(NULL != pHandle2);
		m_pHandleArray = new HANDLE[2];
		m_nHandles = 2;
		m_pHandleArray[0] = (HANDLE) *pHandle1;
		m_pHandleArray[1] = (HANDLE) *pHandle2;
	}
	CeWaitObjects(CeWaitableHandle* pHandleArray, int nHandles)
	{
		m_pHandleArray = new HANDLE[nHandles];
		m_nHandles = nHandles;

		for (int ii = 0; ii < nHandles; ii++)
		{
			_ASSERTE(NULL != m_pHandleArray[ii]);
			m_pHandleArray[ii] = pHandleArray[ii];
		}
	}

	BOOL Add(HANDLE h)
	{
		HANDLE* pTmp = new HANDLE[m_nHandles+1];
		if (! pTmp)
			return FALSE;

		pTmp[m_nHandles] = h;

		if (m_pHandleArray)
		{
			memcpy(pTmp, m_pHandleArray, m_nHandles*sizeof(HANDLE));
			delete[] m_pHandleArray;
		}

		m_pHandleArray = pTmp;
		m_nHandles++;
		return TRUE;
	}

	~CeWaitObjects()
	{
		if (m_pHandleArray)
			delete [] m_pHandleArray;
	}

	DWORD WaitFor(DWORD dwTimeOut=INFINITE, BOOL bWaitForAll=FALSE, DWORD dwWakeMask=0)
	{
		// number of handles in the object handle array 
		DWORD dwResult;
		if (dwWakeMask == 0)
			dwResult = ::WaitForMultipleObjects(m_nHandles,
				m_pHandleArray, bWaitForAll, dwTimeOut);
		else
			dwResult = ::MsgWaitForMultipleObjects(m_nHandles,
				m_pHandleArray, bWaitForAll, dwTimeOut, dwWakeMask);

//		if (WAIT_FAILED == dwResult)
//			TRACE("Error: %u\n", GetLastError());

		return dwResult;
	}

	DWORD MsgWaitFor(DWORD dwTimeOut=INFINITE, BOOL bWaitForAll=FALSE)
	{
		// wait until a NON-windows message event wakes up the object
		DWORD dwWait;
		while (WAIT_OBJECT_0 + m_nHandles == (dwWait = ::MsgWaitForMultipleObjects(m_nHandles, m_pHandleArray, bWaitForAll, dwTimeOut, QS_ALLINPUT)))
		{
			// message to process, process and continue
			MSG msg;

			// just to be careful, i've run into an unexplainable problem
			// where the ::MsgWait... returned with this value, but the
			// GetMessage() hung waiting for a message, so just check first
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				DispatchMessage(&msg);
		}

		return dwWait;
	}
}; 

#define WM_WORKER_DONE (WM_USER + 0x400)

// Note:
// This class does NOT work properly if ExitThread() is called from within the thread
// instead you must

class CeWorkerThread: public CeWaitableHandle
{
protected:
	bool m_bRunning;
	bool m_bAutoDelete;
	bool m_bStopping;

public:
	static DWORD WINAPI StartThread(LPVOID pParam);

	HWND m_hWndMsg;
	DWORD m_dwThreadId;
	CeManualEvent m_eventStop;
	DWORD m_dwStopTimeOut;

	bool m_bInitCOM;
	COINIT m_nCoInit;

	CeWorkerThread(BOOL bAutoDelete=FALSE, HWND hWndMsg=NULL, DWORD dwStopTimeOut=INFINITE);
	~CeWorkerThread();

// Methods used by derived classes
	virtual void Delete();
	virtual void Exit(DWORD dwExitCode);
	BOOL IsStopSet() const { return m_bStopping; }

// Methods used by other threads
	virtual BOOL Start(int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
	virtual void Stop(BOOL bDispatchMsgs=FALSE);

	DWORD WaitForComplete();
	BOOL IsRunning() const;

	virtual BOOL PostThreadMessage(UINT Msg, WPARAM wParam = 0, LPARAM lParam = 0) const;
	virtual BOOL PostWindowMessage(UINT Msg, WPARAM wParam = 0, LPARAM lParam = 0) const;
	virtual BOOL Kill(DWORD dwExit = 1);
	DWORD Pause();
	DWORD Suspend();
	DWORD Resume();
	DWORD GetExitCode();

// Method calls made by either
	int GetPriority() const;
	BOOL SetPriority(int nPriority);
	DWORD GetId() const;
	HANDLE GetHandle() const;

	// just run the thread function directly, debug stuff
	void RunInline();

	// override this to make the thread do something (required) ...
	virtual UINT ThreadProc() = 0;

	// Some virtual calls that happen for the convenience of the
	// derived class, this allows the thread to do some state
	// management if that would aid it in some way
	virtual void OnStop() {}
	virtual void OnSuspend() {}
	virtual void OnResume() {}
	virtual void OnKill() {}
};


#ifdef __AFX_H__

//
// Add MFC support to the thread class
//

class CeMFCWorkerThread : public CeWorkerThread
{
public:
	CeMFCWorkerThread()
	{
		m_pThread = NULL;
	}

	~CeMFCWorkerThread();

	CWinThread* m_pThread;

	// these methods are required in order for MFC to function properly,
	// the rest of the methods defined for CWorkerThread work properly
	// on the handle set up by the Start() method
	virtual BOOL Start( int nPriority = THREAD_PRIORITY_NORMAL,
						UINT nStackSize = 0,
						DWORD dwCreateFlags = 0,
						LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
					  );
	virtual void Delete();
	virtual void Exit(DWORD dwExitCode);
	virtual BOOL Close();
};


inline CeMFCWorkerThread::~CeMFCWorkerThread()
{
	// we ALWAYS hang on to the pointer when we're not auto deleting
	// so we need to get rid of it now, or else we leak CWinThread objects
	if (NULL != m_pThread && ! m_bAutoDelete)
	{
		// if we hung on to the pointer, then we need to get rid of it manually
		m_pThread->m_bAutoDelete = TRUE;
		m_pThread->Delete();

		m_pThread = NULL;
		m_dwThreadId = 0;
		m_handle = NULL;
	}
}


inline BOOL CeMFCWorkerThread::Start(int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
	// Note: MFC actually starts the thread AFTER calling it's own
	// initalization and suspending the thread and returning this pointer
	// See the MFC source code for details

	m_pThread = AfxBeginThread((AFX_THREADPROC) StartThread,
		this, nPriority, nStackSize, dwCreateFlags, lpSecurityAttrs);

	if (NULL == m_pThread)
		return FALSE;

	// have the MFC thread take on the attributes of our thread
	// implementation
	m_pThread->m_bAutoDelete = m_bAutoDelete;
	m_handle = m_pThread->m_hThread;
	m_dwThreadId = m_pThread->m_nThreadID;

	return TRUE;
}

inline void CeMFCWorkerThread::Delete()
{
	if (m_bAutoDelete && m_pThread)
	{
		m_pThread->m_bAutoDelete = TRUE;
		m_pThread->Delete();

		// at this point just forget about the MFC thread, 
		// MFC is still using is after calling us, we'll let MFC handle
		// this one also
		m_pThread = NULL;
		m_handle = NULL;
		m_dwThreadId = 0;
	}

	CeWorkerThread::Delete();
}

inline void CeMFCWorkerThread::Exit(DWORD dwExitCode)
{
	if (m_bAutoDelete)
	{
		// get rid of our pointer states, MFC will shortly
		m_pThread = NULL;
		m_handle = NULL;
		m_dwThreadId = 0;
	}

	// matchs AfxBeginThread() when aborting the thread
	AfxEndThread(dwExitCode);
}

inline BOOL CeMFCWorkerThread::Close()
{
	// do nothing, the base class gets involved and tries to close
	// the handle and MFC and this class lose
	// After a Close() operation the handles are invalid but
	// the thread still runs, the only problem comes from
	// not being able to wait on completion or get status of any kind
	// so, we'll just null our copy and let MFC take care
	// of the other later
	if (m_pThread)
	{
		if (! m_pThread->m_bAutoDelete)
			// turn on auto delete since we can't deal with the
			// thread anymore
			m_pThread->m_bAutoDelete = TRUE;
		m_pThread = NULL;
	}

	m_dwThreadId = 0;
	m_handle = NULL;

	return TRUE;
}

#endif // __AFX_H__


/////////////////////////////////////////////////////////////////////////////
// inline function definitions

inline DWORD WINAPI CeWorkerThread::StartThread(LPVOID pParam)
{
	UINT iRet = 1;		// assume fatal unless otherwise changed

	__try
	{
		CeWorkerThread* pThis = (CeWorkerThread *) pParam;

		if (0 == pThis->m_dwThreadId)
			// paranoia, in case the creator didn't
			pThis->m_dwThreadId = GetCurrentThreadId();

		if (pThis->m_bInitCOM)
			// requires DCOM or WinNT 4.0
			::CoInitializeEx(NULL, pThis->m_nCoInit);

		pThis->m_bRunning = true;

		// This is the overridable virtual function that
		// is the equivelent to the thread proc
		iRet = pThis->ThreadProc();

		// thread processing complete, do all we can to notify
		// that we have completed processing

		pThis->m_bRunning = false;										// flag for our or others uses
		pThis->PostWindowMessage(WM_WORKER_DONE, iRet, pThis->m_dwThreadId);	// post to associated window

		if (pThis->m_bInitCOM)
			::CoUninitialize();

		// note: this only deletes the thread if autodelete is set
		pThis->Delete();
	}
    __except (EXCEPTION_EXECUTE_HANDLER)
	{
		::MessageBox(NULL, _T("Thread termainated abnormally by an exception"),
			_T("Fatal"), MB_OK | MB_ICONSTOP);
	}

	return iRet;
}


inline void CeWorkerThread::Exit(DWORD dwExitCode)
{
	// thread processing complete, do all we can to notify
	// that we have completed processing
	m_bRunning = false;					// flag for our or others uses
	PostWindowMessage(WM_WORKER_DONE);	// post to associated window

	if (m_bInitCOM)
		::CoUninitialize();

	// note: this only deletes the thread if autodelete is set
	Delete();
	
#if defined(_MT) && !defined(_WIN32_WCE)
	_endthreadex(dwExitCode);
#else
	::ExitThread(dwExitCode);
#endif
}

inline CeWorkerThread::CeWorkerThread(BOOL bAutoDelete/*=FALSE*/, HWND hWndMsg/*=NULL*/, DWORD dwStopTimeOut/*=INFINITE*/)
{
	m_handle = NULL;
	m_hWndMsg = hWndMsg;
	m_dwThreadId = 0;
	m_bRunning = false;
	m_bInitCOM = true;
	m_bStopping = false;
	m_nCoInit = (COINIT) COINIT_MULTITHREADED;
	m_dwStopTimeOut = dwStopTimeOut;
	m_bAutoDelete = (bAutoDelete != FALSE);
}

inline CeWorkerThread::~CeWorkerThread()
{
	Stop();
	Close();
}

inline void CeWorkerThread::RunInline()
{
	StartThread(this);
}


inline BOOL CeWorkerThread::Start(int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
	if (m_bRunning)
	{
//		TRACE("Start: Thread is already executing, create a new instance if this is what is required!\n");
		// already running
		return FALSE;
	}
#if defined(_MT) && !defined(_WIN32_WCE)
	m_handle = (HANDLE) _beginthreadex(lpSecurityAttrs, nStackSize, 
		(unsigned (__stdcall *) (void *)) StartThread,
		(LPVOID) this, dwCreateFlags,
		(unsigned int*) &m_dwThreadId);
#else
	m_handle = ::CreateThread(lpSecurityAttrs, nStackSize, StartThread,
		(LPVOID) this, dwCreateFlags, &m_dwThreadId);
#endif

	if (m_handle)
		::SetThreadPriority(m_handle, nPriority);

	return (m_handle != NULL);
}

inline void CeWorkerThread::Stop(BOOL bDispatchMsgs/*=FALSE*/)
{
	// set the stop event for the thread to see
	m_eventStop.Set();
	m_bStopping = true;

	// anything to wait for? may have exited already
	if (! m_bRunning || NULL == m_handle)
		return;

	// wait until complete, kill if we timeout,
	// the default implementation waits for infinite time
	// and the Kill() will never get called in that case

	// notify the derived class that we've been asked to stop,
	// this will allow the thread to kill any blocking functions
	// so that it can process the stop request
	OnStop();

	// don't wait if we have autodelete set, since this
	// will just cause a protection fault anyway in the waitfor

	if (m_bAutoDelete)
		// will delete object on return, thus you CANNOT wait on it
		return;

	if (bDispatchMsgs)
	{
		// for GUI threads, get and dispatch messages while waiting
		// for the thread to terminate
		if (WAIT_TIMEOUT == MsgWaitFor(m_dwStopTimeOut))
			// wait for the time out, kill the thread
			Kill();
	}
	else
	{
		if (WAIT_TIMEOUT == WaitFor(m_dwStopTimeOut))
			// wait for the time out, kill the thread
			Kill();
	}
}

inline void CeWorkerThread::Delete()
{
	if (m_bAutoDelete)
		delete this;
}

inline DWORD CeWorkerThread::WaitForComplete()
{
	_ASSERTE(! m_bAutoDelete);
	return WaitFor(INFINITE);
}

inline BOOL CeWorkerThread::IsRunning() const
{
	return m_bRunning;
}
inline int CeWorkerThread::GetPriority() const
{
	return ::GetThreadPriority(m_handle);
}

inline BOOL CeWorkerThread::SetPriority(int nPriority)
{
	return ::SetThreadPriority(m_handle, nPriority);
}

inline DWORD CeWorkerThread::GetId() const
{
	return m_dwThreadId;
}

inline BOOL CeWorkerThread::PostThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const
{
	if (m_dwThreadId)
		return ::PostThreadMessage(m_dwThreadId, Msg, wParam, lParam);
	return FALSE;
} 

inline BOOL CeWorkerThread::PostWindowMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const
{
	if (m_hWndMsg)
		return ::PostMessage(m_hWndMsg, Msg, wParam, lParam);
	return FALSE;
} 

inline BOOL CeWorkerThread::Kill(DWORD dwExit)
{
	OnKill();
	return ::TerminateThread(m_handle, dwExit);
}

inline DWORD CeWorkerThread::Pause()
{
	return Suspend();
}

inline DWORD CeWorkerThread::Suspend()
{
	OnSuspend();
	return ::SuspendThread(m_handle);
}

inline DWORD CeWorkerThread::Resume()
{
	OnResume();
	return ::ResumeThread(m_handle);
}

inline DWORD CeWorkerThread::GetExitCode()
{
	DWORD dwRet;
	if (! ::GetExitCodeThread(m_handle, &dwRet))
		return 0xffffffff;

	if (STILL_ACTIVE == dwRet)
		TRACE(_T("Thread Still Active\n"));
	else
		TRACE(_T("Thread Exit Code %lu\n"), dwRet);

	return dwRet;

}

#endif // Thread_h__

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Kenny G

United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 5 Oct 2000
Article Copyright 2000 by Kenny G
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid