/* Classe d'objets avec une methode (DoPeriodic()) appelee periodiquement */
/*                                  Eric Aubourg     04/96                */
/*                                  Reza Ansari      06/96                */
/*                      LAL/IN2P3 (Orsay)  DAPNIA/CEA (Saclay)            */

#include "machdefs.h"
#include <signal.h>
#include <unistd.h>

#include "periodic.h"

/* --Methode-- */
Periodic::Periodic(int dt, UsPeriodicAction act, void * usp)
{
mDt = dt;
mAct = act;
mUsp = usp;
if (mDt < 1)  mDt = 5;
mDtms = 1000*mDt;
mFgact = false;
it = -1;
}

/* --Methode-- */
Periodic::~Periodic()
{
if (mFgact) Stop();
}

/* --Methode-- */
void Periodic::SetAction(UsPeriodicAction act, void * usp)
{
mAct = act;
mUsp = usp;
}

/* --Methode-- */
void Periodic::SetInterval(int dt)
{
mDt = dt;
if (mDt < 1)  mDt = 5;
mDtms = 1000*mDt;
}

/* --Methode-- */
void Periodic::SetIntervalms(int dtms)
{
if (dtms < 1) dtms = 5;
mDtms = dtms;
mDt = mDtms/1000;
if (mDt < 1)  mDt = 1;
}

/* --Methode-- */
void Periodic::Start(int dt)
{
if (mFgact)  return;
if (dt > 0)  { mDt = dt;  mDtms = dt*1000; }
if (!actifs) actifs = new PeriodicList;
it = 0;
if (actifs->size() == 0) {
  signal(SIGALRM, CallBack);
  alarm(1);
  }
actifs->push_back(this);
mFgact = true;
return;
}

/* --Methode-- */
void Periodic::Stop()
{
if (!mFgact)  return;

//remove(actifs->begin(), actifs->end(), this);  // $CHECK$ - Reza
actifs->remove(this);    // $CHECK$ 
if (actifs->size() == 0) {
  signal(SIGALRM, SIG_IGN);
  alarm(0);
  delete actifs;
  actifs = NULL;
  }
it = -1;  mFgact = false;
return;
}

/* --Methode-- */
void Periodic::DoPeriodic()
{
if (mAct)   mAct(mUsp);
}

PeriodicList* Periodic::actifs = NULL;

void Periodic::CallBack(int)
{
  if (!actifs) return;

  for (PeriodicList::iterator i = actifs->begin(); i != actifs->end(); i++) {
    Periodic* p = (Periodic*) *i;
    p->it ++;
    if (p->it >= p->mDt) {
      p->it = 0;
      p->DoPeriodic();
    }
  }
  alarm(1);
}

