//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: timer.cpp
//
//Version: $Revision: 1.27 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/10/19 08:46:02 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
// 
//Authors:
//      Pasi Nummisalo
//      Timo Pärnänen
//      Juhana Räsänen
//
//Description:
//      See corresponding header file.
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//     
//      
//Licence:
//     
//
//History:
//
//

#include "timer.h" 
#include "protocol.h"
#include "system.h"

pfTimer :: pfTimer(void)
    : sfTask(),
      _host(0),
      _timerMessenger(0),
      _active(0),
      _timeout(0)
{
    pfSystem::instance()->registerTimer(this);
    return;
}

pfTimer :: pfTimer(const pfTimer &other_)
    : sfTask(other_),
      _host(other_._host),
      _timerMessenger(0),
      _active(0),
      _timeout(other_._timeout)
{
    if (other_._timerMessenger != 0)
    {
        _timerMessenger = other_._timerMessenger->clone();
    }
    pfSystem::instance()->registerTimer(this);
    return;
} 

pfTimer :: ~pfTimer(void)
{
    if (isActive() != 0)
    {
        stop();
    }
    delete _timerMessenger;
    return;
}

//
//Function: assignment operator
//
//Description:
//    Define assignment operator for timer
//

const pfTimer &pfTimer :: operator = (const pfTimer &other_)
{
    if (this != &other_) // if not x = x situation
    {
        // If the timer to which the new values are copied is already
        // running, stop it first.
        if (isActive() != 0)
        {
            stop();
        }

        _host = other_._host;
        _timeout = other_._timeout;
        delete _timerMessenger;
        if (other_._timerMessenger != 0)
        {
            _timerMessenger = other_._timerMessenger->clone();
        }
        else
        {
            _timerMessenger = 0;
        }

        // NOTE: Do not re-register timer to the pfSystem, because at the
        //       time assignment is performed, also the left-hand side does
        //       exist and is thus registered by the constructor.
    }
    return *this;
}

//
//Function: setHost
//
//Description:
//    Set a host implementation of timer.
//

void pfTimer :: setHost(pfProtocol *host_)
{
    _host = host_;
    return;
}

//
//Function: setTimeout
//
//Description:
//	A timeout value computed from milliseconds
//	A different algorithm from SSCOP is given as an option.
//
//

void pfTimer :: setTimeout(pfUlong msec_)
{ 
#if 1
    pfUlong usec = (msec_ % 1000) * 1000;
    pfUlong sec = msec_ / 1000;
#else
    //pfUlong usec = (msec_ % 1000) * 1000;
    //pfUlong sec = (msec_ - (usec / 1000)) / 1000;
#endif
    _timeout = OTime(sec, usec);
    return;
}

//
//Function: setMessenger
//
//Description:
//    Set timer messenger.
//

void pfTimer :: setMessenger(pfTimerMessenger *timerMessenger_)
{
    if (_timerMessenger != 0)
    {
        delete _timerMessenger;
    }
    _timerMessenger = timerMessenger_;
    return;
}

//
//Function: start
//
//Description:
//    Start timer.
//

void pfTimer :: start(void)
{
    // If the timer is already active, stop it before restarting
    if (isActive() != 0)
    {
        stop();
    }
    requestTimeout(_timeout);
    _active = 1;
    return;
}

//
//Function: stop
//
//Description:
//    Stop timer
//

void pfTimer :: stop(void)
{
    cancelTimeout();
    _active = 0;
    return;
}

//
//Function: isActive
//
//Description:
//    Checks if timer is active
//

bool pfTimer :: isActive(void) const
{
    return _active;
}

//
//Function: timeoutCallback
//
//Description:
//    Indicate host that timeout occurs by sending timeout message to it.
//

void pfTimer :: timeoutCallback(void)
{
    _active = 0;
    pfTimerMessenger *timerMessenger = _timerMessenger->clone();
    pfMsgTransporter *timeoutMessage =
        pfMsgTransporter::createMsgTransporter(timerMessenger);
    timeoutMessage->setAcceptMethodToSynchronous();
    _host->accept(timeoutMessage);
    delete timeoutMessage;
    return;
}

