diff --git a/doc/tutorial/source/conceptual-overview.rst b/doc/tutorial/source/conceptual-overview.rst index b75feced9..d3027d413 100644 --- a/doc/tutorial/source/conceptual-overview.rst +++ b/doc/tutorial/source/conceptual-overview.rst @@ -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: diff --git a/examples/tutorial/first.cc b/examples/tutorial/first.cc index f01f88b87..747d5bc7e 100644 --- a/examples/tutorial/first.cc +++ b/examples/tutorial/first.cc @@ -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); diff --git a/src/core/model/nstime.h b/src/core/model/nstime.h index 7bb07b472..19503170a 100644 --- a/src/core/model/nstime.h +++ b/src/core/model/nstime.h @@ -24,10 +24,12 @@ #include "attribute.h" #include "attribute-helper.h" #include "int64x64.h" +#include "unused.h" #include #include #include #include +#include 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::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