/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	Thread.h
 *
 *****************************************************************************/

// SOL++2000
// 1999.09.24 Modified to use _beginthreadex and _endthreadex insteade
// of CreateThread and ExitThread.

#ifndef _SOL_OBJECT
#include <sol\Object.h>
#endif

#ifndef _SOL_THREAD
#define _SOL_THREAD

class Thread :public Object {
	void*	param;
	DWORD	threadId;
	HANDLE  handle;
	static  DWORD WINAPI procedure(DWORD dword);

protected:
	void setHandle(HANDLE handle1) {
		handle = handle1;
	}
	void setThreadId(int id) {
		threadId = id;
	}

public:

	Thread(DWORD stack = 0, void* param = null);

	~Thread() {
		kill();
	}
	void*	getParam() {
			return param;
	}
	DWORD	getThreadId() {
			return threadId;
	}

	HANDLE	getHandle() {
			return handle;
	}
	void	exit(DWORD exitCode);

	// Thread main loop
	virtual void run() {
			// Do something
			//return TRUE;
	}

	// SOL++ 3.0
	virtual DWORD start() {
			return resume();
	}
	void	sleep(DWORD time) {
			::Sleep(time);
	}

	DWORD	resume() {
			return ::ResumeThread(handle);
	}

	void	setPriority(int priority) {
			::SetThreadPriority(handle, priority);
	}

	DWORD	suspend() {
		return ::SuspendThread(handle);
	}
	BOOL	close() {
		if(handle) {
			HANDLE h = handle;
			handle = NULL;
			return ::CloseHandle(h);
		}
		return FALSE;

	}
	BOOL	post(UINT message, WPARAM wParam, LPARAM lParam) {
		if(handle)
			return ::PostThreadMessage(threadId, message, wParam, lParam);
		else 
			return FALSE;
	}

	 BOOL   getExitCode(DWORD* id) {
		return ::GetExitCodeThread(handle, id);
	 }

	void    kill();

	BOOL	terminate(int exitCode) {
		return ::TerminateThread(handle, exitCode);
	}

	int	wait(int interval=INFINITE) {
        	return ::WaitForSingleObject(handle, interval);
	}
};

#endif
