common/selectabletimer.cpp (92 lines of code) (raw):
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <system_error>
#include "common/logger.h"
#include "common/selectabletimer.h"
namespace swss {
SelectableTimer::SelectableTimer(const timespec& interval, int pri)
: Selectable(pri), m_zero({{0, 0}, {0, 0}})
{
// Create the timer
m_tfd = timerfd_create(CLOCK_MONOTONIC, 0);
if (m_tfd == -1)
{
SWSS_LOG_THROW("failed to create timerfd, errno: %s", strerror(errno));
}
setInterval(interval);
m_running = false;
}
SelectableTimer::~SelectableTimer()
{
int err;
do
{
err = close(m_tfd);
}
while(err == -1 && errno == EINTR);
}
void SelectableTimer::start()
{
m_mutex.lock();
if (!m_running)
{
// Set the timer interval and the timer is automatically started
int rc = timerfd_settime(m_tfd, 0, &m_interval, NULL);
if (rc == -1)
{
SWSS_LOG_THROW("failed to set timerfd, errno: %s", strerror(errno));
}
else
{
m_running = true;
}
}
m_mutex.unlock();
}
void SelectableTimer::stop()
{
m_mutex.lock();
if (m_running)
{
// Set the timer interval and the timer is automatically started
int rc = timerfd_settime(m_tfd, 0, &m_zero, NULL);
if (rc == -1)
{
SWSS_LOG_THROW("failed to set timerfd to zero, errno: %s", strerror(errno));
}
else
{
m_running = false;
}
}
m_mutex.unlock();
}
void SelectableTimer::reset()
{
stop();
start();
}
void SelectableTimer::setInterval(const timespec& interval)
{
// The initial expiration and intervals to caller specified
m_interval.it_value = interval;
m_interval.it_interval = interval;
}
int SelectableTimer::getFd()
{
return m_tfd;
}
uint64_t SelectableTimer::readData()
{
uint64_t cnt = 0;
ssize_t ret;
errno = 0;
do
{
ret = read(m_tfd, &cnt, sizeof(uint64_t));
}
while(ret == -1 && errno == EINTR);
ABORT_IF_NOT((ret == 0) || (ret == sizeof(uint64_t)), "Failed to read timerfd. ret=%zd", ret);
// cnt = count of timer events happened since last read.
return cnt;
}
}