package es.ejie.frmk.infraestructura.utilidades.concurrencia;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.control.excepciones.Q70GestorDeExcepcionesServidor;
import es.ejie.frmk.infraestructura.logs.base.Q70LogInterno;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.utilidades.constantes.Q70UtilidadesConstantes;
import es.ejie.frmk.infraestructura.utilidades.excepciones.Q70UtilidadesExcepcion;

/**
 * Clase que actúa como candado para todos los threads que vayan a entrar a la
 * zona crítica.
 * @version 2.0 Fecha: 23-mar-2006
 */
public class Q70LockThreads {
	
	// Referencia a la clase que contiene las variables que condicionan el bloqueo/desbloqueo.
	private Q70Lock lock = null;
	
	/**
	 * Constructor privado para que se use el otro constructor obligatoriamente.
	 */
	private Q70LockThreads(){
	}
	
	public Q70LockThreads(Q70Lock lock) {
		this.lock = lock;
	}
	
	/**
	 * Método que desactiva el bloqueo y activa los threads bloqueados.
	 */
	synchronized protected void activar() {
		// Desactiva el bloqueo
		lock.setBloqueo(false);
		// Activa todos los threads bloquedos
		notifyAll();
	}

	/**
	 * Método que suma uno al contador de threads en la zona crítica y bloquea
	 * la entrada a la zona crítica en caso de que se haya activado el bloqueo.
	 */
	synchronized protected void entradaZonaCritica() {
		// Si el bloqueo esta activado...
		if (lock.isBloqueo()) {
			try {
				// suspendo los threads que intenten entrar a la zona crítica
				wait();
			} catch (InterruptedException e) {
				// Si el componente a reconfigurar es LOGS o TRAZAS, utilizamos Q70LogInterno.
				if (lock.isComponenteLogsTraza()) {
					Q70LogInterno.log("\nERROR!!! En la entrada de la zona critica se ha intentado suspender un thread que ya estaba suspendido.\n");
				} else {
					Q70Factoria.getTraza().trace(Q70UtilidadesConstantes.UTILIDADES_LOCK, Q70TraceLevel.FATAL, "\nERROR!!! En la entrada de la zona critica se ha intentado suspender un thread que ya estaba suspendido.\n");
				}
				Q70GestorDeExcepcionesServidor.getSingleton().recogerThrowable(new Q70UtilidadesExcepcion(Q70UtilidadesConstantes.UTILIDADES_LOCK, this.getClass().getName(),"entradaZonaCritica","ERROR!!! En la entrada de la zona critica se ha intentado suspender un thread que ya estaba suspendido.", e));
			}
		}
		// Sumo uno al contador de threads en la zona crítica.
		lock.mas();
	}
}