275 lines
6.2 KiB
C++
275 lines
6.2 KiB
C++
/**
|
|
@file AsyncAtTimer.cpp
|
|
@brief A timer that times out at a specified absolute time
|
|
@author Tobias Blomberg / SM0SVX
|
|
@date 2013-04-06
|
|
|
|
This class is used to get a timeout at a specified absolute time. That is,
|
|
you can specify a time of day, like 2013-04-06 12:43:00, when you would
|
|
like the timer to expire.
|
|
|
|
\verbatim
|
|
Async - A library for programming event driven applications
|
|
Copyright (C) 2003-2013 Tobias Blomberg / SM0SVX
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
\endverbatim
|
|
*/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* System Includes
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <sys/time.h>
|
|
#include <iostream>
|
|
#include <cstdio>
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Project Includes
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Local Includes
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "AsyncAtTimer.h"
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Namespaces to use
|
|
*
|
|
****************************************************************************/
|
|
|
|
using namespace std;
|
|
using namespace Async;
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Defines & typedefs
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Local class definitions
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Prototypes
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Exported Global Variables
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Local Global Variables
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Public member functions
|
|
*
|
|
****************************************************************************/
|
|
|
|
AtTimer::AtTimer(void)
|
|
{
|
|
timerclear(&m_expire_at);
|
|
m_timer.expired.connect(mem_fun(*this, &AtTimer::onTimerExpired));
|
|
} /* AtTimer::AtTimer */
|
|
|
|
|
|
AtTimer::AtTimer(struct tm &tm, bool do_start)
|
|
{
|
|
timerclear(&m_expire_at);
|
|
m_timer.expired.connect(mem_fun(*this, &AtTimer::onTimerExpired));
|
|
setTimeout(tm);
|
|
if (do_start)
|
|
{
|
|
start();
|
|
}
|
|
} /* AtTimer::AtTimer */
|
|
|
|
|
|
AtTimer::~AtTimer(void)
|
|
{
|
|
|
|
} /* AtTimer::~AtTimer */
|
|
|
|
|
|
bool AtTimer::setTimeout(time_t t)
|
|
{
|
|
m_expire_at.tv_sec = t;
|
|
if (m_timer.isEnabled())
|
|
{
|
|
return start();
|
|
}
|
|
return true;
|
|
} /* AtTimer::setTimeout */
|
|
|
|
|
|
bool AtTimer::setTimeout(struct tm &tm)
|
|
{
|
|
time_t t = mktime(&tm);
|
|
if (t == -1)
|
|
{
|
|
cerr << "mktime[AtTimer::setTimeout]: Could not set the timeout due to "
|
|
"an invalid time format\n";
|
|
return false;
|
|
}
|
|
return setTimeout(t);
|
|
} /* AtTimer::setTimeout */
|
|
|
|
|
|
void AtTimer::setExpireOffset(int offset_ms)
|
|
{
|
|
m_expire_offset = offset_ms;
|
|
} /* AtTimer::setExpireOffset */
|
|
|
|
|
|
bool AtTimer::start(void)
|
|
{
|
|
int msec = msecToTimeout();
|
|
if (msec == -1)
|
|
{
|
|
return false;
|
|
}
|
|
m_timer.setTimeout(msec);
|
|
m_timer.setEnable(true);
|
|
return true;
|
|
} /* AtTimer::start */
|
|
|
|
|
|
void AtTimer::stop(void)
|
|
{
|
|
m_timer.setEnable(false);
|
|
} /* AtTimer::stop */
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Protected member functions
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Private member functions
|
|
*
|
|
****************************************************************************/
|
|
|
|
/**
|
|
* @brief This function will calculate what to set the timer to
|
|
* @return Returns the number of milliseconds to set the timer to
|
|
*
|
|
* This function will calculate how many milliseconds there is left to the
|
|
* wanted timeout time. If the time is larger than one minute it will be
|
|
* chopped up in 59 second chunks so as to not loose precision.
|
|
* One second before the wanted timeout time occurrs, a last timer is
|
|
* schedules so as to obtain good precision for the final timeout.
|
|
*/
|
|
int AtTimer::msecToTimeout(void)
|
|
{
|
|
struct timeval now;
|
|
if (gettimeofday(&now, 0) == -1)
|
|
{
|
|
perror("gettimeofday[AtTimer::msecToTimeout]");
|
|
return -1;
|
|
}
|
|
|
|
struct timeval diff;
|
|
timersub(&m_expire_at, &now, &diff);
|
|
|
|
long long msec = static_cast<long long>(diff.tv_sec) * 1000
|
|
+ diff.tv_usec / 1000 + m_expire_offset + 1;
|
|
if (msec < 0)
|
|
{
|
|
msec = 0;
|
|
}
|
|
else if (msec > 60000)
|
|
{
|
|
msec = 59000;
|
|
}
|
|
else if (msec > 1500)
|
|
{
|
|
msec -= 1000;
|
|
}
|
|
|
|
return static_cast<int>(msec);
|
|
} /* AtTimer::msecToTimeout */
|
|
|
|
|
|
/**
|
|
* @brief Called by the timer when it expires
|
|
* @param t The timer object
|
|
*
|
|
* This function will be called by the timer when it expires. If the specified
|
|
* time of day have not been reached, the timer will be restarted.
|
|
*/
|
|
void AtTimer::onTimerExpired(Timer *t)
|
|
{
|
|
int msec = msecToTimeout();
|
|
if (msec > 0)
|
|
{
|
|
m_timer.setTimeout(msec);
|
|
}
|
|
else
|
|
{
|
|
expired(this);
|
|
}
|
|
} /* AtTimer::onTimerExpired */
|
|
|
|
|
|
|
|
/*
|
|
* This file has not been truncated
|
|
*/
|
|
|