#ifndef SAFELONG_H_INCLUDED
#define SAFELONG_H_INCLUDED
///////////////////////////////////////////////////////////////////////////////////
/// This is a wrapper for the InterLocked... Windows APIs.
/// Instead of using then you can instantiate this class and work with it
/// as a normal long number. 
//  All operations will safe for multithreaded access.
///////////////////////////////////////////////////////////////////////////////////
#include <windows.h>

class SafeLong
{
public:
	SafeLong(void) { InterlockedExchange(&m_value, 0); };
	~SafeLong(void) {};

	SafeLong& operator+=(const SafeLong &_Right)
	{
		InterlockedExchangeAdd(&m_value, _Right.m_value); 
		return *this;
	}

	SafeLong& operator-=(const SafeLong &_Right)
	{
		InterlockedExchange(&m_value, m_value - _Right.m_value); 
		return *this;
	}
	SafeLong& operator=(const SafeLong &_Right)
	{
		InterlockedExchange(&m_value, _Right.m_value); 
		return *this;
	}

	SafeLong& operator+=(const long _Right)
	{
		InterlockedExchangeAdd(&m_value, _Right); 
		return *this;
	}

	SafeLong& operator-=(const long _Right)
	{
		InterlockedExchange(&m_value, m_value - _Right); 
		return *this;
	}

	SafeLong& operator=(const long _Right)
	{
		InterlockedExchange(&m_value, _Right); 
		return *this;
	}

	bool operator==(const SafeLong &_Right)
	{
		return m_value == _Right.m_value;
	}

	bool operator!=(const SafeLong &_Right)
	{
		return !(m_value == _Right.m_value);
	}

	bool operator==(const long _Right)
	{
		return m_value == _Right;
	}

	bool operator!=(const long _Right)
	{
		return !(m_value == _Right);
	}

	operator long()
	{
		return m_value;
	}

	operator bool()
	{
		return m_value ? true : false; 
	}

	SafeLong& operator++(int pos)
	{
        if (pos == 0)
		{
			InterlockedIncrement(&m_value);
		}
		else
		{
			InterlockedExchangeAdd(&m_value, pos+1);
		}
		return *this;
	}

	SafeLong& operator--(int pos)
	{
        if (pos == 0)
	{
	        InterlockedDecrement(&m_value);
		}
		else
		{
			InterlockedExchangeAdd(&m_value, - (pos+1));
		}
		return *this;
	}
private:
	long m_value;
};

#endif //SAFELONG_H_INCLUDED
