A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
time.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  * Copyright (c) 2007 Emmanuelle Laprise
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * TimeStep support by Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
21  */
22 #include "nstime.h"
23 #include "abort.h"
24 #include "global-value.h"
25 #include "enum.h"
26 #include "string.h"
27 #include "object.h"
28 #include "config.h"
29 #include "system-mutex.h"
30 #include "log.h"
31 #include <cmath>
32 #include <iomanip> // showpos
33 #include <sstream>
34 
36 
37 namespace ns3 {
38 
39 // The set of marked times
40 // static
42 
48 SystemMutex &
50 {
51  static SystemMutex g_markingMutex;
52  return g_markingMutex;
53 }
54 
55 
56 // Function called to force static initialization
57 // static
59 {
60  static bool firstTime = true;
61 
62  CriticalSection critical (GetMarkingMutex ());
63 
64  if (firstTime)
65  {
66  if (! g_markingTimes)
67  {
68  static MarkedTimes markingTimes;
69  g_markingTimes = & markingTimes;
70  }
71  else
72  {
73  NS_LOG_ERROR ("firstTime but g_markingTimes != 0");
74  }
75 
76  // Schedule the cleanup.
77  // We'd really like:
78  // NS_LOG_LOGIC ("scheduling ClearMarkedTimes()");
79  // Simulator::Schedule ( Seconds (0), & ClearMarkedTimes);
80  // [or even better: Simulator::AtStart ( & ClearMarkedTimes ); ]
81  // But this triggers a static initialization order error,
82  // since the Simulator static initialization may not have occurred.
83  // Instead, we call ClearMarkedTimes directly from Simulator::Run ()
84  firstTime = false;
85  }
86 
87  return firstTime;
88 }
89 
90 
91 Time::Time (const std::string& s)
92 {
93  NS_LOG_FUNCTION (this << &s);
94  std::string::size_type n = s.find_first_not_of ("+-0123456789.");
95  if (n != std::string::npos)
96  { // Found non-numeric
97  std::istringstream iss;
98  iss.str (s.substr (0, n));
99  double r;
100  iss >> r;
101  std::string trailer = s.substr (n, std::string::npos);
102  if (trailer == std::string ("s"))
103  {
104  *this = Time::FromDouble (r, Time::S);
105  }
106  else if (trailer == std::string ("ms"))
107  {
108  *this = Time::FromDouble (r, Time::MS);
109  }
110  else if (trailer == std::string ("us"))
111  {
112  *this = Time::FromDouble (r, Time::US);
113  }
114  else if (trailer == std::string ("ns"))
115  {
116  *this = Time::FromDouble (r, Time::NS);
117  }
118  else if (trailer == std::string ("ps"))
119  {
120  *this = Time::FromDouble (r, Time::PS);
121  }
122  else if (trailer == std::string ("fs"))
123  {
124  *this = Time::FromDouble (r, Time::FS);
125  }
126  else
127  {
128  NS_ABORT_MSG ("Can't Parse Time " << s);
129  }
130  }
131  else
132  {
133  // they didn't provide units, assume seconds
134  std::istringstream iss;
135  iss.str (s);
136  double v;
137  iss >> v;
138  *this = Time::FromDouble (v, Time::S);
139  }
140 
141  if (g_markingTimes)
142  {
143  Mark (this);
144  }
145 }
146 
147 // static
148 struct Time::Resolution
149 Time::SetDefaultNsResolution (void)
150 {
152  struct Resolution resolution;
153  SetResolution (Time::NS, &resolution, false);
154  return resolution;
155 }
156 
157 // static
158 void
159 Time::SetResolution (enum Unit resolution)
160 {
161  NS_LOG_FUNCTION (resolution);
162  SetResolution (resolution, PeekResolution ());
163 }
164 
165 
166 // static
167 void
168 Time::SetResolution (enum Unit unit, struct Resolution *resolution,
169  const bool convert /* = true */)
170 {
171  NS_LOG_FUNCTION (resolution);
172  if (convert)
173  {
174  // We have to convert existing Times with the old
175  // conversion values, so do it first
176  ConvertTimes (unit);
177  }
178 
179  int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
180  for (int i = 0; i < Time::LAST; i++)
181  {
182  int shift = power[i] - power[(int)unit];
183  int64_t factor = (int64_t) std::pow (10, std::fabs (shift));
184  struct Information *info = &resolution->info[i];
185  info->factor = factor;
186  if (shift == 0)
187  {
188  info->timeFrom = int64x64_t (1);
189  info->timeTo = int64x64_t (1);
190  info->toMul = true;
191  info->fromMul = true;
192  }
193  else if (shift > 0)
194  {
195  info->timeFrom = int64x64_t (factor);
196  info->timeTo = int64x64_t::Invert (factor);
197  info->toMul = false;
198  info->fromMul = true;
199  }
200  else
201  {
202  NS_ASSERT (shift < 0);
203  info->timeFrom = int64x64_t::Invert (factor);
204  info->timeTo = int64x64_t (factor);
205  info->toMul = true;
206  info->fromMul = false;
207  }
208  }
209  resolution->unit = unit;
210 }
211 
212 
213 // static
214 void
216 {
232  CriticalSection critical (GetMarkingMutex ());
233 
235  if (g_markingTimes)
236  {
237  NS_LOG_LOGIC ("clearing MarkedTimes");
238  g_markingTimes->erase (g_markingTimes->begin(), g_markingTimes->end ());
239  g_markingTimes = 0;
240  }
241 } // Time::ClearMarkedTimes
242 
243 
244 // static
245 void
246 Time::Mark (Time * const time)
247 {
248  CriticalSection critical (GetMarkingMutex ());
249 
250  NS_LOG_FUNCTION (time);
251  NS_ASSERT (time != 0);
252 
253  // Repeat the g_markingTimes test here inside the CriticalSection,
254  // since earlier test was outside and might be stale.
255  if (g_markingTimes)
256  {
257  std::pair< MarkedTimes::iterator, bool> ret;
258 
259  ret = g_markingTimes->insert ( time);
260  NS_LOG_LOGIC ("\t[" << g_markingTimes->size () << "] recording " << time);
261 
262  if (ret.second == false)
263  {
264  NS_LOG_WARN ("already recorded " << time << "!");
265  }
266  }
267 } // Time::Mark ()
268 
269 
270 // static
271 void
272 Time::Clear (Time * const time)
273 {
274  CriticalSection critical (GetMarkingMutex ());
275 
276  NS_LOG_FUNCTION (time);
277  NS_ASSERT (time != 0);
278 
279  if (g_markingTimes)
280  {
281  NS_ASSERT_MSG (g_markingTimes->count (time) == 1,
282  "Time object " << time <<
283  " registered " << g_markingTimes->count (time) <<
284  " times (should be 1)." );
285 
286  MarkedTimes::size_type num = g_markingTimes->erase (time);
287  if (num != 1)
288  {
289  NS_LOG_WARN ("unexpected result erasing " << time << "!");
290  NS_LOG_WARN ("got " << num << ", expected 1");
291  }
292  else
293  {
294  NS_LOG_LOGIC ("\t[" << g_markingTimes->size () << "] removing " << time);
295  }
296  }
297 } // Time::Clear ()
298 
299 
300 // static
301 void
302 Time::ConvertTimes (const enum Unit unit)
303 {
304  CriticalSection critical (GetMarkingMutex ());
305 
307 
309  "No MarkedTimes registry. "
310  "Time::SetResolution () called more than once?");
311 
312  for ( MarkedTimes::iterator it = g_markingTimes->begin();
313  it != g_markingTimes->end();
314  it++ )
315  {
316  Time * const tp = *it;
317  if ( ! ( (tp->m_data == std::numeric_limits<int64_t>::min ())
318  || (tp->m_data == std::numeric_limits<int64_t>::max ())
319  )
320  )
321  {
322  tp->m_data = tp->ToInteger (unit);
323  }
324  }
325 
326  NS_LOG_LOGIC ("logged " << g_markingTimes->size () << " Time objects.");
327 
328  // Body of ClearMarkedTimes
329  // Assert above already guarantees g_markingTimes != 0
330  NS_LOG_LOGIC ("clearing MarkedTimes");
331  g_markingTimes->erase (g_markingTimes->begin(), g_markingTimes->end ());
332  g_markingTimes = 0;
333 
334 } // Time::ConvertTimes ()
335 
336 
337 // static
338 enum Time::Unit
340 {
341  // No function log b/c it interferes with operator<<
342  return PeekResolution ()->unit;
343 }
344 
345 
346 std::ostream&
347 operator<< (std::ostream& os, const Time & time)
348 {
349  std::string unit;
351  switch (res)
352  {
353  case Time::S:
354  unit = "s";
355  break;
356  case Time::MS:
357  unit = "ms";
358  break;
359  case Time::US:
360  unit = "us";
361  break;
362  case Time::NS:
363  unit = "ns";
364  break;
365  case Time::PS:
366  unit = "ps";
367  break;
368  case Time::FS:
369  unit = "fs";
370  break;
371  case Time::LAST:
372  NS_ABORT_MSG ("can't be reached");
373  unit = "unreachable";
374  break;
375  }
376  int64_t v = time.ToInteger (res);
377 
378  std::ios_base::fmtflags ff = os.flags ();
379  { // See bug 1737: gcc libstc++ 4.2 bug
380  if (v == 0)
381  {
382  os << '+';
383  }
384  else
385  {
386  os << std::showpos;
387  }
388  }
389  os << v << ".0" << unit;
390  os.flags (ff); // Restore stream flags
391  return os;
392 }
393 std::istream& operator>> (std::istream& is, Time & time)
394 {
395  std::string value;
396  is >> value;
397  time = Time (value);
398  return is;
399 }
400 
402 
403 Ptr<const AttributeChecker>
404 MakeTimeChecker (const Time min, const Time max)
405 {
406  NS_LOG_FUNCTION (min << max);
407 
408  struct Checker : public AttributeChecker
409  {
410  Checker (const Time minValue, const Time maxValue)
411  : m_minValue (minValue),
412  m_maxValue (maxValue) {}
413  virtual bool Check (const AttributeValue &value) const {
414  NS_LOG_FUNCTION (&value);
415  const TimeValue *v = dynamic_cast<const TimeValue *> (&value);
416  if (v == 0)
417  {
418  return false;
419  }
420  return v->Get () >= m_minValue && v->Get () <= m_maxValue;
421  }
422  virtual std::string GetValueTypeName (void) const {
424  return "ns3::TimeValue";
425  }
426  virtual bool HasUnderlyingTypeInformation (void) const {
428  return true;
429  }
430  virtual std::string GetUnderlyingTypeInformation (void) const {
432  std::ostringstream oss;
433  oss << "Time" << " " << m_minValue << ":" << m_maxValue;
434  return oss.str ();
435  }
436  virtual Ptr<AttributeValue> Create (void) const {
438  return ns3::Create<TimeValue> ();
439  }
440  virtual bool Copy (const AttributeValue &source, AttributeValue &destination) const {
441  NS_LOG_FUNCTION (&source << &destination);
442  const TimeValue *src = dynamic_cast<const TimeValue *> (&source);
443  TimeValue *dst = dynamic_cast<TimeValue *> (&destination);
444  if (src == 0 || dst == 0)
445  {
446  return false;
447  }
448  *dst = *src;
449  return true;
450  }
451  Time m_minValue;
452  Time m_maxValue;
453  } *checker = new Checker (min, max);
454  return Ptr<const AttributeChecker> (checker, false);
455 }
456 
457 
458 } // namespace ns3
459 
static struct Resolution * PeekResolution(void)
Definition: nstime.h:474
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:49
nanosecond
Definition: nstime.h:92
Time Get(void) const
Represent the type of an attribute.
Definition: attribute.h:154
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
microsecond
Definition: nstime.h:91
int64x64_t timeFrom
Multiplier to convert from this unit.
Definition: nstime.h:463
Hold a value for an Attribute.
Definition: attribute.h:56
int64_t ToInteger(enum Unit timeUnit) const
Definition: nstime.h:370
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
static Time FromDouble(double value, enum Unit timeUnit)
Definition: nstime.h:391
struct Information info[LAST]
Conversion info from current unit.
Definition: nstime.h:470
NS_LOG_COMPONENT_DEFINE("Time")
picosecond
Definition: nstime.h:93
static enum Unit GetResolution(void)
Definition: time.cc:339
hold objects of type ns3::Time
Definition: nstime.h:828
Ptr< T > Create(void)
Definition: ptr.h:231
static bool StaticInit()
Definition: time.cc:58
A class which provides a simple way to implement a Critical Section.
Definition: system-mutex.h:109
bool fromMul
Multiple when converting From, otherwise divide.
Definition: nstime.h:460
Ptr< SampleEmitter > s
static void ConvertTimes(const enum Unit unit)
Definition: time.cc:302
int64_t factor
Ratio of this unit / current unit.
Definition: nstime.h:461
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:43
SystemMutex & GetMarkingMutex()
Definition: time.cc:49
Time()
Definition: nstime.h:103
A class which provides a relatively platform-independent Mutual Exclusion thread synchronization prim...
Definition: system-mutex.h:50
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
ATTRIBUTE_VALUE_IMPLEMENT(RandomVariable)
static void Mark(Time *const time)
Definition: time.cc:246
#define NS_ABORT_MSG(msg)
Abnormal program termination.
Definition: abort.h:43
#define NS_LOG_WARN(msg)
Definition: log.h:246
enum Time::Unit unit
Current time unit.
Definition: nstime.h:471
static void SetResolution(enum Unit resolution)
Definition: time.cc:159
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range. Both limits are inclusive.
Definition: time.cc:404
static void Clear(Time *const time)
Definition: time.cc:272
#define NS_LOG_ERROR(msg)
Definition: log.h:237
second
Definition: nstime.h:89
std::set< Time * > MarkedTimes
Definition: nstime.h:507
static MarkedTimes * g_markingTimes
Definition: nstime.h:522
static void ClearMarkedTimes()
Definition: time.cc:215
femtosecond
Definition: nstime.h:94
millisecond
Definition: nstime.h:90
Ptr< T > Copy(Ptr< T > object)
Definition: ptr.h:387
int64x64_t timeTo
Multiplier to convert to this unit.
Definition: nstime.h:462
int64_t m_data
Virtual time value, in the current unit.
Definition: nstime.h:569
bool toMul
Multiply when converting To, otherwise divide.
Definition: nstime.h:459