From ccd6240e232338e46bd805a04fb731c53fb1deb2 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 26 Jul 2007 12:08:22 +0100 Subject: [PATCH] Add a Timer class (bug #46) --- src/simulator/timer.cc | 81 +++++++++++++++ src/simulator/timer.h | 223 +++++++++++++++++++++++++++++++++++++++++ src/simulator/wscript | 2 + 3 files changed, 306 insertions(+) create mode 100644 src/simulator/timer.cc create mode 100644 src/simulator/timer.h diff --git a/src/simulator/timer.cc b/src/simulator/timer.cc new file mode 100644 index 000000000..823efb65b --- /dev/null +++ b/src/simulator/timer.cc @@ -0,0 +1,81 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INESC Porto + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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 + * + * Author: Gustavo Carneiro + */ + +#include "timer.h" + +#ifdef RUN_SELF_TESTS + +#include "ns3/test.h" + +namespace ns3 { + +class TimerTests : public Test +{ + int m_counter; +public: + TimerTests (); + virtual ~TimerTests (); + virtual bool RunTests (void); + + void TimerCallback (int x); +}; + +TimerTests::TimerTests () + : Test ("Timer"), m_counter (0) +{} +TimerTests::~TimerTests () +{} + +void +TimerTests::TimerCallback (int x) +{ + m_counter += x; +} + +bool TimerTests::RunTests (void) +{ + bool result = true; + + Timer timer1 (MilliSeconds (1), MakeCallback (&TimerTests::TimerCallback, this)); + + // Check if it works in the common case + timer1.Schedule (1); + Simulator::Run (); + NS_TEST_ASSERT_EQUAL (m_counter, 1); + + // Check that it does not repeat itself + Simulator::Run (); + NS_TEST_ASSERT_EQUAL (m_counter, 1); + + // Check cancellation + timer1.Schedule (1); + timer1.Cancel (); + Simulator::Run (); + NS_TEST_ASSERT_EQUAL (m_counter, 1); + + return result; +} + +static TimerTests g_timerTests; + +}; + +#endif /* RUN_SELF_TESTS */ diff --git a/src/simulator/timer.h b/src/simulator/timer.h new file mode 100644 index 000000000..6be706fa6 --- /dev/null +++ b/src/simulator/timer.h @@ -0,0 +1,223 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INESC Porto + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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 + * + * Author: Gustavo Carneiro + */ +#ifndef TIMER_H +#define TIMER_H + +#include "simulator.h" +#include "ns3/callback.h" +#include "nstime.h" + +namespace ns3 { + +template +class Timer +{ +public: + typedef Callback CallbackType; + +protected: + Time m_interval; + CallbackType m_callback; + EventId m_eventId; + T1 m_t1; + T2 m_t2; + T3 m_t3; + T4 m_t4; + T5 m_t5; + + +public: + + /** + * \brief create a new timer object + * + * Constructs a new timer object with the given interval and callback. + * The timer will not actually start until Schedule() is called. + * + * \param interval The time interval after which the timer will expire + * \param callback The callback object that will be invoked when the + * timer expires + * + */ + Timer (Time const &interval, CallbackType callback) + : m_interval (interval), m_callback (callback) + { + } + + Timer (CallbackType callback) + : m_callback (callback) + { + } + + bool IsRunning () const + { + return m_eventId.IsRunning (); + } + + /** + * \brief start the timer + * + * Calling Schedule() on a timer essentially starts running + * it. After the configured interval, the timer will expire and the + * registered callback will be invoked. + */ + void Schedule () + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + m_eventId = Simulator::Schedule (m_interval, &Timer::Expired, this); + } + void Schedule (T1 v1) + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + m_eventId = Simulator::Schedule (m_interval, &Timer::Expired, this, + v1); + } + void Schedule (T1 v1, T2 v2) + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + m_eventId = Simulator::Schedule (m_interval, &Timer::Expired, this, + v1, v2); + } + void Schedule (T1 v1, T2 v2, T3 v3) + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + m_eventId = Simulator::Schedule (m_interval, &Timer::Expired, this, + v1, v2, v3); + } + void Schedule (T1 v1, T2 v2, T3 v3, T4 v4) + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + m_eventId = Simulator::Schedule (m_interval, &Timer::Expired, this, + v1, v2, v3, v4); + } + void Schedule (T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + m_eventId = Simulator::Schedule (m_interval, &Timer::Expired, this, + v1, v2, v3, v4, v5); + } + + /** + * \brief changes the time interval for future Schedule() calls + * + * \param interval The time interval after which the timer will expire + */ + void SetInterval (Time const &interval) + { + m_interval = interval; + } + + /** + * \brief cancel the timer + * + * Cancels the timer; after calling Cancel () the registered + * callback will no longer be invoked, unless Schedule() is called + * again. May be called even if the timer is not running. + */ + void Cancel () + { + if (m_eventId.IsRunning ()) + Simulator::Cancel (m_eventId); + } + + ~Timer () + { + Cancel (); + } + + /** + * \brief artificially expire the timer + * + * Expires the timer at the current time. This will result in the + * registered callback to be invoked and the previously schedule + * timeout, if any, to be cancelled. + */ + void Expire () + { + Cancel (); + Expired (); + } + void Expire (T1 v1) + { + Cancel (); + Expired (v1); + } + void Expire (T1 v1, T2 v2) + { + Cancel (); + Expired (v1, v2); + } + void Expire (T1 v1, T2 v2, T3 v3) + { + Cancel (); + Expired (v1, v2, v3); + } + void Expire (T1 v1, T2 v2, T3 v3, T4 v4) + { + Cancel (); + Expired (v1, v2, v3, v4); + } + void Expire (T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) + { + Cancel (); + Expired (v1, v2, v3, v4, v5); + } + +private: + void Expired () + { + m_callback (); + } + void Expired (T1 v1) + { + m_callback (v1); + } + void Expired (T1 v1, T2 v2) + { + m_callback (v1, v2); + } + void Expired (T1 v1, T2 v2, T3 v3) + { + m_callback (v1, v2, v3); + } + void Expired (T1 v1, T2 v2, T3 v3, T4 v4) + { + m_callback (v1, v2, v3, v4); + } + void Expired (T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) + { + m_callback (v1, v2, v3, v4, v5); + } + +}; + + +}; // namespace ns3 + +#endif /* TIMER_H */ diff --git a/src/simulator/wscript b/src/simulator/wscript index c9f14bd67..f043d65b6 100644 --- a/src/simulator/wscript +++ b/src/simulator/wscript @@ -55,6 +55,7 @@ def build(bld): sim.source = [ 'high-precision.cc', 'time.cc', + 'timer.cc', 'event-id.cc', 'scheduler.cc', 'scheduler-factory.cc', @@ -71,6 +72,7 @@ def build(bld): headers.source = [ 'high-precision.h', 'nstime.h', + 'timer.h', 'event-id.h', 'event-impl.h', 'simulator.h',