bug 954: Changing the simulation time resolution does not work well with attributes
v.3 Responding to code review comments https://codereview.appspot.com/6821106/
This commit is contained in:
@@ -340,6 +340,21 @@ Just as in any C++ program, you need to define a main function that will be
|
||||
the first function run. There is nothing at all special here. Your
|
||||
|ns3| script is just a C++ program.
|
||||
|
||||
The next line sets the time resolution to one nanosecond, which happens
|
||||
to be the default value:
|
||||
|
||||
::
|
||||
|
||||
Time::SetResolution (Time::NS);
|
||||
|
||||
The resolution is the smallest time value that can be represented (as well as
|
||||
the smallest representable difference between two time values).
|
||||
You can change the resolution exactly once. The mechanism enabling this
|
||||
flexibility is somewhat memory hungry, so once the resolution has been
|
||||
set explicitly we release the memory, preventing further updates. (If
|
||||
you don't set the resolution explicitly, it will default to one nanosecond,
|
||||
and the memory will be released when the simulation starts.)
|
||||
|
||||
The next two lines of the script are used to enable two logging components that
|
||||
are built into the Echo Client and Echo Server applications:
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
Time::SetResolution (Time::NS);
|
||||
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
||||
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
#include "attribute.h"
|
||||
#include "attribute-helper.h"
|
||||
#include "int64x64.h"
|
||||
#include "unused.h"
|
||||
#include <stdint.h>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -106,12 +108,12 @@ public:
|
||||
*/
|
||||
enum Unit
|
||||
{
|
||||
S = 0,
|
||||
MS = 1,
|
||||
US = 2,
|
||||
NS = 3,
|
||||
PS = 4,
|
||||
FS = 5,
|
||||
S = 0, //!< second
|
||||
MS = 1, //!< millisecond
|
||||
US = 2, //!< microsecond
|
||||
NS = 3, //!< nanosecond
|
||||
PS = 4, //!< picosecond
|
||||
FS = 5, //!< femtosecond
|
||||
LAST = 6
|
||||
};
|
||||
|
||||
@@ -122,42 +124,86 @@ public:
|
||||
}
|
||||
inline Time ()
|
||||
: m_data ()
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
inline Time(const Time &o)
|
||||
: m_data (o.m_data)
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (double v)
|
||||
: m_data (lround (v))
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (int v)
|
||||
: m_data (v)
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (long int v)
|
||||
: m_data (v)
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (long long int v)
|
||||
: m_data (v)
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (unsigned int v)
|
||||
: m_data (v)
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (unsigned long int v)
|
||||
: m_data (v)
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
explicit inline Time (unsigned long long int v)
|
||||
: m_data (v)
|
||||
{}
|
||||
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* \brief String constructor
|
||||
* Construct Time object from common time expressions like "
|
||||
* 1ms" or "10s". Supported units include:
|
||||
* - s (seconds)
|
||||
* - ms (milliseconds)
|
||||
* - us (microseconds)
|
||||
* - ns (nanoseconds)
|
||||
* - ps (picoseconds)
|
||||
* - fs (femtoseconds)
|
||||
* \brief Construct Time object from common time expressions like "1ms"
|
||||
*
|
||||
* Supported units include:
|
||||
* - `s` (seconds)
|
||||
* - `ms` (milliseconds)
|
||||
* - `us` (microseconds)
|
||||
* - `ns` (nanoseconds)
|
||||
* - `ps` (picoseconds)
|
||||
* - `fs` (femtoseconds)
|
||||
*
|
||||
* There can be no white space between the numerical portion
|
||||
* and the units. Any otherwise malformed string causes a fatal error to
|
||||
@@ -181,6 +227,17 @@ public:
|
||||
return Time (std::numeric_limits<int64_t>::max ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Time ()
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Clear (this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \return true if the time is zero, false otherwise.
|
||||
*/
|
||||
@@ -216,7 +273,9 @@ public:
|
||||
{
|
||||
return m_data > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return -1,0,+1 if `this < o`, `this == o`, or `this > o`
|
||||
*/
|
||||
inline int Compare (const Time &o) const
|
||||
{
|
||||
return (m_data < o.m_data) ? -1 : (m_data == o.m_data) ? 0 : 1;
|
||||
@@ -272,8 +331,7 @@ public:
|
||||
return ToInteger (Time::FS);
|
||||
}
|
||||
/**
|
||||
* \returns an approximation of the time stored in this
|
||||
* instance in the units specified in m_tsPrecision.
|
||||
* \returns the raw time value, in the current units
|
||||
*/
|
||||
inline int64_t GetTimeStep (void) const
|
||||
{
|
||||
@@ -403,13 +461,21 @@ public:
|
||||
}
|
||||
explicit inline Time (const int64x64_t &value)
|
||||
: m_data (value.GetHigh ())
|
||||
{}
|
||||
{
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
inline static Time From (const int64x64_t &value)
|
||||
{
|
||||
return Time (value);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* How to convert between other units and the current unit
|
||||
*/
|
||||
struct Information
|
||||
{
|
||||
bool toMul;
|
||||
@@ -418,15 +484,18 @@ private:
|
||||
int64x64_t timeTo;
|
||||
int64x64_t timeFrom;
|
||||
};
|
||||
/**
|
||||
* Current time unit, and conversion info.
|
||||
*/
|
||||
struct Resolution
|
||||
{
|
||||
struct Information info[LAST];
|
||||
enum Time::Unit unit;
|
||||
struct Information info[LAST]; //!< Conversion info from current unit
|
||||
enum Time::Unit unit; //!< Current time unit
|
||||
};
|
||||
|
||||
static inline struct Resolution *PeekResolution (void)
|
||||
{
|
||||
static struct Time::Resolution resolution = GetNsResolution ();
|
||||
static struct Time::Resolution resolution = SetDefaultNsResolution ();
|
||||
return &resolution;
|
||||
}
|
||||
static inline struct Information *PeekInformation (enum Unit timeUnit)
|
||||
@@ -434,8 +503,75 @@ private:
|
||||
return &(PeekResolution ()->info[timeUnit]);
|
||||
}
|
||||
|
||||
static struct Resolution GetNsResolution (void);
|
||||
static void SetResolution (enum Unit unit, struct Resolution *resolution);
|
||||
static struct Resolution SetDefaultNsResolution (void);
|
||||
static void SetResolution (enum Unit unit, struct Resolution *resolution,
|
||||
const bool convert = true);
|
||||
|
||||
/**
|
||||
* Record all instances of Time, so we can rescale them when
|
||||
* the resolution changes.
|
||||
*
|
||||
* \intern
|
||||
*
|
||||
* We use a std::set so we can remove the record easily when
|
||||
* ~Time() is called.
|
||||
*
|
||||
* We don't use Ptr<Time>, because we would have to bloat every Time
|
||||
* instance with SimpleRefCount<Time>.
|
||||
*
|
||||
* Seems like this should be std::set< Time * const >, but
|
||||
* [Stack Overflow](http://stackoverflow.com/questions/5526019/compile-errors-stdset-with-const-members)
|
||||
* says otherwise, quoting the standard:
|
||||
*
|
||||
* > §23.1/3 states that std::set key types must be assignable
|
||||
* > and copy constructable; clearly a const type will not be assignable.
|
||||
*/
|
||||
typedef std::set< Time * > MarkedTimes;
|
||||
/**
|
||||
* Record of outstanding Time objects which will need conversion
|
||||
* when the resolution is set.
|
||||
*
|
||||
* \intern
|
||||
*
|
||||
* Use a classic static variable so we can check in Time ctors
|
||||
* without a function call.
|
||||
*
|
||||
* We'd really like to initialize this here, but we don't want to require
|
||||
* C++0x, so we init in time.cc. To ensure that happens before first use,
|
||||
* we add a call to StaticInit (below) to every compilation unit which
|
||||
* includes nstime.h.
|
||||
*/
|
||||
static MarkedTimes * g_markingTimes;
|
||||
public:
|
||||
/**
|
||||
* Function to force static initialization of Time
|
||||
*/
|
||||
static bool StaticInit ();
|
||||
private:
|
||||
|
||||
/* Friend the Simulator class so it can call the private function
|
||||
ClearMarkedTimes ()
|
||||
*/
|
||||
friend class Simulator;
|
||||
/**
|
||||
* Remove all MarkedTimes.
|
||||
*
|
||||
* \intern
|
||||
* Has to be visible to the Simulator class, hence the friending.
|
||||
*/
|
||||
static void ClearMarkedTimes ();
|
||||
/**
|
||||
* Record a Time instance with the MarkedTimes
|
||||
*/
|
||||
static void Mark (Time * const time);
|
||||
/**
|
||||
* Remove a Time instance from the MarkedTimes, called by ~Time()
|
||||
*/
|
||||
static void Clear (Time * const time);
|
||||
/**
|
||||
* Convert existing Times to the new unit.
|
||||
*/
|
||||
static void ConvertTimes (const enum Unit unit);
|
||||
|
||||
friend bool operator == (const Time &lhs, const Time &rhs);
|
||||
friend bool operator != (const Time &lhs, const Time &rhs);
|
||||
@@ -451,8 +587,14 @@ private:
|
||||
friend Time Max (const Time &ta, const Time &tb);
|
||||
friend Time Min (const Time &ta, const Time &tb);
|
||||
|
||||
int64_t m_data;
|
||||
};
|
||||
|
||||
int64_t m_data; //!< Virtual time value, in the current unit.
|
||||
|
||||
}; // class Time
|
||||
|
||||
|
||||
// Force static initialization of Time
|
||||
static bool NS_UNUSED_GLOBAL (g_TimeStaticInit) = Time::StaticInit ();
|
||||
|
||||
inline bool
|
||||
operator == (const Time &lhs, const Time &rhs)
|
||||
@@ -506,6 +648,7 @@ inline Time &operator -= (Time &lhs, const Time &rhs)
|
||||
/**
|
||||
* \anchor ns3-Time-Abs
|
||||
* \relates ns3::TimeUnit
|
||||
* Absolute value function for Time
|
||||
* \param time the input value
|
||||
* \returns the absolute value of the input value.
|
||||
*/
|
||||
@@ -525,8 +668,6 @@ inline Time Max (const Time &ta, const Time &tb)
|
||||
return Time ((ta.m_data < tb.m_data) ? tb : ta);
|
||||
}
|
||||
/**
|
||||
* \anchor ns3-Time-Min
|
||||
* \relates ns3::TimeUnit
|
||||
* \param ta the first value
|
||||
* \param tb the seconds value
|
||||
* \returns the min of the two input values.
|
||||
@@ -537,7 +678,19 @@ inline Time Min (const Time &ta, const Time &tb)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Time output streamer.
|
||||
*
|
||||
* Generates output such as "3.96ns"
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
std::ostream& operator<< (std::ostream& os, const Time & time);
|
||||
/**
|
||||
* \brief Time input streamer
|
||||
*
|
||||
* Uses the Time::Time (const std::string &) constructor
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
std::istream& operator>> (std::istream& is, Time & time);
|
||||
|
||||
/**
|
||||
@@ -549,6 +702,7 @@ std::istream& operator>> (std::istream& is, Time & time);
|
||||
* Simulator::Schedule (Seconds (5.0), ...);
|
||||
* \endcode
|
||||
* \param seconds seconds value
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time Seconds (double seconds)
|
||||
{
|
||||
@@ -564,6 +718,7 @@ inline Time Seconds (double seconds)
|
||||
* Simulator::Schedule (MilliSeconds (5), ...);
|
||||
* \endcode
|
||||
* \param ms milliseconds value
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time MilliSeconds (uint64_t ms)
|
||||
{
|
||||
@@ -578,6 +733,7 @@ inline Time MilliSeconds (uint64_t ms)
|
||||
* Simulator::Schedule (MicroSeconds (5), ...);
|
||||
* \endcode
|
||||
* \param us microseconds value
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time MicroSeconds (uint64_t us)
|
||||
{
|
||||
@@ -592,6 +748,7 @@ inline Time MicroSeconds (uint64_t us)
|
||||
* Simulator::Schedule (NanoSeconds (5), ...);
|
||||
* \endcode
|
||||
* \param ns nanoseconds value
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time NanoSeconds (uint64_t ns)
|
||||
{
|
||||
@@ -606,6 +763,7 @@ inline Time NanoSeconds (uint64_t ns)
|
||||
* Simulator::Schedule (PicoSeconds (5), ...);
|
||||
* \endcode
|
||||
* \param ps picoseconds value
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time PicoSeconds (uint64_t ps)
|
||||
{
|
||||
@@ -620,6 +778,7 @@ inline Time PicoSeconds (uint64_t ps)
|
||||
* Simulator::Schedule (FemtoSeconds (5), ...);
|
||||
* \endcode
|
||||
* \param fs femtoseconds value
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time FemtoSeconds (uint64_t fs)
|
||||
{
|
||||
@@ -627,26 +786,50 @@ inline Time FemtoSeconds (uint64_t fs)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \see Seconds(double)
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time Seconds (int64x64_t seconds)
|
||||
{
|
||||
return Time::From (seconds, Time::S);
|
||||
}
|
||||
/**
|
||||
* \see MilliSeconds(uint64_t)
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time MilliSeconds (int64x64_t ms)
|
||||
{
|
||||
return Time::From (ms, Time::MS);
|
||||
}
|
||||
/**
|
||||
* \see MicroSeconds(uint64_t)
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time MicroSeconds (int64x64_t us)
|
||||
{
|
||||
return Time::From (us, Time::US);
|
||||
}
|
||||
/**
|
||||
* \see NanoSeconds(uint64_t)
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time NanoSeconds (int64x64_t ns)
|
||||
{
|
||||
return Time::From (ns, Time::NS);
|
||||
}
|
||||
/**
|
||||
* \see PicoSeconds(uint64_t)
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time PicoSeconds (int64x64_t ps)
|
||||
{
|
||||
return Time::From (ps, Time::PS);
|
||||
}
|
||||
/**
|
||||
* \see FemtoSeconds(uint64_t)
|
||||
* \relates ns3::Time
|
||||
*/
|
||||
inline Time FemtoSeconds (int64x64_t fs)
|
||||
{
|
||||
return Time::From (fs, Time::FS);
|
||||
|
||||
@@ -157,6 +157,7 @@ void
|
||||
Simulator::Run (void)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
Time::ClearMarkedTimes ();
|
||||
GetImpl ()->Run ();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,41 @@
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Time");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Time");
|
||||
// The set of marked times
|
||||
// static
|
||||
Time::MarkedTimes * Time::g_markingTimes = 0;
|
||||
|
||||
// Function called to force static initialization
|
||||
// static
|
||||
bool Time::StaticInit ()
|
||||
{
|
||||
static bool firstTime = true;
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
if (! g_markingTimes)
|
||||
{
|
||||
g_markingTimes = new Time::MarkedTimes;
|
||||
}
|
||||
|
||||
// Schedule the cleanup.
|
||||
// We'd really like:
|
||||
// NS_LOG_LOGIC ("scheduling ClearMarkedTimes()");
|
||||
// Simulator::Schedule ( Seconds (0), & ClearMarkedTimes);
|
||||
// [or even better: Simulator::AtStart ( & ClearMarkedTimes ); ]
|
||||
// But this triggers a static initialization order error,
|
||||
// since the Simulator static initialization may not have occurred.
|
||||
// Instead, we call ClearMarkedTimes directly from Simulator::Run ()
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
return firstTime;
|
||||
}
|
||||
|
||||
|
||||
Time::Time (const std::string& s)
|
||||
{
|
||||
@@ -48,36 +80,34 @@ Time::Time (const std::string& s)
|
||||
if (trailer == std::string ("s"))
|
||||
{
|
||||
*this = Time::FromDouble (r, Time::S);
|
||||
return;
|
||||
}
|
||||
if (trailer == std::string ("ms"))
|
||||
else if (trailer == std::string ("ms"))
|
||||
{
|
||||
*this = Time::FromDouble (r, Time::MS);
|
||||
return;
|
||||
}
|
||||
if (trailer == std::string ("us"))
|
||||
else if (trailer == std::string ("us"))
|
||||
{
|
||||
*this = Time::FromDouble (r, Time::US);
|
||||
return;
|
||||
}
|
||||
if (trailer == std::string ("ns"))
|
||||
else if (trailer == std::string ("ns"))
|
||||
{
|
||||
*this = Time::FromDouble (r, Time::NS);
|
||||
return;
|
||||
}
|
||||
if (trailer == std::string ("ps"))
|
||||
else if (trailer == std::string ("ps"))
|
||||
{
|
||||
*this = Time::FromDouble (r, Time::PS);
|
||||
return;
|
||||
}
|
||||
if (trailer == std::string ("fs"))
|
||||
else if (trailer == std::string ("fs"))
|
||||
{
|
||||
*this = Time::FromDouble (r, Time::FS);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("Can't Parse Time " << s);
|
||||
}
|
||||
// else
|
||||
}
|
||||
else
|
||||
{
|
||||
// they didn't provide units, assume seconds
|
||||
std::istringstream iss;
|
||||
iss.str (s);
|
||||
@@ -86,24 +116,42 @@ Time::Time (const std::string& s)
|
||||
*this = Time::FromDouble (v, Time::S);
|
||||
}
|
||||
|
||||
if (g_markingTimes)
|
||||
{
|
||||
Mark (this);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
struct Time::Resolution
|
||||
Time::GetNsResolution (void)
|
||||
Time::SetDefaultNsResolution (void)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
struct Resolution resolution;
|
||||
SetResolution (Time::NS, &resolution);
|
||||
SetResolution (Time::NS, &resolution, false);
|
||||
return resolution;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
Time::SetResolution (enum Unit resolution)
|
||||
{
|
||||
NS_LOG_FUNCTION (resolution);
|
||||
SetResolution (resolution, PeekResolution ());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void
|
||||
Time::SetResolution (enum Unit unit, struct Resolution *resolution)
|
||||
Time::SetResolution (enum Unit unit, struct Resolution *resolution,
|
||||
const bool convert /* = true */)
|
||||
{
|
||||
NS_LOG_FUNCTION (unit << resolution);
|
||||
NS_LOG_FUNCTION (resolution);
|
||||
if (convert)
|
||||
{ // We have to convert old values
|
||||
ConvertTimes (unit);
|
||||
}
|
||||
|
||||
int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
|
||||
for (int i = 0; i < Time::LAST; i++)
|
||||
{
|
||||
@@ -136,6 +184,97 @@ Time::SetResolution (enum Unit unit, struct Resolution *resolution)
|
||||
}
|
||||
resolution->unit = unit;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void
|
||||
Time::ClearMarkedTimes ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
if (g_markingTimes)
|
||||
{
|
||||
NS_LOG_LOGIC ("clearing MarkedTimes");
|
||||
delete g_markingTimes;
|
||||
g_markingTimes = 0;
|
||||
}
|
||||
} // Time::ClearMarkedTimes
|
||||
|
||||
|
||||
// static
|
||||
void
|
||||
Time::Mark (Time * const time)
|
||||
{
|
||||
NS_LOG_FUNCTION (time);
|
||||
NS_ASSERT (time != 0);
|
||||
|
||||
if (g_markingTimes)
|
||||
{
|
||||
std::pair< MarkedTimes::iterator, bool> ret;
|
||||
|
||||
ret = g_markingTimes->insert ( time);
|
||||
NS_LOG_LOGIC ("\t[" << g_markingTimes->size () << "] recording " << time);
|
||||
|
||||
if (ret.second == false)
|
||||
{
|
||||
NS_LOG_WARN ("already recorded " << time << "!");
|
||||
}
|
||||
}
|
||||
} // Time::Mark ()
|
||||
|
||||
|
||||
// static
|
||||
void
|
||||
Time::Clear (Time * const time)
|
||||
{
|
||||
NS_LOG_FUNCTION (time);
|
||||
NS_ASSERT (time != 0);
|
||||
|
||||
if (g_markingTimes)
|
||||
{
|
||||
NS_ASSERT_MSG (g_markingTimes->count (time) == 1,
|
||||
"Time object " << time <<
|
||||
" registered " << g_markingTimes->count (time) <<
|
||||
" times (should be 1)." );
|
||||
|
||||
MarkedTimes::size_type num = g_markingTimes->erase (time);
|
||||
if (num != 1)
|
||||
{
|
||||
NS_LOG_WARN ("unexpected result erasing " << time << "!");
|
||||
NS_LOG_WARN ("got " << num << ", expected 1");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("\t[" << g_markingTimes->size () << "] removing " << time);
|
||||
}
|
||||
}
|
||||
} // Time::Clear ()
|
||||
|
||||
|
||||
// static
|
||||
void
|
||||
Time::ConvertTimes (const enum Unit unit)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
|
||||
NS_ASSERT_MSG (g_markingTimes != 0,
|
||||
"No MarkedTimes registry. "
|
||||
"Time::SetResolution () called more than once?");
|
||||
|
||||
for ( MarkedTimes::iterator it = g_markingTimes->begin();
|
||||
it != g_markingTimes->end();
|
||||
it++ )
|
||||
{
|
||||
Time * const tp = *it;
|
||||
tp->m_data = tp->ToInteger (unit);
|
||||
}
|
||||
|
||||
NS_LOG_LOGIC ("logged " << g_markingTimes->size () << " Time objects.");
|
||||
|
||||
ClearMarkedTimes ();
|
||||
} // Time::ConvertTimes ()
|
||||
|
||||
|
||||
// static
|
||||
enum Time::Unit
|
||||
Time::GetResolution (void)
|
||||
{
|
||||
|
||||
@@ -5,4 +5,14 @@
|
||||
# define NS_UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
#ifndef NS_UNUSED_GLOBAL
|
||||
#if defined(__GNUC__)
|
||||
# define NS_UNUSED_GLOBAL(x) x __attribute__((unused))
|
||||
#elif defined(__LCLINT__)
|
||||
# define NS_UNUSED_GLOBAL(x) /*@unused@*/ x
|
||||
#else
|
||||
# define NS_UNUSED_GLOBAL(x) x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* UNUSED_H */
|
||||
|
||||
@@ -27,31 +27,26 @@ using namespace ns3;
|
||||
class TimeSimpleTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
TimeSimpleTestCase (enum Time::Unit resolution);
|
||||
TimeSimpleTestCase ();
|
||||
private:
|
||||
virtual void DoSetup (void);
|
||||
virtual void DoRun (void);
|
||||
virtual void DoTeardown (void);
|
||||
enum Time::Unit m_originalResolution;
|
||||
enum Time::Unit m_resolution;
|
||||
};
|
||||
|
||||
TimeSimpleTestCase::TimeSimpleTestCase (enum Time::Unit resolution)
|
||||
: TestCase ("Sanity check of common time operations"),
|
||||
m_resolution (resolution)
|
||||
TimeSimpleTestCase::TimeSimpleTestCase ()
|
||||
: TestCase ("Sanity check of common time operations")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TimeSimpleTestCase::DoSetup (void)
|
||||
{
|
||||
m_originalResolution = Time::GetResolution ();
|
||||
}
|
||||
|
||||
void
|
||||
TimeSimpleTestCase::DoRun (void)
|
||||
{
|
||||
Time::SetResolution (m_resolution);
|
||||
NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (1.0).GetSeconds (), 1.0, TimeStep (1).GetSeconds (),
|
||||
"is 1 really 1 ?");
|
||||
NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (10.0).GetSeconds (), 10.0, TimeStep (1).GetSeconds (),
|
||||
@@ -70,12 +65,18 @@ TimeSimpleTestCase::DoRun (void)
|
||||
NS_TEST_ASSERT_MSG_EQ (FemtoSeconds (1).GetFemtoSeconds (), 1,
|
||||
"is 1fs really 1fs ?");
|
||||
#endif
|
||||
|
||||
Time ten = NanoSeconds (10);
|
||||
int64_t tenValue = ten.GetInteger ();
|
||||
Time::SetResolution (Time::PS);
|
||||
int64_t tenKValue = ten.GetInteger ();
|
||||
NS_TEST_ASSERT_MSG_EQ (tenValue * 1000, tenKValue,
|
||||
"change resolution to PS");
|
||||
}
|
||||
|
||||
void
|
||||
TimeSimpleTestCase::DoTeardown (void)
|
||||
{
|
||||
Time::SetResolution (m_originalResolution);
|
||||
}
|
||||
|
||||
class TimesWithSignsTestCase : public TestCase
|
||||
@@ -139,7 +140,7 @@ public:
|
||||
TimeTestSuite ()
|
||||
: TestSuite ("time", UNIT)
|
||||
{
|
||||
AddTestCase (new TimeSimpleTestCase (Time::US), TestCase::QUICK);
|
||||
AddTestCase (new TimeSimpleTestCase (), TestCase::QUICK);
|
||||
AddTestCase (new TimesWithSignsTestCase (), TestCase::QUICK);
|
||||
}
|
||||
} g_timeTestSuite;
|
||||
|
||||
Reference in New Issue
Block a user