#pragma once
#include "th.h"
#include "gcola_con.h"


template <typename T>
struct Timers_Cth_cola
{
	T tarea;//tarea a encadenar
	__int64 t;//tiempo desde la ultima ejecucion
	int dt;//periodo del timer
};
//------------------------------------------------------------
class Cth_rimers_cola : //tread para los timers
	public Cth
{
public:
	Crunable *clase_run;
	inline virtual void run()
	{
		clase_run->frun(0);
	}
};
//cola asincrona--------------------------------------------
//thread de tareas tipico-----------------------------------
template <typename T>
class Cth_cola : //falta probar, poner timers
	public Cth, Crunable
{
public:
	Cgcola_con<T> cola;//cola de tareas pendientes
	Cgcola_con<Timers_Cth_cola<T>> timers;//tareas periodicas activas
	BOOL pirate;//indica al tread que hay que terminar
	BOOL eje_fin;//indica que hay que ejecutar la tarea final
	int time_sleep;//tiempo de espera cuando no hay tareas
	int tp_max;//maximo de tareas pendientes en cola
	T tfin;//tarea final;
	Cth_rimers_cola thtimers;//thread de control de tareas periodicas
	//constructor y destructor--------------------------------
	//**************************************************
	Cth_cola(void)
	{
		pirate=FALSE;
		time_sleep=1;
		tp_max=1000;
		eje_fin=FALSE;
		thtimers.clase_run=this;
		thtimers.join();
		

	};
	//**************************************************
	~Cth_cola(void)
	{
		fin();
	};
	//funciones-----------------------------------------------
	void pon_tfin(T &e)
	{
		tfin=e;
		eje_fin=TRUE;
	};
	//**************************************************
	virtual inline BOOL operator+(T &e )//aņade tarea
	{
		return !pirate && cola.n<=tp_max && cola+e;
	};
	//**************************************************
	virtual inline BOOL operator-(T &e )//aņade tarea y elimina el resto
	{
		if (pirate)
			return FALSE;
		cola.cerrojo.entro();
		cola.borra();
		cola.cerrojo.salgo();
		return cola+e;
	};
	//**************************************************
	virtual void fin()//termina el proceso
	{
		pirate=TRUE;
		thtimers.join();
		join();

	};
	//**************************************************
	BOOL pon_timer(int seg, T &tar)//pone una tarea periodica siendo t el periodo en seg
	{
		Timers_Cth_cola<T> tim;
		tim.t=0;
		tim.tarea=tar;
		tim.dt=seg;
		timers+tim;
		return TRUE;
	};
	//**************************************************
	virtual void procesa(T &t)//override de procesado que hay que sobreescribir
	{

	};
	//**************************************************
	virtual void run()//proceso que despacha
	{
		T tarea;
		sprintf(thtimers.nombre,"%s_timers",nombre);
		if (timers.n)
			thtimers.lanza();
		while (!pirate)
		{
			if (cola-=&tarea)
				procesa(tarea);
			else
				Sleep(time_sleep);
		}
		if(eje_fin)
			procesa(tfin);
	};
	//**************************************************
	virtual void frun(int modo=0)//proceso del timer
	{
		__int64 t;
		Element_Cgcola<Timers_Cth_cola<T>> *e;
		while(!pirate)
		{
			timers.cerrojo.entro();
			e=timers.ini;
			t=_time64(NULL);
			while(e)
			{
				if (e->t.t<t)
				{
					if(Cth_cola::operator+(e->t.tarea))
						e->t.t=t+e->t.dt;
				}
				e=e->sig;
			}
			Sleep(500);
		}
	};
	//**************************************************
};
