//----------------------------------------------------
/**
	\file		ctk/inc/sync.h
	\ingroup	general	
	\ingroup	all

	\brief		Funkce pro synchronizaci automatu pri
				pristupu ke globalnim promennym
				<<< ALL >>>
			
	\author		ConTeK s.r.o., Ing. Petr Cernin
	\version	01.01
	\date		12.01.2007
*/
//----------------------------------------------------


#ifndef _SYNC_H_
#define _SYNC_H_	//!< Definice pritomnosti knihovny

#include <ctktypes.h>
#include <hwmodel.h>

//--------------------------------------------------
/**
	\brief	definice typu flock_t
*/
//--------------------------------------------------

typedef uint8_t flock_t;


//--------------------------------------------------
/**
	\brief	Vstup do kriticke sekce

	\return	Pocet vnorenych FastLocku

	\note	Hodnotu nutno poznamenat
			bude potreba pri FastUnlocku
*/
//--------------------------------------------------

flock_t FastLock( void );


//--------------------------------------------------
/**
	\brief	Vystup z kriticke sekce

	\param	lock	Pocet vnorenych FastLocku
					hodnota navracena FastLockem
*/
//--------------------------------------------------

void FastUnlock( const flock_t lock );


//--------------------------------------------------
/**
	\brief	Vstup do kriticke sekce nerekurzivni

	\note	Pouzivat jen vyjimecne
			(zakazani preruseni)
*/
//--------------------------------------------------

void _FastLock( void );


//--------------------------------------------------
/**
	\brief	Vystup z kriticke sekce nerekurzivni

	\note	Pouzivat jen vyjimecne
			(povoleni preruseni na zacatku programu)
*/
//--------------------------------------------------

void _FastUnlock( void );


//--------------------------------------------------
/**
	\brief	Promene uchovavajici delku FastLocku
*/
//--------------------------------------------------

#ifdef SYNC_FASTLOCK_MEASURE
extern volatile hrctime_t gFastLockTime, gFastLockMaxTime; //!< Promenne uchovavajici delku FastLocku
#endif // SYNC_FASTLOCK_MEASURE

//--------------------------------------------------
/**
	\brief	Atomicky presun mezi promennymi, rekurzivni
*/
//--------------------------------------------------
#define AtomMove( dest, src ) \
	if (sizeof(dest) <= ATOM_BYTES) \
	{ \
		(dest) = (src); \
	} \
	else \
	{ \
		flock_t AtomMoveLock = FastLock(); \
		(dest) = (src); \
		FastUnlock( AtomMoveLock ); \
	}

//--------------------------------------------------
/**
	\brief	Atomicky zapis do promenne, rekurzivni
*/
//--------------------------------------------------
#define AtomWrite( dest, src ) \
	do { \
		AtomMove( dest, src ); \
	} while (0)

#ifndef MSVC

//--------------------------------------------------
/**
	\brief	Atomicke cteni promenne, rekurzivni
*/
//--------------------------------------------------
#define AtomRead( src ) \
	((sizeof( src ) <= ATOM_BYTES) ? \
		(src) : \
		(  { \
			typeof( src ) _src; \
			flock_t AtomReadLock = FastLock(); \
			_src = src; \
			FastUnlock( AtomReadLock ); \
			_src; \
		} ))

#else
template <class T>
static inline T AtomRead(T src) 
{
	T tmp;
	flock_t _atomreadlock = FastLock();
	tmp = src;
	FastUnlock(_atomreadlock);
	return tmp;
}

#endif // MSVC

//--------------------------------------------------
/**
	\brief	Inicializace kriticke sekce

	\note	Tuto funkci zavolat jednou
			pred prvnim volanim FastLock/Unlock
*/
//--------------------------------------------------

bool_t FastLockInitialize( void );


//--------------------------------------------------
/**
	\brief	Ukonceni cinnosti kriticke sekce

	\note	Tuto funkci zavolat jednou
			pred prvnim volanim FastLock/Unlock
*/
//--------------------------------------------------

void FastLockFinalize( void );

#endif // _SYNC_H_
