#ifndef _OS_OBJECT_H_
#define _OS_OBJECT_H_

U32 GetHostIP(U32 ethNum);

class OSMutex 
{
private:
	bool m_bCreate;
	HANDLE mutex;
public:
	OSMutex() {m_bCreate = false;};
	OSMutex(bool bCreate);
	virtual ~OSMutex();

	void Create(bool bCreate=true);
	DWORD Lock();
	void Unlock();
};

class OSMutexLock
{
protected:
	OSMutex &m_mutex;
public:
	OSMutexLock(OSMutex &mutex):m_mutex(mutex) {m_mutex.Lock();};
	~OSMutexLock() {m_mutex.Unlock();};
};

class OSSema
{
public:
	OSSema() {m_bCreate = false;};
	OSSema(DWORD nInit,bool bCreate=true);
	~OSSema();

	void Create(DWORD nInit,bool bCreate=true);
	int ActP();
	int ActP( int timeout);
	int ActV();

protected:
	bool m_bCreate;//用来控制是否生成信号量,缺省情况下生成。
	HANDLE	m_semval;
};

typedef struct
{
    unsigned char	*pBuff;
    int			head, tail, length, full;

} fifo_FifoStruct;

class CFIFO
{
public:
	CFIFO();
	~CFIFO();

	OSMutex m_OSMutex;

	fifo_FifoStruct m_FifoPtr;
	int  fifo_create(int FifoSize);
	int  fifo_destroy();
	int fifo_read( unsigned char *Buffer, int Len);
	int fifo_write(unsigned char *Buffer, int Len);
	int  fifo_real_get_size();
	void fifo_flush();
private:
	bool bCreate;

};


class OSMQueue 
{
public:
	OSMQueue() {m_bCreate = false;};

	OSMQueue(DWORD maxLen);

	virtual ~OSMQueue();

	void Create(DWORD maxLen);

	int SendMsg(U8* pBuf,U32 Len);

	int ReceiveMsg(U8* pBuf, U32 Len);

	int ReceiveMsg(U8* pBuf,U32 Len , int timeout);
	
private:
	OSSema m_SemNotify;
	bool m_bCreate;

	CFIFO m_CFIFO;
};

class OSTime
{
public:
/** Returns an OSTime instance representing the current wallclock time. 
*  Returns an OSTime instance representing the current wallclock time. This is expressed 
*  as a number of seconds since 00:00:00 UTC, January 1, 1970.
	*/
	static OSTime CurrentTime();
	
	/** This function waits the amount of time specified in \c delay. */
	static void Wait(const OSTime &delay);
	
	/** Creates an OSTime instance representing \c t, which is expressed in units of seconds. */
	OSTime(double t);
	
	/** Creates an instance corresponding to \c seconds and \c microseconds. */
	OSTime(unsigned long seconds,unsigned long microseconds)					{ sec = seconds; microsec = microseconds; };
	
	/** Returns the number of seconds stored in this instance. */
	unsigned long GetSeconds() const										{ return sec; };
	
	/** Returns the number of microseconds stored in this instance. */
	unsigned long GetMicroSeconds() const								{ return microsec; }
	
	/** Returns the time stored in this instance, expressed in units of seconds. */
	double GetDouble() const 										{ return (((double)sec)+(((double)microsec)/1000000.0)); }
	
	OSTime &operator-=(const OSTime &t);
	OSTime &operator+=(const OSTime &t);
	bool operator<(const OSTime &t) const;
	bool operator>(const OSTime &t) const;
	bool operator<=(const OSTime &t) const;
	bool operator>=(const OSTime &t) const;
private:
	unsigned long sec,microsec;
};

inline OSTime::OSTime(double t)
{
	sec = (unsigned long)t;
	
	double t2 = t-((double)sec);
	t2 *= 1000000.0;
	microsec = (unsigned long)t2;
}

inline OSTime OSTime::CurrentTime()
{
	static int inited = 0;
	static unsigned __int64 microseconds, initmicroseconds;
	static LARGE_INTEGER performancefrequency;
	
	unsigned __int64 emulate_microseconds, microdiff;
	SYSTEMTIME systemtime;
	FILETIME filetime;
	
	LARGE_INTEGER performancecount;
	
	QueryPerformanceCounter(&performancecount);
    
	if(!inited){
		inited = 1;
		QueryPerformanceFrequency(&performancefrequency);
		GetSystemTime(&systemtime);
		SystemTimeToFileTime(&systemtime,&filetime);
		microseconds = ( ((unsigned __int64)(filetime.dwHighDateTime) << 32) + (unsigned __int64)(filetime.dwLowDateTime) ) / 10ui64;
		microseconds-= 11644473600000000ui64; // EPOCH
		initmicroseconds = ( ( performancecount.QuadPart * 1000000ui64 ) / performancefrequency.QuadPart );
	}
    
	emulate_microseconds = ( ( performancecount.QuadPart * 1000000ui64 ) / performancefrequency.QuadPart );
	
	microdiff = emulate_microseconds - initmicroseconds;
	
	return OSTime((unsigned long)((microseconds + microdiff) / 1000000ui64),((unsigned long)((microseconds + microdiff) % 1000000ui64)));
}

inline void OSTime::Wait(const OSTime &delay)
{
	DWORD t;
	
	t = ((DWORD)delay.GetSeconds())*1000+(((DWORD)delay.GetMicroSeconds())/1000);
	Sleep(t);
}

inline OSTime &OSTime::operator-=(const OSTime &t)
{ 
	sec -= t.sec; 
	if (t.microsec > microsec)
	{
		sec--;
		microsec += 1000000;
	}
	microsec -= t.microsec;
	return *this;
}

inline OSTime &OSTime::operator+=(const OSTime &t)
{ 
	sec += t.sec; 
	microsec += t.microsec;
	if (microsec >= 1000000)
	{
		sec++;
		microsec -= 1000000;
	}
	return *this;
}
inline bool OSTime::operator<(const OSTime &t) const
{
	if (sec < t.sec)
		return true;
	if (sec > t.sec)
		return false;
	if (microsec < t.microsec)
		return true;
	return false;
}

inline bool OSTime::operator>(const OSTime &t) const
{
	if (sec > t.sec)
		return true;
	if (sec < t.sec)
		return false;
	if (microsec > t.microsec)
		return true;
	return false;
}

inline bool OSTime::operator<=(const OSTime &t) const
{
	if (sec < t.sec)
		return true;
	if (sec > t.sec)
		return false;
	if (microsec <= t.microsec)
		return true;
	return false;
}

inline bool OSTime::operator>=(const OSTime &t) const
{
	if (sec > t.sec)
		return true;
	if (sec < t.sec)
		return false;
	if (microsec >= t.microsec)
		return true;
	return false;
}

#endif