//
// Thread.h: header file
//
// Copyright (C) Walter E. Capers.  All rights reserved
//
// This source is free to use as you like.  If you make
// any changes please keep me in the loop.  Email them to
// walt.capers@comcast.net.
//
// PURPOSE:
//
//  To implement Win32 threading as a C++ object
//
// REVISIONS
// =======================================================
// Date: 10.24.07        
// Name: Walter E. Capers
// Description: File creation
//
// Date: 10.24.07 11:49 am
// Name: Walter E. Capers
// Description: Added SetIdle function to allow the idle time to be altered
//              independent of the SetThreadType member function.
// Date: 10.31.07
// Name: Walter E. Capers
// Description: Added support for beginthreadex
//              To use compile with -DUSE_BEGIN_THREAD
//
//

#ifndef THREAD_CLASS
#define THREAD_CLASS

#ifndef WINDOWS
#if defined(_WIN32) || defined(_WIN64)
#define WINDOWS
#endif
#endif
#ifdef __APPLE__
#define VMS
#endif

#ifndef WINDOWS
#include <stdio.h>
#include <string.h>
//#include <malloc.h>
#include <memory.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
typedef unsigned char BOOL;
#define TRUE 1
#define FALSE 0
typedef long DWORD;
typedef void *LPVOID;
#else
#include "afx.h"
/* #include <windows.h> */
#include <stdio.h>
#endif

#if defined(AS400) || defined(OS400)
typedef pthread_id_np_t ThreadId_t;
#elif defined(VMS) 
typedef pthread_t ThreadId_t;
#else
#ifdef USE_BEGIN_THREAD
typedef unsigned ThreadId_t;
#else
typedef DWORD ThreadId_t;
#endif
#endif

#include <common/MutexClass.h>
#include <common/EventClass.h>

#define QUEUE_SIZE 100
#define DEFAULT_STACK_SIZE 0
#ifndef WINDOWS
void Sleep( unsigned int mseconds);
#endif

#ifndef ASSERT
#if defined(DEBUG) || defined(_DEBUG)
#define ASSERT(test) if( !(test) ) { \
	fprintf(stderr,"\nASSERT(%s) FAILS, %s line %d\n",#test,__FILE__, __LINE__); exit(0);}
#else
#define ASSERT(test)
#endif
#endif


typedef enum {
	ThreadStateBusy,               // thread is currently handling a task
	ThreadStateWaiting,            // thread is waiting for something to do
    ThreadStateDown,               // thread is not running
    ThreadStateShuttingDown,       // thread is in the process of shutting down
    ThreadStateFault               // an error has occured and the thread could not
	                               // be launched
} ThreadState_t;

typedef enum {
	ThreadTypeHomogeneous,
	ThreadTypeSpecialized,
    ThreadTypeIntervalDriven,
    ThreadTypeNotDefined } ThreadType_t;


typedef enum {
	TaskStatusNotSubmitted,
	TaskStatusWaitingOnQueue,
	TaskStatusBeingProcessed,
	TaskStatusCompleted } TaskStatus_t;

class CTask
{
private:
	TaskStatus_t m_state;
	ThreadId_t m_dwThread;
public:
	CMutexClass m_mutex;

	void SetTaskStatus(TaskStatus_t state) 
	{
		m_mutex.Lock();
			m_state=state;
		m_mutex.Unlock();
	}

	void SetId(ThreadId_t *pid)
	{
		memcpy(&m_dwThread,pid,sizeof(ThreadId_t));
	}

	/**
	 *
	 * Wait
	 * waits for upto timeoutSeconds for a task
	 * to complete
	 *
	 **/
	BOOL Wait(int timeoutSeconds)
	{
        timeoutSeconds = timeoutSeconds * 1000;
		if( Status() != TaskStatusCompleted &&
			timeoutSeconds > 0 )
		{
			Sleep(100);
			timeoutSeconds = timeoutSeconds - 100;
		}
		if( Status() == TaskStatusCompleted ) return TRUE;
		return FALSE;
	}

	/**
	 *
	 * Status
	 * returns current state of a task
	 *
	 **/
	TaskStatus_t Status()
	{
		TaskStatus_t state ;

		m_mutex.Lock();
		  state = m_state;
		m_mutex.Unlock();
	    return state;
	}

	void Thread(ThreadId_t *pId)
	{
		memcpy(pId,&m_dwThread,sizeof(ThreadId_t));
	}

	CTask(){m_state=TaskStatusNotSubmitted; memset(&m_dwThread,0,sizeof(ThreadId_t)); }
	~CTask(){}
	virtual BOOL Task()=0;
};


class CThread 
#ifdef WINDOWS
	: public CObject // use CObject as a base class so object can be used in lists and
	               // object arrays
#endif
{
private:
	CEventClass   m_event;         // event controller
	int           m_StopTimeout;   // specifies a timeout value for stop
	                               // if a thread fails to stop within m_StopTimeout
	                               // seconds an exception is thrown

	BOOL		  m_bRunning;      // set to TRUE if thread is running
#ifdef WINDOWS
	HANDLE		  m_thread;		   // thread handle
#else
	pthread_t     m_thread;        // thread handle
#endif
	ThreadId_t	  m_dwId;          // id of this thread
	LPVOID        *m_lppvQueue;    // task que
	unsigned int  m_chQueue;       // que depth
	unsigned int  m_queuePos;      // current que possition
	LPVOID        m_lpvProcessor;  // data which is currently being processed
	ThreadState_t m_state;         // current state of thread see thread state data
	                               // structure.
	DWORD         m_dwIdle;        // used for Sleep periods
	ThreadType_t  m_type;
	DWORD		  m_stackSize;     // thread stack size
#define NO_ERRORS			       0
#define MUTEX_CREATION		       0x01
#define EVENT_CREATION		       0x02
#define THREAD_CREATION		       0x04
#define UNKNOWN					   0x08
#define ILLEGAL_USE_OF_EVENT       0x10
#define MEMORY_FAULT               0x20
#define EVENT_AND_TYPE_DONT_MATCH  0x40
#define STACK_OVERFLOW             0x80
#define STACK_EMPTY                0x100
#define STACK_FULL                 0x200

	DWORD         m_dwObjectCondition;
	BOOL		  Push(LPVOID lpv);
	BOOL		  Pop();
	BOOL		  Empty();
public:
	/**
	 *
	 * user definable member functions
	 *
	 **/
	CMutexClass	  m_mutex;         // mutex that protects threads internal data

	virtual BOOL OnTask(LPVOID lpvData);     // called when an event occurs
	virtual BOOL OnTask();                   // called when a time interval has elapsed

	CThread(void);
	~CThread(void);
#ifdef WINDOWS
#ifdef USE_BEGIN_THREAD
	friend unsigned __stdcall _THKERNEL(LPVOID lpvData);
#else
	friend DWORD WINAPI _THKERNEL( LPVOID lpvData );
#endif
#else
	friend LPVOID _THKERNEL(LPVOID lpvData);
#endif
	BOOL        FromSameThread();
	float		PercentCapacity();
	void        WaitTillExit();
	BOOL		KernelProcess();
	BOOL		Event(LPVOID lpvData=NULL);
	BOOL        Event(CTask *pvTask);
	void		SetOnStopTimeout(int seconds ) { m_StopTimeout = seconds; }
    BOOL        SetQueueSize( unsigned int ch );
	BOOL		Stop();
	BOOL		Start();
	void		GetId(ThreadId_t *pId) { memcpy(pId,&m_dwId,sizeof(ThreadId_t)); }      // returns thread id
	ThreadState_t ThreadState();
	BOOL		PingThread(DWORD dwTimeout=0);
	BOOL        AtCapacity();
#ifdef WINDOWS
	void		SetPriority(DWORD dwPriority=THREAD_PRIORITY_NORMAL);
#else
	void		SetPriority(DWORD dwPriority=0);
#endif
	DWORD		GetErrorFlags() { return m_dwObjectCondition; } // returns state of object
	void		SetThreadType(ThreadType_t typ=ThreadTypeNotDefined,DWORD dwIdle=100);
	void		SetIdle(DWORD dwIdle=100);
    unsigned int GetEventsPending();
    static BOOL ThreadIdsEqual(ThreadId_t *p1,
						       ThreadId_t *p2)
	{
#if defined(AS400)||defined(OS400)
		return(( memcmp(p1,p2,sizeof(ThreadId_t))==0)?TRUE:FALSE);
#elif defined(VMS) 
		return (( pthread_equal(*p1,*p2) )?TRUE:FALSE );
#else
		return ((*p1 == *p2)?TRUE:FALSE);
#endif

	}

	static ThreadId_t ThreadId()
	{
		ThreadId_t thisThreadsId ;
#if defined(AS400) || defined(OS400)
		pthread_t thread;
#endif

#ifdef WINDOWS
		thisThreadsId = (ThreadId_t)GetCurrentThreadId();
#else

#if defined(AS400) || defined(OS400)
		thread = pthread_self();
		pthread_getunique_np(&thread,&thisThreadsId);
#elif defined(ALPHA) || defined(DEC) || defined(VMS)
#ifdef VMS
		thisThreadsId = pthread_self();
#else
		thisThreadsId = pthread_getsequence_np(pthread_self());
#endif
#else
		thisThreadsId = pthread_self();
#endif
#endif
		return thisThreadsId;
	}


};
#endif

