#pragma once


//!	CreateMutexを保持する関数
class CSyncMutex
{
public:
	CSyncMutex()
	{
		m_mutex = NULL;
	};
	
	virtual ~CSyncMutex()
	{
		Close();
	};

	//	作成
	int Create(BOOL bInitialOwner)
	{
		Close();

		m_mutex = ::CreateMutex(NULL,bInitialOwner,NULL);
		if(m_mutex == NULL)
			return(-1);
		return(0);
	}

	//	閉じる
	void Close()
	{
		SAFE_CLOSE_HANDLE(m_mutex);
	}

	//	ハンドルの取得
	__inline operator HANDLE() { return m_mutex; };

protected:
	HANDLE	m_mutex;
};

//!	CreateEventを保持する関数
class CSyncEvent
{
public:
	CSyncEvent()
	{
		m_event = NULL;
	};
	
	virtual ~CSyncEvent()
	{
		Close();
	};

	//	作成
	int Create(BOOL bManualReset, BOOL bInitialState)
	{
		Close();

		m_event = ::CreateEvent(NULL,bManualReset,bInitialState,NULL);
		if(m_event == NULL)
			return(-1);
		return(0);
	}

	//	閉じる
	void Close()
	{
		SAFE_CLOSE_HANDLE(m_event);
	}

	//	ハンドルの取得
	__inline operator HANDLE() { return m_event; };

protected:
	HANDLE	m_event;
};


//!	CSyncSemaphoreを保持する関数
class CSyncSemaphore
{
public:
	CSyncSemaphore()
	{
		m_semaphore = NULL;
	};
	
	virtual ~CSyncSemaphore()
	{
		Close();
	};

	//	作成
	int Create(LONG lInitialCount, LONG lMaximumCount)
	{
		Close();

		m_semaphore = ::CreateSemaphore(NULL,lInitialCount,lMaximumCount,NULL);
		if(m_semaphore == NULL)
			return(-1);
		return(0);
	}

	//	閉じる
	void Close()
	{
		SAFE_CLOSE_HANDLE(m_semaphore);
	}

	//	ハンドルの取得
	__inline operator HANDLE() { return m_semaphore; };

protected:
	HANDLE	m_semaphore;
};

//!	WaitableTimerを保持する関数
class CSyncTimer
{
public:
	CSyncTimer()
	{
		m_timer = NULL;
	};
	
	virtual ~CSyncTimer()
	{
		Close();
	};

	//	作成
	int Create(int waitMs)
	{
		Close();

		//	作成
		m_timer = ::CreateWaitableTimer(NULL,FALSE,NULL);
		if(m_timer == NULL)
			return(-1);

		//	起動
		LARGE_INTEGER	largeTime;
		largeTime.QuadPart = -10000 * (__int64)waitMs;
		if(!SetWaitableTimer(m_timer, &largeTime, waitMs, NULL, NULL, FALSE))
			return(-1);

		return(0);
	}

	//	閉じる
	void Close()
	{
		SAFE_CLOSE_HANDLE(m_timer);
	}

	//	ハンドルの取得
	__inline operator HANDLE() { return m_timer; };

protected:
	HANDLE	m_timer;
};


//	Interlockedカウンタ
class CInterlockCounter
{
protected:
	LONG	m_counter;

public:
	//	初期化
	CInterlockCounter()
	{
		::InterlockedExchange(&m_counter,0);
	};

	//	インクリメント
	__inline int IncCounter()
	{
		return(::InterlockedIncrement(&m_counter));
	};

	//	デクリメント
	__inline int DecCounter()
	{
		return(::InterlockedDecrement(&m_counter));
	};

	//	加算
	__inline int AddCounter(int add)
	{
		return(::InterlockedExchangeAdd(&m_counter, add));
	};

	//	取得
	__inline int GetCounter()
	{
		return(::InterlockedExchangeAdd(&m_counter,0));
	};

	//	設定
	__inline void SetCounter(int count)
	{
		::InterlockedExchange(&m_counter,count);
	};

	///////////////////////////////////////////////////////////////////
	//	演算子
	///////////////////////////////////////////////////////////////////
	//	取得
	__inline operator int()
	{
		return(::InterlockedExchangeAdd(&m_counter,0));
	};

	//	設定
	__inline void operator=(const int &other)
	{
		::InterlockedExchange(&m_counter,other);
	};
/*
	//	インクリメント
	__inline int operator++()
	{
		return(::InterlockedIncrement(&m_counter));
	};

	//	デクリメント
	__inline int operator--()
	{
		return(::InterlockedDecrement(&m_counter));
	};
*/
};


//!	IOCP
class CIOCompletePort
{
public:
	//!	初期化
	CIOCompletePort()
	{
		m_hIocp = NULL;
	};

	//!	終了
	virtual ~CIOCompletePort()
	{
		Close();
	};
	
	
	//!	作成
	int Create(int NumberOfConcurrentThreads, HANDLE attach = INVALID_HANDLE_VALUE, int key = 0)
	{
		Close();

		m_hIocp = CreateIoCompletionPort(attach, NULL, key, NumberOfConcurrentThreads);
		if(m_hIocp == NULL)
			return(-1);

		return(0);
	};

	//!	閉じる
	void Close()
	{
		SAFE_CLOSE_HANDLE(m_hIocp);
	}

	//!	割り当て
	int SetToDeviceHANDLE(HANDLE hDevice, ULONG_PTR dwCompKey)
	{
		HANDLE ret = CreateIoCompletionPort(hDevice, m_hIocp, dwCompKey, 0);
		if(ret != m_hIocp)
			return(-1);

		return(0);
	};
	
	//!	割り当て
	static int SetToDeviceHANDLE(HANDLE hIocp, HANDLE hDevice, ULONG_PTR dwCompKey)
	{
		HANDLE ret = CreateIoCompletionPort(hDevice, hIocp, dwCompKey, 0);
		if(ret != hIocp)
			return(-1);

		return(0);
	};

	//	ハンドルの取得
	__inline operator HANDLE() { return m_hIocp; };

protected:
	///////////////////////////////////////////////////////////////////
	//	メンバ
	///////////////////////////////////////////////////////////////////
	//!	IOCP
	HANDLE	m_hIocp;
};

/*!
	自動同期ラッパ
*/
template<class TYPE>
class CLockObject
{
	CCriticalSection	m_scopeLock;

protected:
	TYPE	m_data;

public:
	void operator=(TYPE &other)
	{
		SCOPE_LOCK();
		m_data = other;
	}

	void operator=(TYPE other)
	{
		SCOPE_LOCK();
		m_data = other;
	}

	operator TYPE()
	{
		SCOPE_LOCK();
		return(m_data);
	}
};
