#include "psema.h"

/*! \ingroup Gpsema
\brief Initialise le descripteur de sémaphore
\param s adresse descripteur sémaphore
\param i nombre initial de jetons
\return  code d'erreur 0 OK 1 erreur
\warning la valeur initiale du sémaphore doit être positive ou nulle
*/

int PhilSemaphoreInit(PhilSemaphore *s, int     i)
{  
	/* le semaphore existe et la valeur initiale est >=0 */
	if ((s !=(PhilSemaphore *) 0)&&(i>=0)){
		s->counter = i;
		if(PhilMutexInit(&(s->lock)))return 1 ;
		if(PhilCondInit(&(s->queue)))return 1 ;
		return 0;
	}
	return 1;
}

/*! \ingroup Gpsema
\brief Détruit le  sémaphore
\param s adresse descripteur sémaphore
\return  code d'erreur 0 OK 1 erreur
\warning la valeur initiale du sémaphore doit être positive ou nulle
*/

int PhilSemaphoreDestroy(PhilSemaphore *s)
{ 
	/* le semaphore existe et la valeur initiale est >=0 */
	if (s !=(PhilSemaphore *) 0){
		if(PhilMutexDestroy(&(s->lock)))return 1 ;
		if(PhilCondDestroy(&(s->queue)))return 1 ;
		return 0;
	}
	return 1;
}



/*************************************************/
/*! \ingroup Gpsema
\brief Prend un jeton
\param s adresse descripteur sémaphore
\return  code d'erreur 0 OK 1 erreur
S'il n'y a pas de jeton, le thread se bloque. Il sera réveillé à son tour ( file d'attente FIFO à priorité) quand un jeton lui sera donné. 

\htmlonly <hr WIDTH="100%"> \endhtmlonly 
\htmlonly <hr WIDTH="100%"> \endhtmlonly 
\b Implantation
*/

int   PhilSemaphoreP(PhilSemaphore * s)
{
	if(!s)return 1;
	if(PhilMutexLock(&(s->lock)))return 1;/* début d'exclusion mutuelle */
	s->counter--;
	while(s->counter < 0){
		/* pas de jeton :  on suspend le thread actif   */
    if(PhilCondWait(&(s->queue),&(s->lock))){
			PhilMutexUnlock(&(s->lock));
			return 1  ; 
		}
	}              
  if(PhilMutexUnlock(&(s->lock)))return 1;/* fin d'exclusion mutuelle */
	return 0;
}

/*************************************************/
/*! \ingroup Gpsema
\brief Depose un jeton
\param s adresse descripteur sémaphore
\return  code d'erreur 0 OK 1 erreur
S'il y a des threads en attente d'un jeton, on réveille le + prioritaire.

\htmlonly <hr WIDTH="100%"> \endhtmlonly 
\htmlonly <hr WIDTH="100%"> \endhtmlonly 
\b Implantation

*/
int PhilSemaphoreV(PhilSemaphore * s)
{
	if(!s)return 1;
	if(PhilMutexLock(&(s->lock)))return 1;/* début d'exclusion mutuelle */
	s->counter++;
	if(s->counter <=0){
		/* il y a des demandeurs en attente */
		if(PhilCondSignal(&(s->queue)))return 1;
	}
	if(PhilMutexUnlock(&(s->lock)))return 1;/* fin d'exclusion mutuelle */
	return 0;
}





