#ifndef CRITSECTION_H
#define CRITSECTION_H

/**
 * Critical section
 * Critical Section object
 */
class ThreadSection
{
public:
	ThreadSection()
	{
		HRESULT hr = Init();
		(hr);
	}

	~ThreadSection()
	{
		DeleteCriticalSection(&_CriticalSection);
	}

	/// Enter/Lock a critical section
	bool Lock()
	{
		bool result = false;
		__try
		{
			EnterCriticalSection(&_CriticalSection);
			result = true;
		}
		__except (STATUS_NO_MEMORY == GetExceptionCode())
		{
		}
		return result;
	}

	/// Leave/Unlock a critical section
	bool Unlock()
	{
		bool result = false;
		__try
		{
			LeaveCriticalSection(&_CriticalSection);
			result = true;
		}
		__except (STATUS_NO_MEMORY == GetExceptionCode())
		{
		}
		return result;
	}

private:
	/// Initialize critical section
	HRESULT Init() throw()
	{
		HRESULT hRes = E_FAIL;
		__try
		{
			InitializeCriticalSection(&_CriticalSection);
			hRes = S_OK;
		}
		// structured exception may be raised in low memory situations
		__except (STATUS_NO_MEMORY == GetExceptionCode())
		{
			hRes = E_OUTOFMEMORY;
		}
		return hRes;
	}

	ThreadSection(const ThreadSection & tSection);
	ThreadSection &operator=(const ThreadSection & tSection);
	CRITICAL_SECTION _CriticalSection;
};


/**
 * AutoThreadSection class
 * Critical section auto-lock
 */
class AutoThreadSection
{
public:
	/// auto section - constructor
	AutoThreadSection(__in ThreadSection* pSection)
	{
		_pSection = pSection;
		_pSection->Lock();
	}

	~AutoThreadSection()
	{
		_pSection->Unlock();
	}
private:
	AutoThreadSection(const AutoThreadSection & tSection);
	AutoThreadSection &operator=(const AutoThreadSection & tSection);
	ThreadSection * _pSection;
};

#endif //CRITSECTION_H