--- a/.hgtags Sat May 19 13:41:50 2007 +0200
+++ b/.hgtags Fri May 25 09:44:18 2007 +0200
@@ -1,1 +1,2 @@
56928998e05c9c11f5f3aefe79be8d2843e0db88 release ns-3.0.1
+7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2
--- a/INSTALL Sat May 19 13:41:50 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-ns-3.0.1 snapshot release, March 2007
-
-1. Tested platforms:
-
-- Windows XP 32-bit Cygwin
-
-- Linux Fedora Core 5 x86
-
-- OS X 10.4.7 or later with XCode 2.4 or later
-
-2. Prerequisites:
-
-- The SCons build system (http://www.scons.org) version 0.96.1 or later
-
-- gcc (version 3.4 or later)
-
-3. Installing into your current directory:
-
-tar xvfz ns-3.0.1.tar.gz
-cd ns-3.0.1
-scons
-cd build-dir/dbg-shared/bin/
-./simple-p2p
-
-The above steps will run a simple program whose source is found in
-ns-3.0.1/examples/simple-p2p.cc
-Some minimal trace output is found in simple-p2p.tr.
-
-Note: OS X users may need to set the following env. variable from
-the bin/ directory above:
-setenv DYLD_LIBRARY_PATH `pwd`/../lib
-
-4. For more information, read
-ns-3.0.1-documentation.pdf
-
--- a/README Sat May 19 13:41:50 2007 +0200
+++ b/README Fri May 25 09:44:18 2007 +0200
@@ -1,9 +1,9 @@
- The Network Simulator Version 3
- -------------------------------
+ The Network Simulator, Version 3
+ --------------------------------
-Table of Content:
------------------
+Table of Contents:
+------------------
1) An Open Source project
2) An overview of the ns-3 project
@@ -16,7 +16,7 @@
1) An Open Source project
-------------------------
-ns-3 is an Open Source project and we intend to make this
+ns-3 is an Open Source project. We intend to make this
project a successful collaborative project: we hope that
the missing pieces of the models we have not yet implemented
will be contributed by the community in an open collaboration
@@ -25,11 +25,11 @@
Contributing to the ns-3 project is still a very informal
process because that process depends heavily on the personality
of the people involved, the amount of time they can invest
-and the type of model they want to work on.
+and the type of model they want to work on.
Despite this lack of a formal process, there are a number of
steps which naturally stem from the open-source roots of the
-project. These steps are described in doc/contributing.txt
+project. These steps are described in doc/contributing.txt
2) An overview of the ns-3 project
----------------------------------
@@ -42,8 +42,9 @@
- point-to-point physical-layer links
- OnOff traffic generator
-However, the framework is there to make adding new models as
-simple as possible:
+Our focus to date has been on getting an overall software
+framework in place. The framework is there to make adding
+new models as simple as possible:
- an extensive tracing system can be used to connect
any number of arbitrary trace sources to any number
of trace sinks. This tracing system is decoupled
@@ -65,7 +66,7 @@
The code for the framework and the default models provided
by ns-3 is built as a set of libraries. User simulations
-are expected to be written as simple programs which make
+are expected to be written as simple programs that make
use of these ns-3 libraries.
To build the set of default libraries and the example
@@ -84,7 +85,8 @@
The current codebase is expected to build and run on the
following set of platforms:
- - linux x86 gcc 4.1, gcc 3.4.
+ - linux x86 gcc 4.2, 4.1, and, 3.4.
+ - linux x86_64 gcc 4.0
- MacOS X ppc and x86
The current codebase is expected to fail to build on
@@ -92,14 +94,14 @@
- gcc 3.3 and earlier
- optimized builds on linux x86 gcc 4.0
-Other platforms might or might not work: we welcome
+Other platforms may or may not work: we welcome
patches to improve the portability of the code to these
other platforms.
4) Running ns-3
---------------
-On Recent Linux systems, once you have built ns-3, it
+On recent Linux systems, once you have built ns-3, it
should be easy to run the sample programs with the
following command:
@@ -112,7 +114,7 @@
That program should generate a simple-p2p.tr text
trace file and a set of simple-p2p-xx-xx.pcap binary
-pcap trace files.
+pcap trace files, which can be read by tcpdump.
5) Getting access to the ns-3 documentation
-------------------------------------------
@@ -123,18 +125,17 @@
some ns-3 documentation.
All of that documentation should always be available from
-the ns-3 website: http:://www.nsnam.org/
+the ns-3 website: http:://www.nsnam.org/ but we
+include some of it in this release for ease of use.
-It includes:
+This documentation includes:
- an architecture document which describes a very
high-level view of ns-3: it tries to explain the
use-cases the ns-3 developers really focused on when
doing the initial design and then goes on to explain
the structure of the resulting framework.
- XXX introduce url link
-
- - a user manual: XXX
+ See the file doc/architecture.pdf
- a wiki for user-contributed tips: http://www.nsnam.org/wiki/
@@ -143,6 +144,17 @@
as introductory text:
http://www.nsnam.org/doxygen/index.html
+If you want to re-generate this documentation, you can
+easily do so:
+
+ - doc/architecture.pdf is generated from the architecture.tex
+ file in http://code.nsnam.org/docs
+
+ - the doxygen documentation is generated from the doc/doxygen.conf
+ configuration file. The command "scons doc" will generate it
+ as doc/html/index.html if you have installed the doxygen tools
+ (see http://www.doxygen.org)
+
6) Working with the development version of ns-3
-----------------------------------------------
@@ -156,4 +168,4 @@
If you have successfully installed mercurial, you can get
a copy of the development version with the following
command:
-"hg clone http://code.nsnam.org/ns-3-dev"
\ No newline at end of file
+"hg clone http://code.nsnam.org/ns-3-dev"
--- a/RELEASE_NOTES Sat May 19 13:41:50 2007 +0200
+++ b/RELEASE_NOTES Fri May 25 09:44:18 2007 +0200
@@ -1,9 +1,9 @@
ns-3 RELEASE NOTES
-This file contains ns-3 release notes (most recent releases first).
+This file contains ns-3 release notes (most recent releases first).
-Release 0.2 (2007/05/XX)
+Release 3.0.2 (2007/05/18)
========================
- Implement a new memory management infrastructure based
@@ -15,7 +15,7 @@
- Add support for a BSD-style socket API for user applications
-Release 0.1 (2007/03/31)
+Release 3.0.1 (2007/03/31)
========================
- First public release; not yet pre-alpha.
--- a/SConstruct Sat May 19 13:41:50 2007 +0200
+++ b/SConstruct Fri May 25 09:44:18 2007 +0200
@@ -2,19 +2,27 @@
import os.path
import build
+version_file = open ('VERSION', 'r')
+version = version_file.readline ()
+version_file.close ()
+version = version.strip ()
+
ns3 = build.Ns3()
ns3.build_dir = 'build-dir'
-ns3.version = '0.2'
+ns3.version = version
ns3.name = 'ns3'
-ns3.distname = 'ns-3'
+ns3.distname = 'ns'
ns3.doxygen_config = os.path.join('doc', 'doxygen.conf')
ns3.add_extra_dist(os.path.join('doc', 'main.txt'))
+ns3.add_extra_dist ('doc/architecture.pdf')
ns3.add_extra_dist ('doc/contributing.txt')
ns3.add_extra_dist ('doc/build.txt')
+ns3.add_extra_dist ('doc/codingstd.txt')
ns3.add_extra_dist ('doc/mercurial.txt')
ns3.add_extra_dist ('README')
ns3.add_extra_dist ('RELEASE_NOTES')
ns3.add_extra_dist ('AUTHORS')
+ns3.add_extra_dist ('VERSION')
#
@@ -23,7 +31,6 @@
core = build.Ns3Module('core', 'src/core')
ns3.add(core)
core.add_sources([
- 'reference-list-test.cc',
'callback-test.cc',
'debug.cc',
'assert.cc',
@@ -56,7 +63,6 @@
])
core.add_inst_headers([
'system-wall-clock-ms.h',
- 'reference-list.h',
'callback.h',
'ptr.h',
'object.h',
@@ -196,8 +202,6 @@
'array-trace-resolver.h',
'trace-root.h',
'terminal-trace-resolver.h',
- 'smartvector.h',
- 'smartset.h',
'data-rate.h',
])
--- a/VERSION Sat May 19 13:41:50 2007 +0200
+++ b/VERSION Fri May 25 09:44:18 2007 +0200
@@ -1,1 +1,1 @@
-3.0.1
+3.0.2
--- a/build.py Sat May 19 13:41:50 2007 +0200
+++ b/build.py Fri May 25 09:44:18 2007 +0200
@@ -504,7 +504,7 @@
# dist support
dist_env = env.Copy()
- if dist_env['PLATFORM'] == 'posix':
+ if dist_env['PLATFORM'] == 'posix' or dist_env['PLATFORM'] == 'darwin':
dist_list = []
for module in self.__modules:
for f in module.sources:
--- a/doc/build-waf.txt Sat May 19 13:41:50 2007 +0200
+++ b/doc/build-waf.txt Fri May 25 09:44:18 2007 +0200
@@ -1,12 +1,17 @@
-WAF is an alternative build system, similar to SCons. NS-3 now is
-able to build with WAF, in parallel to SCons.
+The main ns-3 build system is SCons. Read the file build.txt
+for SCons instructions.
-Note: the WAF build scripts are experimental at this stage.
+Waf is an alternative build system, similar to SCons. ns-3 now is
+able to build with Waf, in parallel to SCons.
+(http://www.freehackers.org/~tnagy/waf.html)
-=== Building with WAF ===
+Note: the Waf build scripts are experimental at this stage.
+Gustavo Carneiro (gjcarneiro@gmail.com) is the maintainer.
-To build NS-3 with waf type the commands:
+=== Building with Waf ===
+
+To build ns-3 with waf type the commands:
1. ./waf configure [options]
2. ./waf
@@ -30,7 +35,18 @@
Run code coverage analysis (assuming the project was configured
with --enable-gcov)
-=== Extending NS-3 ===
+ 4. ./waf --run "program [args]"
+ Run a ns3 program, given its target name, with the given
+ arguments. This takes care of automatically modifying the the
+ path for finding the ns3 dynamic libraries in the environment
+ before running the program. Note: the "program [args]" string is
+ parsed using POSIX shell rules.
+
+ 5. ./waf --shell
+ Starts a nested system shell with modified environment to run ns3 programs.
+
+
+=== Extending ns-3 ===
To add new modules:
1. Create the module directory under src (or src/devices, or whatever);
@@ -38,7 +54,7 @@
3. Add a 'wscript' describing it;
4. Add the module subdirectory name to the all_modules list in src/wscript.
-A module's wscript file is basically a regular WAF script. A NS-3
+A module's wscript file is basically a regular Waf script. A ns-3
module is created as a cpp/shlib object, like this:
def build(bld):
@@ -65,7 +81,7 @@
=== Note for developers ===
-The NS-3 code repository does not contain the waf script. Instead,
+The ns-3 code repository does not contain the waf script. Instead,
developers should check it out from a subversion repository:
svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf
@@ -77,8 +93,8 @@
Then it can be installed system-wide with 'sudo ./waf-light install'.
When preparing a distribution, the resulting 'waf' script, which is
self contained (no external files needed), can be easily included in
-the tarball so that users downloading NS-3 can easily build it without
-having WAF installed (although Python >= 2.3 is still needed).
+the tarball so that users downloading ns-3 can easily build it without
+having Waf installed (although Python >= 2.3 is still needed).
The command 'waf dist' can be used to create a distribution tarball.
It includes all files in the source directory, except some particular
--- a/doc/build.txt Sat May 19 13:41:50 2007 +0200
+++ b/doc/build.txt Fri May 25 09:44:18 2007 +0200
@@ -16,6 +16,10 @@
the right libraries. This saves you the pain of having to
setup environment variables to point to the right libraries.
+(Note: An alternative build system (Waf) is being
+evaluated in the development branch of ns-3-dev on our server
+only (i.e., not in the release tarballs)-- see doc/build-waf.txt)
+
1) Options
----------
--- a/doc/codingstd.tex Sat May 19 13:41:50 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,592 +0,0 @@
-\documentclass[11pt]{article}
-\usepackage{times}
-\setlength{\textwidth}{6.5in}
-\setlength{\textheight}{9in}
-\setlength{\oddsidemargin}{0.0in}
-\setlength{\evensidemargin}{0.0in}
-\setlength{\topmargin}{-0.5in}
-\def\nst{{\em ns--3}}
-\newcommand{\code}[1]{\texttt{#1}}
-
-\begin{document}
-\begin{center}
-{\Large Coding Standard for ns--3}\\
-August 22, 2005
-
-\end{center}
-\section{Introduction}
-
-The purpose of the \nst\ project is to build software which will last
-many years: making sure that the code is readable and stays so is
-one of the most important items required to achieve this goal. This
-document thus outlines guidelines we plan to enforce on each component
-integrated in \nst to ensure uniformity of the codebase which is
-a first step towards readable code.
-
-\section{Recommendations}
-
-The following recommendations are not strict rules and some of them
-are conflicting but the point here is to outline the fact that we
-value more common-sense than strict adherence to the coding style
-defined in this document.
-
-\subsection{naming}
-
-Types, methods, functions and variable names should be self-descriptive.
-Avoid using acronyms, expand them, do not hesitate to use long names,
-Avoid shortcuts such as \code{sz} for \code{size}. Long names sometimes get in the
-way of being able to read the code:
-\begin{verbatim}
-for (int loopCount = 0; loopCount < max; loopCount++)
- {
- // code
- }
-\end{verbatim}
-loopCount should be renamed to something shorter such as
-\code{i}, \code{j}, \code{k}, \code{l}, \code{m}, and \code{n}
-which are widely used names which identify loop counters:
-\begin{verbatim}
-for (int i = 0; i < max; i++)
- {
- // code
- }
-\end{verbatim}
-Similarly, \code{tmp} is a common way to denote temporary variables. On
-the other hand, \code{foo} is not an appropriate name: it says nothing
-about the purpose of the variable.
-
-If you use predicates (that is, functions, variables or methods
-which return a single boolean value), prefix the
-name with \code{is} or \code{has}.
-
-\subsection{Memory management}
-
-As much as possible, try to pass around objects
-by value and allocate them on the stack. If you need to allocate
-objects on the heap with new, make sure that the corresponding
-call to delete happens where the new took place. i.e., avoid
-passing around pointer ownership.
-Avoid the use of reference counting and, more generaly, strive to
-keep the memory-management model simple.
-
-\subsection{Templates}
-
-For now, templates are defined only in the simulator
-core and are used everywhere else. Try to keep it that way by
-avoiding defining new templates in model-specific code.
-
-
-\section{Standards}
-\subsection{General}
-\begin{enumerate}
-\item There will be no {\em tab} characters in the code. Rather, repeated
-spaces are used to separate the characters as needed.
-\item No line of code will be longer than 80 characters in length, to
-prevent lines wrapping in the {\tt emacs} or {\tt vi} editors. For both
-of these linux text editing tools, the default is a window that is
-exactly 80 characters wide, so if none of the lines wrap when editing
-in {\tt emacs} or {\tt vi} this requirement is met.
-
-\item Each C++ statement will be on a separate line. The only exception
-is when an {\tt if}, {\tt else}, {\tt for} or {\tt while}
-statement has a single
-statement sub--block these can be on the same line.
-
-Examples:
-
-\begin{tt}
-int i = 0; // Right\\
-i = 10; j = 20; // Wrong. Two statements same line\\
-Sub1(k); Sub2(k); // Wrong. Two statements same line\\
-if (done) break; // Right. If statement with single statement sub-block
-\end{tt}
-
-\item Each variable declaration will be on a separate line.
-
-Examples:
-
-\begin{tt}
-\begin{tabbing}
-int c, d; \=// Wrong. c and d defined on same line.\\
-int a = 0; \\
-int b = 0; \>// Right. a and b on different lines\\
-\end{tabbing}
-\end{tt}
-
-\item Variables should be declared at the point in the code
-where they are needed, and should be assigned an initial value
-at the time of declaration.
-
-\begin{tt}
-\begin{tabbing}
-int a = 0; \=// Right, a is assigned in initial value.\\
-int b; \> Wrong, b is not assigned an initial value.\\
-int c = 0; \\
-int d = Sub1(a, b);\\
-c = Sub2(d); \> // Wrong, c should be declared here, not above
-\end{tabbing}
-\end{tt}
-
-\item Excepting when used in a {\tt switch} statement, the open
-and close curly braces (\{ and \}) are always on a separate line.
-
-Examples:
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-for (int i = 0; i < MAX\_COUNT; ++i) \\
-\>\{ // Right. Open brace on separate line \\
-\>\>sum += i; \\
-\>\>prod *= i; \\
-\>\} // Right. Close brace on separate line
-\end{tabbing}
-\end{tt}
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-for (int i = 0; i < 10; ++i) \{ // Wrong. Open brace on same line\\
-\>sum += i; \\
-\>prod *= i; \} // Wrong. Close brace on same line
-\end{tabbing}
-\end{tt}
-
-\item The C++ {\tt goto} statement is not to be used.
-\end{enumerate}
-\subsection{Commenting}
-In general, comments should be use liberally throughout the program to
-increase readability. Specifically:
-
-\begin{enumerate}
-\item C++ style comments using the {\tt //} delimeter
-are to be used, rather than C style comments with the {\tt /*}
-and {\tt */} delimieters.
-
-\item Variable declaration should have a short, one or two line comment
-describing the purpose of the variable, unless it is a
-local variable whose use is obvious from the context. The short
-comment should be on the same line as the variable declaration, unless it
-is too long, in which case it should be on the preceding lines.
-
-Example:
-
-\begin{tt}
-int averageGrade; // Computed average grade for this project \\
- // Note. The above comment likely qualifies as \\
- // obvious from context, and could be omitted.
-\\
-// Counts the total number of students completing the project, but\\
-// does not include those not turning in the project. \\
-int projectCount = 0;
-\end{tt}
-\item Every function should be preceded by a detailed comment block
-describing what the function does, what the formal parameters are, and
-what the return value is (if any).
-
-\item Every class declaration should be preceded by a comment block
-describing what the class is to be used for.
-
-\item Unless obvious from context, each {\tt if} statement should
-include a one--line comment on the open curly brace following describing
-the {\tt TRUE} condition and the {\tt FALSE} condition.
-
-Example:
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-if (iter == students.end()) \\
-\>\{ // Student not found, add him \\
-\>\>students.push\_back(thisStudent); \\
-\>\} \\
-else \\
-\>\{ // Student exists, modify existing data \\
-\>\>iter->grade += thisGrade; \\
-\>\}
-\end{tabbing}
-\end{tt}
-\item Class and function comments should adhere to the Doxygen standard
-format, for automated extraction by the Doxygen tool. {\em Note from
-GFR. We need a bit more here, as Doxygen has several possible methods
-for commenting. I'll look them over and suggest an approach, for later
-discussion}
-
-\end{enumerate}
-\subsection{Naming Conventions}
-\begin{enumerate}
-\item {\bf Variable Names}. All variables, including global variables,
-local variables, formal parameters,
-and member variables in classes will start with a
-lower case letter, and consist of only alphabetic characters and numeric
-digits. Capital letters are to be used when appropriate between words
-in a variable name for increased readability.
-Variable names should not contain the underscore character.
-
-Examples:
-
-{\tt int i;}\\
-{\tt int nextIndexValue;}\\
-{\tt int sum1;}\\
-{\tt int loopCount10;}
-
-\item {\bf Class Member and Global Variables}. To be able to distinguish
-local variables from class member and global variables, prepend the
-\code{m\_} prefix to class member variables and the \code{g\_} prefix
-to global variables.
-
-Examples:
-\begin{verbatim}
-class Foo {
-private:
- int m_myPrivateVar;
-};
-static int g_myGlobalVar;
-\end{verbatim}
-
-\item {\bf Subroutine Names}. All subroutine names, including global
-routines and member functions in classes, will start with an upper case
-letter, and consist of only alphabetic characters and numeric digits
-(although digits should be rarely needed).
-As in variable names, upper case letters are to be used between words as needed
-to increase readability.
-
-Examples:
-
-{\tt int ComputeNextIterator()}\\
-{\tt int Calculate()}\\
-{\tt int TransmitPacket()}\\
-{\tt int Dummy()}
-
-\item {\bf Defined Constants}. All defined constants will be all upper
-case letters or numeric digits, with the underscore character separating
-words.
-
-Examples:
-
-{\tt typedef enum \{ PACKET\_RX, PACKET\_FIRST\_BIT\_RX, PACKET\_TX\} }\\
-{\tt \#define NUMBER\_ELEMENTS 10}\\
-{\tt const int LOOP\_COUNT = 100}
-
-\item {\bf Defined Types}. All user defined types will end start with
-an upper case letter, consist of upper and lower case letters only, and
-end in {\tt \_t}.
-
-Examples:
-
-{\tt typedef double Time\_t; // Simulation time}\\
-{\tt typedef unsigned long SimulatorUid\_t; // Unique ID for each event}\\
-{\tt typedef unsigned long Event\_t; // Idenifies events in handler}\\
-
-\item {\bf Class Names}. Class names will start with an upper case letter,
-consist of only alphabetic characters, and include capital letters as
-needed to increase readability.
-
-Examples:
-
-{\tt class DropTailQueue \{}\\
-{\tt class Ferrari \{}\\
-
-\end{enumerate}
-
-%\newpage % Adjust as needed
-\subsection{Statement Formatting}
-\begin{enumerate}
-\item {\bf Indention}. The basic indention level for all code
-is two character positions.
-\item {\bf Continuation statements}. Frequently a single statement
-is too long to fit within a single 80 column line. In this case, the
-statement is simply continued on the next one or more lines. Each
-continuation line must be indented at least one--half indention level,
-and more as necessary to increase readability.
-
-Examples:
-
-\begin{tt}
-\begin{tabbing}
-longVariableName = \=(anotherLongName * shorterName) + (loopIndex2 * i) + \\
-\>(k * j); // Correct, indented for neatness
-\end{tabbing}
-\end{tt}
-
-\begin{tt}
-\begin{tabbing}
-a\=a\=a\= \kill
-for (LongTypeName\_t longLoopIndexName = aLongExpression; \\
-\>longLoopIndexName < MAX\_VALUE; \\
-\>longLoopIndexName++) // Wrong, continuations not indented far enough
-\end{tabbing}
-\end{tt}
-
-\begin{tt}
-\begin{tabbing}
-for (\=LongTypeName\_t longLoopIndexName = aLongExpression; \\
-\>longLoopIndexName < MAX\_VALUE; \\
-\>longLoopIndexName++) // Right, indented for readability
-\end{tabbing}
-\end{tt}
-
-\item {\bf {\tt IF} Statements}.
-The open curly brace following an {\tt IF} statement must be on the
-following line, indented by one indention level.
-The subsequent lines must be
-indented by an additional one indention level.
-The {\tt ELSE} statement (if present)
-must be on a line by itself.
-
-Examples:
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-if (someCondition) \\
-\>\{ // Describe TRUE condition here\\
-\>\>i = k;\\
-\>\>k = i + 2;\\
-\>\} // Right, curly block indented one indent level, statements one indent more
-\end{tabbing}
-\end{tt}
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-if (someCondition) \\
-\>\{ // Describe TRUE condition here\\
-\>\>i = k;\\
-\>\>k = i + 2;\\
-\>\} \\
-else // Right, ELSE statement on separate line, same indent as IF \\
-\>\{ // Describe FALSE condition here\\
-\>\>i = k * 2; \\
-\>\>k = i + 4; \\
-\>\} // Right, closing curly brace lined up with open brace
-\end{tabbing}
-\end{tt}
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-if (someCondition) // Describe TRUE condition here\\
-\>i = k; // Right, single line block need not have curly braces \\
-\end{tabbing}
-\end{tt}
-
-
-\item {\bf {\tt FOR} Statements}.
-The open brace following a {\tt for} statement is indented
-one level from the {\tt for} statement itself. Each statement
-in the sub--block is indented one level from the curly brace.
-If the sub--block is a single statement, the curly braces can be
-omitted and the statement indented one level, or optionally appear
-on the same line as the {\tt for} statement.
-
-Example:
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-for (int i = 0; i < MAX\_COUNT; ++i) \\
-\>\{ // Curly brace indented one level \\
-\>\>sum += i; // Statements indented another one level \\
-\>\>prod *= i; \\
-\>\} // Close brace on same column as open brace \\
-\end{tabbing}
-\end{tt}
-
-\item {\bf {\tt WHILE} Statements}.
-{\tt While} statements are formatted similarly to {\tt IF} statements,
-with curly braces indented one level on separate lines, and the
-inner statements indented another level. If the sub--block has only
-a single line, the curly braces can be omitted, and the statement may
-appear on the same line as the {\tt WHILE} statement.
-
-Examples:
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-while (someCondition) \\
-\>\{ // Right, open brace indented one level \\
-\>\>i = k; // Right, statements indented one level from open brace \\
-\>\>k = i + 2;\\
-\>\} // Right, close brace lines up with open brace
-\end{tabbing}
-\end{tt}
-
-\item {\bf Infinite Loops}.
-Any loop intended to be infinite (of course with a {\tt break} statement
-somewhere) should be of the form:
-
-\begin{tt}
-while(true) \\
- { // Loop until sentinel found\\
- ...code here \\
- }
-\end{tt}
-
-\item {\bf {\tt SWITCH} Statements}.
-The open curly brace for a {\tt switch} statement will be on the same
-line as the {\tt switch} statement itself. Each {\tt case} statement
-following is indented two columns from the switch statement. Each
-statement in the {\tt case} block is indented two column from the
-{\tt case} statement. The closing curly brace is on a separate line
-by itself, indented two columns from the {\tt switch} statement.
-
-Example:
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\= \kill
-switch(someCondition) \{ Right, open brace on same line as switch\\
-\>case 0 : // Right, case indented two columns from switch\\
-\>\>i = k; // Right, statements indented two columns from case \\
-\>\>k = i + 2;\\
-\>\>break;\\
-\>case 1 : // Right, case indented two columns from switch\\
-\>\>i = k + 2; // Right, statements indented two columns from case \\
-\>\>k = i + 4;\\
-\>\>break;\\
-\>\} // Right, close brace lines up with case statements
-\end{tabbing}
-\end{tt}
-
-\item {\bf Functions}. Since C and C++ do not allow nested functions,
-all functions start with no indentation at column 0. The open curly
-brace is on a line by itself immediately following the function header
-and formal parameters, also in column 0.
-
-Example:
-
-\begin{tt}
-\begin{tabbing}
-aa\=aa\=aa\=aa\= \kill
-void Function1(int arg1, double arg2)\\
-\{ // Right, curly brace at column 0\\
-\>int local1 = 0; // Right, local variable at column 2\\
-\>int local2;\\
-\>\\
-\>local2 = local1 + arg1 + arg2; // Right, indented two columns\\
-\>int local3; // Right, variable at same level\\
-\>local3 = Function2(local2);\\
-\>if (someCondition)\\
-\>\>\{\\
-\>\>\>local3 = 0;\\
-\>\>\>local2 = local1;\\
-\>\>\>int local4 = local1 + 1; // Right, variable at same level\\
-\>\>\>Function3(local4);\\
-\>\>\}\\
-\} // Right, close brace at column 0
-\end{tabbing}
-\end{tt}
-
-\item {\bf Expressions}. Spaces should be used liberally in expressions
-to increase readability. One space before and after each operator,
-excepting the increment and decrement operators, leads to easy--to--read
-expressions. Continued expressions should be indented as far as needed
-for neatness and readability.
-
-Examples:
-
-\begin{tt}
-i = k * 2 + 3 / var1++; // Right, spacing separating terms \\
-\end{tt}
-
-\begin{tt}
-i = k*2+2/var1++; // Wrong, crowded together and hard to read
-\end{tt}
-
-\begin{tt}
-\begin{tabbing}
-someLongVariableName = \=anotherLongVariableName * shorterName + \\
-\>anotherName; // Right, indented to line up
-\end{tabbing}
-\end{tt}
-
-\end{enumerate}
-\subsection{Header Files}
-\begin{enumerate}
-\item All header files will have a file name ending with {\tt .h}.
-\item All header files should have a one line comment describing
-the purpose of the header, and comments identifying the
-author and the (approximate) date the file was created.
-
-Example:
-
-\begin{tt}
-// ns3 Network Simulator - TCP Base Class Declaration \\
-// George F. Riley. riley@ece.gatech.edu. \\
-// Georgia Tech, Fall 2006
-\end{tt}
-
-\item All header files should have an ``include guard'' to prevent accidental
-inclusion of the file multiple times in a single compilation unit. The include
-guard should be named after the file name. If the file name is \code{foo-bar.h}, then the
-include guard should be named \code{FOO\_BAR\_H}
-
-Example:
-
-\begin{tt}
-\#ifndef FOO\_BAR\_H \\
-\#define FOO\_BAR\_H \\
-
-// (Contents of foo-bar.h here
-
-\#endif
-\end{tt}
-\item Header files should avoid including other files whenever possible.
-This can often be avoided with judicious use of the
-{\tt class ClassName;} forward declaration.
-
-Example:
-
-\begin{tt}
-// excerpt from application.h \\
-class L4Protocol; \\
-
-class Application \{ \\
- .... \\
- AddL4Proto(const L4Protocol\&); \\
- .... \\
- L4Protocol* l4Proto; \\
-\};
-\end{tt}
-
-In the above example, the use of the forward declaration for {\tt L4Protocol}
-obviates the need to include {\tt l4proto.h} in the application header
-file.
-
-\end{enumerate}
-\subsection{Source Code Files}
-\begin{enumerate}
-\item All souce code files will have a file name ending with {\tt .cc}.
-\item All source code files should have a one line comment describing
-the purpose of the code, and comments identifying the
-author and the (approximate) date the file was created.
-
-Example:
-
-\begin{tt}
-// ns3 Network Simulator - TCP Base Class Implementation \\
-// George F. Riley. riley@ece.gatech.edu. \\
-// Georgia Tech, Fall 2006
-\end{tt}
-
-\item All {\tt \#include} directives should be grouped with {\em system}
-files listed first (eg. {\tt \#include <iostream>}), followed by
-\nst\ defined files (eg. {\tt \#include "tcp.h"}). Within a group,
-the includes should be sorted in alphabetical order.
-
-Example:
-
-\begin{tt}
-\#include <iostream> \\
-\#include <list> \\
-\#include <vector> \\
-
-\#include "application.h" \\
-\#include "dumbbell.h" \\
-\#include "simulator.h" \\
-\#include "tcp.h.h"
-
-\end{tt}
-\end{enumerate}
-\end{document}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/codingstd.txt Fri May 25 09:44:18 2007 +0200
@@ -0,0 +1,210 @@
+ The Ns-3 Coding Style
+
+/*
+ * Note: This file is incomplete and will be converted to non-text (html,pdf)
+ * formats at a future date
+ */
+
+1) Code layout
+ -----------
+
+The code layout follows the GNU coding standard layout for C and extends
+it to C++. Do not use tabs for indentation. Indentation spacing is 2
+spaces as outlined below:
+
+void
+Foo (void)
+{
+ if (test)
+ {
+ // do stuff here
+ }
+ else
+ {
+ // do other stuff here
+ }
+
+ for (int i = 0; i < 100; i++)
+ {
+ // do loop
+ }
+
+ while (test)
+ {
+ // do while
+ }
+
+ do
+ {
+ // do stuff
+ } while ();
+}
+
+The following is not recommended:
+
+if (test) statement
+
+if (test)
+ statement
+
+for (...) statement
+
+Each statement should be put on a separate line to increase readability.
+Short one-line comments can use the C++ comment style, that is, '//'
+but longer comments should use C-style comments:
+/*
+ *
+ *
+ */
+
+
+2) Naming Patterns
+ ---------------
+
+2.1) Name encoding
+ -------------
+Function, Method, and Type names should follow the CamelCase convention:
+words are joined without spaces and are capitalized. For example,
+"my computer" is transformed into MyComputer. Do not use all capital
+letters such as MAC or, PHY, but choose instead Mac or Phy. Do not use
+all capital letters, even for acronyms such as EDCA: use Edca instead.
+The goal of the CamelCase convention is to ensure that the words which
+make up a name can be separated by the eye: the initial Caps fills
+that role.
+
+Variable names should follow a slight variation on the base CamelCase
+convention: camelBack. For example, the variable "user name" would be
+named "userName". This variation on the basic naming pattern is used to
+allow a reader to distinguish a variable name from its type. For example,
+"UserName userName;" would be used to declare a variable named userName
+of type UserName.
+
+Global variables should be prefixed with a "g_" and member variables
+(including static member variables) should be prefixed with a "m_". The
+goal of that prefix is to give a reader a sense of where a variable of
+a given name is declared to allow the reader to locate the variable
+declaration and infer the variable type from that declaration. For example
+you could declare in your class header my-class.h:
+
+class MyClass
+{
+ void MyMethod (int aVar);
+ int m_aVar;
+ static int m_anotherVar;
+};
+
+and implement in your class file my-class.cc:
+
+int MyClass::m_anotherVar = 10;
+static int g_aStaticVar = 100;
+int g_aGlobalVar = 1000;
+
+void
+MyClass::MyMethod (int aVar)
+{
+ m_aVar = aVar;
+}
+
+2.2) Choosing names
+
+Variable, function, method, and type names should be based on the
+english language. Furthermore, always try to choose descriptive
+names for them. Types are often english names such as: Packet,
+Buffer, Mac, or Phy. Functions and Methods are often named
+based on verbs and adjectives: GetX, DoDispose, ClearArray, etc.
+
+A long descriptive name which requires a lot of typing is always
+better than a short name which is hard to decipher. Do not use
+abbreviations in names unless the abbreviation is really unambiguous
+and obvious to everyone. Do not use short inapropriate names such
+as foo, bar, or baz. The name of an item should always match its
+purpose. As such, names such as tmp to identify a temporary
+variable or such as 'i' to identify a loop index are ok.
+
+3) File layout and code organization
+ ---------------------------------
+
+A class named MyClass should be declared in a header named my-class.h
+and implemented in a source file named my-class.cc. The goal of this
+naming pattern is to allow a reader to quickly navigate through
+the ns-3 codebase to locate the source file relevant to a specific
+type.
+
+Each my-class.h header should start with the following comments: the
+first line ensures that developers who use the emacs editor will be
+able to indent your code correctly. The following lines ensure that
+your code is licensed under the GPL, that the copyright holders
+are properly identified (typically, you or your employer), and
+that the actual author of the code is identified. The latter is
+purely informational and we use it to try to track the most
+appropriate person to review a patch or fix a bug.
+
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) YEAR COPYRIGHTHOLDER
+ *
+ * 3-paragran GPL blurb
+ *
+ * Author: MyName <myemail@foo.com>
+ */
+
+Below these C-style comments, always include the following which
+defines a set of header guards (MY_CLASS_H) used to avoid multiple
+header includes, which ensures that your code is included
+in the "ns3" namespace and which provides a set of doxygen comments
+for the public part of your class API. Detailed information
+on the set of tags available for doxygen documentation is described
+in the doxygen website: http://www.doxygen.org.
+
+#ifndef MY_CLASS_H
+#define MY_CLASS_H
+
+namespace n3 {
+
+/**
+ * \brief short one-line description of the purpose of your class
+ *
+ * A longer description of the purpose of your class after a blank
+ * empty line.
+ */
+class MyClass
+{
+public:
+ MyClass ();
+ /**
+ * \param firstParam a short description of the purpose of this parameter
+ * \returns a short description of what is returned from this function.
+ *
+ * A detailed description of the purpose of the method.
+ */
+ int DoFoo (int firstParam);
+private:
+ void MyPrivateMethod (void);
+ int m_myPrivateMemberVariable;
+};
+
+} // namespace ns3
+
+#endif /* MY_CLASS_H */
+
+The my-class.cc file is structured similarly:
+
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) YEAR COPYRIGHTHOLDER
+ *
+ * 3-paragran GPL blurb
+ *
+ * Author: MyName <myemail@foo.com>
+ */
+#include "my-class.h"
+
+namespace ns3 {
+
+MyClass::MyClass ()
+{}
+
+...
+
+} // namespace ns3
+
--- a/doc/contributing.txt Sat May 19 13:41:50 2007 +0200
+++ b/doc/contributing.txt Fri May 25 09:44:18 2007 +0200
@@ -1,7 +1,13 @@
-
Contributing to the ns-3 project
--------------------------------
+ns-3 is an open source project backed by an NSF CISE CRI grant.
+Although the NSF PIs have specific aims to fulfill, we want others to
+contribute, and we'd like to have a broad community of users and
+developers, with the goal of a self-sustaining project downstream.
+The project is currently in a bootstrapping phase, but we welcome
+ambitious developers who might want to help shape the early design.
+
Despite the lack of a formal contribution process to the ns-3
project, there are a number of steps which we expect every
potential contributor to follow. These naturally stem from
@@ -46,8 +52,12 @@
also expect model authors to act as responsible maintainers
and be reactive to bug reports concerning their models.
- - you should make sure that you understand that contributed
- models should be licensed under the GPLv2. You do not have
- to assign your copyright to the ns-3 project but you must
- accept the terms of the GPLv2. See the following link:
+ - The project has decided upon GNU GPLv2 as the licensing structure.
+ All simulation software in the ns-3 repositories will be GNU GPLv2
+ or GNU GPLv2-compatible (with non-GPLv2 licensing reserved for
+ ports of pre-existing code under a different license, such as BSD).
+ You do not have to assign your copyright to the ns-3 project but
+ you must accept the terms of the GPLv2 and attest that your
+ contributions can be licensed under those terms. See the
+ following link:
http://www.fsf.org/licensing/licenses/info/GPLv2.html
--- a/doc/mercurial.txt Sat May 19 13:41:50 2007 +0200
+++ b/doc/mercurial.txt Fri May 25 09:44:18 2007 +0200
@@ -3,7 +3,7 @@
ns-3 uses the Mercurial software revision control system which
is a replacement for tools liks cvs or subversion. Thus, to get
-access to the developement versions of ns-3, you need to install
+access to the development versions of ns-3, you need to install
mercurial first. See http://www.selenic.com/mercurial/wiki/
Mercurial cheat sheet
@@ -38,6 +38,7 @@
--------------------------------------
To the main repository:
hg push ssh://code@code.nsnam.org/repos/ns-3-dev
+
To your private repository:
hg push ssh://username@code.nsnam.org//home/username/repositories/username/repository
--- a/src/common/data-rate.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/common/data-rate.cc Fri May 25 09:44:18 2007 +0200
@@ -147,6 +147,36 @@
return v;
}
+bool DataRate::operator < (const DataRate& rhs)
+{
+ return m_bps<rhs.m_bps;
+}
+
+bool DataRate::operator <= (const DataRate& rhs)
+{
+ return m_bps<=rhs.m_bps;
+}
+
+bool DataRate::operator > (const DataRate& rhs)
+{
+ return m_bps>rhs.m_bps;
+}
+
+bool DataRate::operator >= (const DataRate& rhs)
+{
+ return m_bps>=rhs.m_bps;
+}
+
+bool DataRate::operator == (const DataRate& rhs)
+{
+ return m_bps==rhs.m_bps;
+}
+
+bool DataRate::operator != (const DataRate& rhs)
+{
+ return m_bps!=rhs.m_bps;
+}
+
double DataRate::CalculateTxTime(uint32_t bytes) const
{
return static_cast<double>(bytes)*8/m_bps;
--- a/src/common/data-rate.h Sat May 19 13:41:50 2007 +0200
+++ b/src/common/data-rate.h Fri May 25 09:44:18 2007 +0200
@@ -41,6 +41,8 @@
* uint32_t nBytes = 20;
* double txtime = x.CalclulateTxTime(nBytes);
* \endcode
+ * This class also supports the regular comparison operators <, >, <=, >=, ==,
+ * and !=
*/
class DataRate
{
@@ -70,6 +72,13 @@
*/
DataRate (const std::string s);
+ bool operator < (const DataRate& rhs);
+ bool operator <= (const DataRate& rhs);
+ bool operator > (const DataRate& rhs);
+ bool operator >= (const DataRate& rhs);
+ bool operator == (const DataRate& rhs);
+ bool operator != (const DataRate& rhs);
+
/**
* \brief Calculate transmission time
*
--- a/src/common/smartset.h Sat May 19 13:41:50 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-#ifndef __SMART_SET_H__
-#define __SMART_SET_H__
-
-#include <set>
-
-namespace ns3 {
-
-// Define a "smart" set container to be used by any ns3 object
-// maintaining a collection of pointers, which must be freed at
-// a later time. The template parameter T must be a pointer, or an
-// object supporting the delete operator, and the dereferenced object
-// must support a Copy() function. The set implementation
-// has a O(1) "Remove" operation, that removes and deletes
-// a single element in the container. However, additions to the
-// set are O(n) due to the sorted nature of the underlying STL set.
-
-// Define a "smart" set container
-template <typename T> class SmartSet {
-public:
- typedef typename std::set<T>::const_iterator const_iterator;
- typedef typename std::set<T>::iterator iterator;
- typedef typename std::set<T>::size_type size_type;
- SmartSet()
- { // Nothing needed for default constructor
- }
-
- ~SmartSet()
- { // Smart container destructor
- for (const_iterator i = m_elements.begin(); i != m_elements.end(); ++i)
- {
- delete *i;
- }
- // No need to "clear" the set, as the set destructor does this
- }
-
- SmartSet(const SmartSet& o)
- { // Copy constructor, copy all underlying objects
- for (iterator i = o.Begin(); i != o.End(); ++i)
- {
- Add((*i)->Copy());
- }
- }
-
- void Add(const T& t) // Add element, will be deleted on Clear or destructor
- {
- m_elements.insert(t);
- }
-
- bool Remove(T& t) // Remove and delete specified element
- { // Find the specified element, delete it, and remove from the container.
- // Returns true if found
- iterator i = m_elements.find(t);
- if (i != m_elements.end())
- { // Found it, delete it
- delete t; // Delete the object
- m_elements.erase(i); // Erase the element
- return true;
- }
- return false;
- }
-
- void Clear()
- { // Delete and remove all elements from the smart container
- for (const_iterator i = m_elements.begin(); i != m_elements.end(); ++i)
- {
- delete *i;
- }
- m_elements.clear();
- }
-
- // Iterator access
- iterator Begin() const
- {
- return m_elements.begin();
- }
-
- iterator End() const
- {
- return m_elements.end();
- }
-
- // Miscellaneous
- size_type Size() const
- {
- return m_elements.size();
- }
-
- bool Empty() const
- {
- return m_elements.empty();
- }
-
-private:
- std::set<T> m_elements;
-};
-
-} // namespace ns3
-#endif
--- a/src/common/smartvector.h Sat May 19 13:41:50 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-#ifndef __SMART_VECTOR_H__
-#define __SMART_VECTOR_H__
-
-#include <vector>
-
-namespace ns3 {
-
-// Define a "smart" vector container to be used by any ns3 object
-// maintaining a collection of pointers, which must be freed at
-// a later time. The template parameter T must be a pointer, or an
-// object supporting the delete operator, and the dereferenced object
-// must support the Copy() operation. The vector implementation
-// has in inefficient "Remove" operation, that removes and deletes
-// a single element in the container. If frequent "Remove" operations
-// are needed, the SmartSet is likey a better choice.
-
-template <typename T> class SmartVector {
-public:
- typedef typename std::vector<T>::const_iterator const_iterator;
- typedef typename std::vector<T>::iterator iterator;
- typedef typename std::vector<T>::size_type size_type;
- SmartVector()
- { // Nothing needed for default constructor
- }
- ~SmartVector()
- { // Smart container destructor
- for (const_iterator i = m_elements.begin(); i != m_elements.end(); ++i)
- {
- delete *i;
- }
- // No need to "clear" the vector, as the vector destructor does this
- }
-
- SmartVector(const SmartVector& o)
- { // Copy constructor, copy each underlying object
- for (const_iterator i = o.Begin(); i != o.End(); ++i)
- {
- Add((*i)->Copy());
- }
- }
-
- void Add(const T& t) // Add element, will be deleted on Clear or destructor
- {
- m_elements.push_back(t);
- }
-
- bool Remove()
- { // Remove the back element
- if (Empty()) return false; // No back element exists
- m_elements.pop_back();
- return true;
- }
-
- bool Remove(const T& t) // Remove and delete specified element
- { // Find the specified element, delete it, and remove from the container.
- // Returns true if found.
- // Note, this implementation is not particularly efficient. If
- // explicit individual element removal is a frequent operation for a given
- // smart container, an implementation based on STL "set" will
- // be a better choice. See "SmartSet" if for this approach.
- // The SmartSet adds extra overhead in that the elementes are sorted,
- // so it should be used with caution.
- for (const_iterator i = m_elements.begin(); i != m_elements.end(); ++i)
- {
- if (*i == t)
- { // Found it
- delete t; // Delete the object
- m_elements.erase(i); // Erase the element
- return true;
- }
- }
- return false;
- }
-
- void Clear()
- { // Delete and remove all elements from the smart container
- for (const_iterator i = m_elements.begin(); i != m_elements.end(); ++i)
- {
- delete *i;
- }
- m_elements.clear();
- }
-
- // Iterator access
- const_iterator Begin() const
- {
- return m_elements.begin();
- }
-
- const_iterator End() const
- {
- return m_elements.end();
- }
-
- // Miscellaneous
- size_type Size() const
- {
- return m_elements.size();
- }
-
- bool Empty() const
- {
- return m_elements.empty();
- }
-
- T& Back()
- {
- return m_elements.back();
- }
-
- T operator[](size_type i) const
- { // Indexing operator
- return m_elements[i];
- }
-
-private:
- std::vector<T> m_elements;
-};
-
-} // Namespace ns3
-#endif
--- a/src/common/wscript Sat May 19 13:41:50 2007 +0200
+++ b/src/common/wscript Fri May 25 09:44:18 2007 +0200
@@ -43,7 +43,5 @@
'array-trace-resolver.h',
'trace-root.h',
'terminal-trace-resolver.h',
- 'smartvector.h',
- 'smartset.h',
'data-rate.h',
]
--- a/src/core/callback-test.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/core/callback-test.cc Fri May 25 09:44:18 2007 +0200
@@ -192,8 +192,17 @@
f1 (1);
g1 (2);
+ a1.Nullify ();
+ b1.Nullify ();
+ c1.Nullify ();
+ d1.Nullify ();
+ e1.Nullify ();
+ g1.Nullify ();
+
Test8 (f1);
+ f1.Nullify ();
+
Callback<void, int64_t,int64_t> a2;
if (IsWrong ())
--- a/src/core/callback.h Sat May 19 13:41:50 2007 +0200
+++ b/src/core/callback.h Fri May 25 09:44:18 2007 +0200
@@ -22,7 +22,7 @@
#ifndef CALLBACK_H
#define CALLBACK_H
-#include "reference-list.h"
+#include "ptr.h"
#include "fatal-error.h"
namespace ns3 {
@@ -58,10 +58,35 @@
*/
class empty {};
+template <typename T>
+struct CallbackTraits;
+
+template <typename T>
+struct CallbackTraits<T *>
+{
+ static T & GetReference (T * const p)
+ {
+ return *p;
+ }
+};
+
class CallbackImplBase {
public:
+ CallbackImplBase ()
+ : m_count (1) {}
virtual ~CallbackImplBase () {}
+ void Ref (void) {
+ m_count++;
+ }
+ void Unref (void) {
+ m_count--;
+ if (m_count == 0) {
+ delete this;
+ }
+ }
virtual bool IsEqual (CallbackImplBase const *other) const = 0;
+private:
+ uint32_t m_count;
};
// declare the CallbackImpl class
@@ -116,7 +141,7 @@
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
FunctorCallbackImpl (T const &functor)
- : m_functor (functor) {}
+ : m_functor (functor) {}
virtual ~FunctorCallbackImpl () {}
R operator() (void) {
return m_functor ();
@@ -158,25 +183,25 @@
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5> {
public:
MemPtrCallbackImpl (OBJ_PTR const&objPtr, MEM_PTR mem_ptr)
- : m_objPtr (objPtr), m_memPtr (mem_ptr) {}
+ : m_objPtr (objPtr), m_memPtr (mem_ptr) {}
virtual ~MemPtrCallbackImpl () {}
R operator() (void) {
- return ((*m_objPtr).*m_memPtr) ();
+ return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) ();
}
R operator() (T1 a1) {
- return ((*m_objPtr).*m_memPtr) (a1);
+ return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1);
}
R operator() (T1 a1,T2 a2) {
- return ((*m_objPtr).*m_memPtr) (a1,a2);
+ return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2);
}
R operator() (T1 a1,T2 a2,T3 a3) {
- return ((*m_objPtr).*m_memPtr) (a1,a2,a3);
+ return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4) {
- return ((*m_objPtr).*m_memPtr) (a1,a2,a3,a4);
+ return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4);
}
R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
- return ((*m_objPtr).*m_memPtr) (a1,a2,a3,a4,a5);
+ return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5);
}
virtual bool IsEqual (CallbackImplBase const *other) const {
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *otherDerived =
@@ -242,40 +267,43 @@
// always properly disambiguited by the c++ compiler
template <typename FUNCTOR>
Callback (FUNCTOR const &functor, bool, bool)
- : m_impl (new FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> (functor))
+ : m_impl (MakeNewObject<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> > (functor))
{}
template <typename OBJ_PTR, typename MEM_PTR>
Callback (OBJ_PTR const &objPtr, MEM_PTR mem_ptr)
- : m_impl (new MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> (objPtr, mem_ptr))
+ : m_impl (MakeNewObject<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> > (objPtr, mem_ptr))
{}
- Callback (ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5> *> const &impl)
+ Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > const &impl)
: m_impl (impl)
{}
bool IsNull (void) {
- return (m_impl.Get () == 0)?true:false;
+ return (PeekImpl () == 0)?true:false;
+ }
+ void Nullify (void) {
+ m_impl = 0;
}
Callback () : m_impl () {}
R operator() (void) const {
- return (*(m_impl.Get ())) ();
+ return (*(PeekImpl ())) ();
}
R operator() (T1 a1) const {
- return (*(m_impl.Get ())) (a1);
+ return (*(PeekImpl ())) (a1);
}
R operator() (T1 a1, T2 a2) const {
- return (*(m_impl).Get ()) (a1,a2);
+ return (*(PeekImpl ())) (a1,a2);
}
R operator() (T1 a1, T2 a2, T3 a3) const {
- return (*(m_impl).Get ()) (a1,a2,a3);
+ return (*(PeekImpl ())) (a1,a2,a3);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4) const {
- return (*(m_impl).Get ()) (a1,a2,a3,a4);
+ return (*(PeekImpl ())) (a1,a2,a3,a4);
}
R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const {
- return (*(m_impl).Get ()) (a1,a2,a3,a4,a5);
+ return (*(PeekImpl ())) (a1,a2,a3,a4,a5);
}
bool IsEqual (CallbackBase const &other) {
@@ -304,10 +332,10 @@
*this = *goodType;
}
private:
- virtual CallbackImplBase *PeekImpl (void) const {
- return m_impl.Get ();
+ virtual CallbackImpl<R,T1,T2,T3,T4,T5> *PeekImpl (void) const {
+ return PeekPointer (m_impl);
}
- ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> m_impl;
+ Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > m_impl;
};
/**
@@ -323,12 +351,12 @@
* Build Callbacks for class method members which takes no arguments
* and potentially return a value.
*/
-template <typename OBJ, typename R>
-Callback<R> MakeCallback (R (OBJ::*mem_ptr) (), OBJ *const objPtr) {
- return Callback<R> (objPtr, mem_ptr);
+template <typename T, typename OBJ, typename R>
+Callback<R> MakeCallback (R (T::*memPtr) (void), OBJ objPtr) {
+ return Callback<R> (objPtr, memPtr);
}
-template <typename OBJ, typename R>
-Callback<R> MakeCallback (R (OBJ::*mem_ptr) () const, OBJ const *const objPtr) {
+template <typename T, typename OBJ, typename R>
+Callback<R> MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) {
return Callback<R> (objPtr, mem_ptr);
}
/**
@@ -339,12 +367,12 @@
* Build Callbacks for class method members which takes one argument
* and potentially return a value.
*/
-template <typename OBJ, typename R, typename T1>
-Callback<R,T1> MakeCallback (R (OBJ::*mem_ptr) (T1), OBJ *const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1>
+Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1), OBJ *const objPtr) {
return Callback<R,T1> (objPtr, mem_ptr);
}
-template <typename OBJ, typename R, typename T1>
-Callback<R,T1> MakeCallback (R (OBJ::*mem_ptr) (T1) const, OBJ const *const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1>
+Callback<R,T1> MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr) {
return Callback<R,T1> (objPtr, mem_ptr);
}
/**
@@ -355,12 +383,12 @@
* Build Callbacks for class method members which takes two arguments
* and potentially return a value.
*/
-template <typename OBJ, typename R, typename T1, typename T2>
-Callback<R,T1,T2> MakeCallback (R (OBJ::*mem_ptr) (T1,T2), OBJ *const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1, typename T2>
+Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ *const objPtr) {
return Callback<R,T1,T2> (objPtr, mem_ptr);
}
-template <typename OBJ, typename R, typename T1, typename T2>
-Callback<R,T1,T2> MakeCallback (R (OBJ::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1, typename T2>
+Callback<R,T1,T2> MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) {
return Callback<R,T1,T2> (objPtr, mem_ptr);
}
/**
@@ -371,12 +399,12 @@
* Build Callbacks for class method members which takes three arguments
* and potentially return a value.
*/
-template <typename OBJ, typename R, typename T1,typename T2, typename T3>
-Callback<R,T1,T2,T3> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1,typename T2, typename T3>
+Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) {
return Callback<R,T1,T2,T3> (objPtr, mem_ptr);
}
-template <typename OBJ, typename R, typename T1,typename T2, typename T3>
-Callback<R,T1,T2,T3> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1,typename T2, typename T3>
+Callback<R,T1,T2,T3> MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) {
return Callback<R,T1,T2,T3> (objPtr, mem_ptr);
}
/**
@@ -387,12 +415,12 @@
* Build Callbacks for class method members which takes four arguments
* and potentially return a value.
*/
-template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
-Callback<R,T1,T2,T3,T4> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
+Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) {
return Callback<R,T1,T2,T3,T4> (objPtr, mem_ptr);
}
-template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
-Callback<R,T1,T2,T3,T4> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4>
+Callback<R,T1,T2,T3,T4> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) {
return Callback<R,T1,T2,T3,T4> (objPtr, mem_ptr);
}
/**
@@ -403,12 +431,12 @@
* Build Callbacks for class method members which takes five arguments
* and potentially return a value.
*/
-template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
-Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) {
return Callback<R,T1,T2,T3,T4,T5> (objPtr, mem_ptr);
}
-template <typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
-Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) {
+template <typename T, typename OBJ, typename R, typename T1, typename T2, typename T3, typename T4,typename T5>
+Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) {
return Callback<R,T1,T2,T3,T4,T5> (objPtr, mem_ptr);
}
@@ -599,44 +627,34 @@
template <typename R, typename TX>
Callback<R> MakeBoundCallback (R (*fnPtr) (TX), TX a) {
- ReferenceList<CallbackImpl<R,empty,empty,empty,empty,empty>*> impl =
- ReferenceList<CallbackImpl<R,empty,empty,empty,empty,empty>*> (
- new BoundFunctorCallbackImpl<R (*) (TX),R,TX,empty,empty,empty,empty,empty> (fnPtr, a)
- );
+ Ptr<CallbackImpl<R,empty,empty,empty,empty,empty> > impl =
+ MakeNewObject<BoundFunctorCallbackImpl<R (*) (TX),R,TX,empty,empty,empty,empty,empty> >(fnPtr, a);
return Callback<R> (impl);
}
template <typename R, typename TX, typename T1>
Callback<R,T1> MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) {
- ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> impl =
- ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> (
- new BoundFunctorCallbackImpl<R (*) (TX,T1),R,TX,T1,empty,empty,empty,empty> (fnPtr, a)
- );
+ Ptr<CallbackImpl<R,T1,empty,empty,empty,empty> > impl =
+ MakeNewObject<BoundFunctorCallbackImpl<R (*) (TX,T1),R,TX,T1,empty,empty,empty,empty> > (fnPtr, a);
return Callback<R,T1> (impl);
}
template <typename R, typename TX, typename T1, typename T2>
Callback<R,T1,T2> MakeBoundCallback (R (*fnPtr) (TX,T1,T2), TX a) {
- ReferenceList<CallbackImpl<R,T1,T2,empty,empty,empty>*> impl =
- ReferenceList<CallbackImpl<R,T1,T2,empty,empty,empty>*> (
- new BoundFunctorCallbackImpl<R (*) (TX,T1,T2),R,TX,T1,T2,empty,empty,empty> (fnPtr, a)
- );
+ Ptr<CallbackImpl<R,T1,T2,empty,empty,empty> > impl =
+ MakeNewObject<BoundFunctorCallbackImpl<R (*) (TX,T1,T2),R,TX,T1,T2,empty,empty,empty> > (fnPtr, a);
return Callback<R,T1,T2> (impl);
}
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4>
Callback<R,T1,T2,T3,T4> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), TX a) {
- ReferenceList<CallbackImpl<R,T1,T2,T3,T4,empty>*> impl =
- ReferenceList<CallbackImpl<R,T1,T2,T3,T4,empty>*> (
- new BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4),R,TX,T1,T2,T3,T4,empty> (fnPtr, a)
- );
+ Ptr<CallbackImpl<R,T1,T2,T3,T4,empty> > impl =
+ MakeNewObject<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4),R,TX,T1,T2,T3,T4,empty> > (fnPtr, a);
return Callback<R,T1,T2,T3,T4> (impl);
}
template <typename R, typename TX, typename T1, typename T2,typename T3,typename T4,typename T5>
Callback<R,T1,T2,T3,T4,T5> MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), TX a) {
- ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> impl =
- ReferenceList<CallbackImpl<R,T1,T2,T3,T4,T5>*> (
- new BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4,T5),R,TX,T1,T2,T3,T4,T5> (fnPtr, a)
- );
+ Ptr<CallbackImpl<R,T1,T2,T3,T4,T5> > impl =
+ MakeNewObject<BoundFunctorCallbackImpl<R (*) (TX,T1,T2,T3,T4,T5),R,TX,T1,T2,T3,T4,T5> > (fnPtr, a);
return Callback<R,T1,T2,T3,T4,T5> (impl);
}
--- a/src/core/default-value.h Sat May 19 13:41:50 2007 +0200
+++ b/src/core/default-value.h Fri May 25 09:44:18 2007 +0200
@@ -286,6 +286,10 @@
* user with ns3::Bind
*/
T GetValue (void);
+ /**
+ * \param value the new default value.
+ */
+ void SetValue (T value);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
@@ -467,6 +471,12 @@
return m_value;
}
template <typename T>
+void
+EnumDefaultValue<T>::SetValue (T value)
+{
+ m_value = value;
+}
+template <typename T>
bool
EnumDefaultValue<T>::DoParseValue (const std::string &value)
{
--- a/src/core/ptr.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/core/ptr.cc Fri May 25 09:44:18 2007 +0200
@@ -33,7 +33,7 @@
public:
NoCount (Callback<void> cb);
~NoCount ();
- void Nothing () const;
+ void Nothing (void) const;
private:
Callback<void> m_cb;
};
@@ -280,6 +280,25 @@
ok = false;
}
}
+
+ {
+ Ptr<NoCount> p = MakeNewObject<NoCount> (cb);
+ Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
+ callback ();
+ }
+ {
+ Ptr<const NoCount> p = MakeNewObject<NoCount> (cb);
+ Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
+ callback ();
+ }
+
+#if 0
+ // as expected, fails compilation.
+ {
+ Ptr<const Object> p = MakeNewObject<NoCount> (cb);
+ Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
+ }
+#endif
return ok;
--- a/src/core/ptr.h Sat May 19 13:41:50 2007 +0200
+++ b/src/core/ptr.h Fri May 25 09:44:18 2007 +0200
@@ -73,11 +73,12 @@
/**
* \param ptr raw pointer to manage
*
- * Create a smart pointer which points to the
- * input raw pointer. This method takes ownershipt
- * of the input raw pointer. That is, the smart pointer
- * becomes responsible for calling delete on the
- * raw pointer when needed.
+ * Create a smart pointer which points to the object pointed to by
+ * the input raw pointer ptr. This method creates its own reference
+ * to the pointed object. The caller is responsible for Unref()'ing
+ * its own reference, and the smart pointer will eventually do the
+ * same, so that object is deleted if no more references to it
+ * remain.
*/
Ptr (T *ptr);
Ptr (Ptr const&o);
@@ -170,6 +171,31 @@
template <typename T1, typename T2>
Ptr<T1> const_pointer_cast (Ptr<T2> const&p);
+template <typename T>
+struct CallbackTraits;
+
+template <typename T>
+struct CallbackTraits<Ptr<T> >
+{
+ static T & GetReference (Ptr<T> const p)
+ {
+ return *PeekPointer (p);
+ }
+};
+
+template <typename T>
+struct EventMemberImplTraits;
+
+template <typename T>
+struct EventMemberImplTraits<Ptr<T> >
+{
+ static T &GetReference (Ptr<T> p) {
+ return *PeekPointer (p);
+ }
+};
+
+
+
} // namespace ns3
--- a/src/core/random-variable.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/core/random-variable.cc Fri May 25 09:44:18 2007 +0200
@@ -663,7 +663,7 @@
return z;
}
-double LogNormalVariable::GetSingleValue(double sigma,double mu)
+double LogNormalVariable::GetSingleValue (double mu, double sigma)
{
double u, v, r2, normal, z;
do
@@ -686,3 +686,104 @@
}//namespace ns3
+
+#ifdef RUN_SELF_TESTS
+#include "test.h"
+#include <vector>
+
+namespace ns3 {
+
+
+class RandomVariableTest : public Test
+{
+public:
+ RandomVariableTest () : Test ("RandomVariable") {}
+ virtual bool RunTests (void)
+ {
+ bool ok = true;
+ const double desired_mean = 1.0;
+ const double desired_stddev = 1.0;
+ double tmp = log (1 + (desired_stddev/desired_mean)*(desired_stddev/desired_mean));
+ double sigma = sqrt (tmp);
+ double mu = log (desired_mean) - 0.5*tmp;
+
+ // Test a custom lognormal instance
+ {
+ LogNormalVariable lognormal (mu, sigma);
+ vector<double> samples;
+ const int NSAMPLES = 10000;
+ double sum = 0;
+ for (int n = NSAMPLES; n; --n)
+ {
+ double value = lognormal.GetValue ();
+ sum += value;
+ samples.push_back (value);
+ }
+ double obtained_mean = sum / NSAMPLES;
+ sum = 0;
+ for (vector<double>::iterator iter = samples.begin (); iter != samples.end (); iter++)
+ {
+ double tmp = (*iter - obtained_mean);
+ sum += tmp*tmp;
+ }
+ double obtained_stddev = sqrt (sum / (NSAMPLES - 1));
+
+ if (not (obtained_mean/desired_mean > 0.90 and obtained_mean/desired_mean < 1.10))
+ {
+ ok = false;
+ Failure () << "Obtained lognormal mean value " << obtained_mean << ", expected " << desired_mean << std::endl;
+ }
+
+ if (not (obtained_stddev/desired_stddev > 0.90 and obtained_stddev/desired_stddev < 1.10))
+ {
+ ok = false;
+ Failure () << "Obtained lognormal stddev value " << obtained_stddev <<
+ ", expected " << desired_stddev << std::endl;
+ }
+ }
+
+ // Test GetSingleValue
+ {
+ vector<double> samples;
+ const int NSAMPLES = 10000;
+ double sum = 0;
+ for (int n = NSAMPLES; n; --n)
+ {
+ double value = LogNormalVariable::GetSingleValue (mu, sigma);
+ sum += value;
+ samples.push_back (value);
+ }
+ double obtained_mean = sum / NSAMPLES;
+ sum = 0;
+ for (vector<double>::iterator iter = samples.begin (); iter != samples.end (); iter++)
+ {
+ double tmp = (*iter - obtained_mean);
+ sum += tmp*tmp;
+ }
+ double obtained_stddev = sqrt (sum / (NSAMPLES - 1));
+
+ if (not (obtained_mean/desired_mean > 0.90 and obtained_mean/desired_mean < 1.10))
+ {
+ ok = false;
+ Failure () << "Obtained LogNormalVariable::GetSingleValue mean value " << obtained_mean
+ << ", expected " << desired_mean << std::endl;
+ }
+
+ if (not (obtained_stddev/desired_stddev > 0.90 and obtained_stddev/desired_stddev < 1.10))
+ {
+ ok = false;
+ Failure () << "Obtained LogNormalVariable::GetSingleValue stddev value " << obtained_stddev <<
+ ", expected " << desired_stddev << std::endl;
+ }
+ }
+
+ return ok;
+ }
+};
+
+
+static RandomVariableTest g_random_variable_tests;
+
+}//namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/core/random-variable.h Sat May 19 13:41:50 2007 +0200
+++ b/src/core/random-variable.h Fri May 25 09:44:18 2007 +0200
@@ -23,7 +23,7 @@
#include <vector>
#include <algorithm>
-
+#include <stdint.h>
/**
* \defgroup randomvariable Random Variable Distributions
--- a/src/core/reference-list-test.cc Sat May 19 13:41:50 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 INRIA
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "reference-list.h"
-#include "test.h"
-
-#ifdef RUN_SELF_TESTS
-
-#define noREFTEST_DEBUG 1
-
-#ifdef REFTEST_DEBUG
-#include <iostream>
-#define TRACE(x) \
- std::cout << x << std::endl;
-#else
-#define TRACE(x)
-#endif
-
-namespace {
-
-class A {
-public:
- A () {
- TRACE ("constructor");
- }
- ~A () {
- TRACE ("destructor");
- }
- void Trace (void) {
- TRACE ("trace");
- }
-};
-
-class RefTest : public ns3::Test {
-public:
- RefTest ();
- virtual bool RunTests (void);
-private:
- void OneTest (ns3::ReferenceList<A *>);
-};
-
-RefTest::RefTest ()
- : ns3::Test ("ReferenceList")
-{}
-
-void
-RefTest::OneTest (ns3::ReferenceList<A *> a)
-{
- a->Trace ();
-}
-
-bool
-RefTest::RunTests (void)
-{
- bool ok = true;
-
- {
- ns3::ReferenceList<A *> tmp;
- {
- ns3::ReferenceList<A *> a (new A ());
-
- OneTest (a);
- tmp = a;
- OneTest (tmp);
- a = tmp;
- OneTest (a);
- TRACE ("leave inner scope");
- }
- OneTest (tmp);
- TRACE ("leave outer scope");
- }
-
- {
- ns3::ReferenceList<A *> tmp;
- }
-
- {
- ns3::ReferenceList<A *> tmp (new A ());
- }
-
- {
- ns3::ReferenceList<A *> tmp;
- tmp.Set (new A ());
- }
-
- {
- TRACE ("test assignement");
- ns3::ReferenceList<A *> a0 (new A ());
- ns3::ReferenceList<A *> a1 (new A ());
- a0 = a1;
- }
-
-
-
- return ok;
-}
-
-
-static RefTest gRefTest = RefTest ();
-
-}; // namespace
-
-#endif /* RUN_SELF_TESTS */
--- a/src/core/reference-list.h Sat May 19 13:41:50 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 INRIA
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef REFERENCE_LIST_H
-#define REFERENCE_LIST_H
-
-/* This is a reference list implementation. The technique underlying
- * this code was first described in 1995 by Risto Lankinen on Usenet
- * but I have never been able to find his original posting. Instead,
- * this code is based on the description of the technique found in
- * "Modern C++ design" by Andrei Alexandrescu in chapter 7.
- */
-
-
-namespace ns3 {
-
-template <typename OBJ_PTR>
-class ReferenceList;
-
-template <typename OBJ_PTR>
-class ReferenceList {
-public:
- ReferenceList ()
- : m_objPtr (),
- m_prev (),
- m_next ()
- {
- m_prev = this;
- m_next = this;
- }
- ReferenceList (ReferenceList &o)
- : m_objPtr (),
- m_prev (),
- m_next ()
- {
- m_prev = this;
- m_next = this;
- InsertSelfInOther (o);
- }
- ReferenceList (ReferenceList const&o)
- : m_objPtr (),
- m_prev (),
- m_next ()
- {
- m_prev = this;
- m_next = this;
- InsertSelfInOther (o);
- }
- ReferenceList (OBJ_PTR const &objPtr)
- : m_objPtr (objPtr),
- m_prev (),
- m_next ()
- {
- m_prev = this;
- m_next = this;
- }
- ~ReferenceList () {
- RemoveFromList ();
- }
- ReferenceList & operator= (ReferenceList const&o) {
- RemoveFromList ();
- InsertSelfInOther (o);
- return *this;
- }
- OBJ_PTR operator-> () const {
- return m_objPtr;
- }
- void Set (OBJ_PTR objPtr) {
- RemoveFromList ();
- m_objPtr = objPtr;
- }
- OBJ_PTR Get (void) const {
- // explicit conversion to raw pointer type.
- return m_objPtr;
- }
-private:
- void InsertSelfInOther (ReferenceList const&o) {
- m_prev = &o;
- m_next = o.m_next;
- m_next->m_prev = this;
- o.m_next = this;
- m_objPtr = o.m_objPtr;
- }
- void RemoveFromList (void) {
- if (m_prev == this)
- {
- //NS_ASSERT (m_next == this);
- delete m_objPtr;
- m_objPtr = OBJ_PTR ();
- }
- m_prev->m_next = m_next;
- m_next->m_prev = m_prev;
- }
- OBJ_PTR m_objPtr;
- mutable ReferenceList const*m_prev;
- mutable ReferenceList const*m_next;
-};
-
-}; // namespace ns3
-
-#endif /* REFERENCE_LIST_H */
--- a/src/core/rng-stream.h Sat May 19 13:41:50 2007 +0200
+++ b/src/core/rng-stream.h Fri May 25 09:44:18 2007 +0200
@@ -20,6 +20,7 @@
#ifndef RNGSTREAM_H
#define RNGSTREAM_H
#include <string>
+#include <stdint.h>
namespace ns3{
--- a/src/core/win32-system-wall-clock-ms.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/core/win32-system-wall-clock-ms.cc Fri May 25 09:44:18 2007 +0200
@@ -25,8 +25,8 @@
class SystemWallClockMsPrivate {
public:
- void start (void);
- unsigned long long end (void);
+ void Start (void);
+ unsigned long long End (void);
private:
};
--- a/src/core/wscript Sat May 19 13:41:50 2007 +0200
+++ b/src/core/wscript Fri May 25 09:44:18 2007 +0200
@@ -24,7 +24,6 @@
core.name = 'ns3-core'
core.target = core.name
core.source = [
- 'reference-list-test.cc',
'callback-test.cc',
'debug.cc',
'assert.cc',
@@ -53,7 +52,6 @@
headers = bld.create_obj('ns3header')
headers.source = [
'system-wall-clock-ms.h',
- 'reference-list.h',
'callback.h',
'ptr.h',
'object.h',
--- a/src/internet-node/udp-socket.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/internet-node/udp-socket.cc Fri May 25 09:44:18 2007 +0200
@@ -30,7 +30,7 @@
: m_endPoint (0),
m_node (node),
m_udp (udp),
- m_errno (ENOTERROR),
+ m_errno (ERROR_NOTERROR),
m_shutdownSend (false),
m_shutdownRecv (false),
m_connected (false)
@@ -154,7 +154,7 @@
ns3::Callback<void, Ptr<Socket> > closeRequested)
{
// calling accept on a udp socket is a programming error.
- m_errno = EOPNOTSUPP;
+ m_errno = ERROR_OPNOTSUPP;
return -1;
}
int
@@ -164,7 +164,7 @@
{
if (!m_connected)
{
- m_errno = ENOTCONN;
+ m_errno = ERROR_NOTCONN;
return -1;
}
Packet p;
@@ -193,7 +193,7 @@
}
if (m_shutdownSend)
{
- m_errno = ESHUTDOWN;
+ m_errno = ERROR_SHUTDOWN;
return -1;
}
m_udp->Send (p, m_endPoint->GetLocalAddress (), daddr,
@@ -213,7 +213,7 @@
{
if (m_connected)
{
- m_errno = EISCONN;
+ m_errno = ERROR_ISCONN;
return -1;
}
Packet p;
--- a/src/node/socket.h Sat May 19 13:41:50 2007 +0200
+++ b/src/node/socket.h Fri May 25 09:44:18 2007 +0200
@@ -46,13 +46,13 @@
virtual ~Socket();
enum SocketErrno {
- ENOTERROR,
- EISCONN,
- ENOTCONN,
- EMSGSIZE,
- EAGAIN,
- ESHUTDOWN,
- EOPNOTSUPP,
+ ERROR_NOTERROR,
+ ERROR_ISCONN,
+ ERROR_NOTCONN,
+ ERROR_MSGSIZE,
+ ERROR_AGAIN,
+ ERROR_SHUTDOWN,
+ ERROR_OPNOTSUPP,
SOCKET_ERRNO_LAST
};
--- a/src/simulator/event-id.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/event-id.cc Fri May 25 09:44:18 2007 +0200
@@ -26,13 +26,13 @@
EventId::EventId ()
: m_eventImpl (0),
- m_ns (0),
+ m_ts (0),
m_uid (0)
{}
-EventId::EventId (EventImpl *impl, uint64_t ns, uint32_t uid)
+EventId::EventId (EventImpl *impl, uint64_t ts, uint32_t uid)
: m_eventImpl (impl),
- m_ns (ns),
+ m_ts (ts),
m_uid (uid)
{}
void
@@ -60,9 +60,9 @@
return m_eventImpl;
}
uint64_t
-EventId::GetNs (void) const
+EventId::GetTs (void) const
{
- return m_ns;
+ return m_ts;
}
uint32_t
EventId::GetUid (void) const
--- a/src/simulator/event-id.h Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/event-id.h Fri May 25 09:44:18 2007 +0200
@@ -33,7 +33,7 @@
class EventId {
public:
EventId ();
- EventId (EventImpl *impl, uint64_t ns, uint32_t uid);
+ EventId (EventImpl *impl, uint64_t ts, uint32_t uid);
/**
* This method is syntactic sugar for the ns3::Simulator::cancel
* method.
@@ -52,11 +52,11 @@
* subclasses of the Scheduler base class.
*/
EventImpl *GetEventImpl (void) const;
- uint64_t GetNs (void) const;
+ uint64_t GetTs (void) const;
uint32_t GetUid (void) const;
private:
EventImpl *m_eventImpl;
- uint64_t m_ns;
+ uint64_t m_ts;
uint32_t m_uid;
};
--- a/src/simulator/nstime.h Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/nstime.h Fri May 25 09:44:18 2007 +0200
@@ -22,12 +22,42 @@
#define TIME_H
#include <stdint.h>
+#include <math.h>
#include "ns3/assert.h"
#include <ostream>
#include "high-precision.h"
+#include "cairo-wideint-private.h"
namespace ns3 {
+namespace TimeStepPrecision {
+
+enum precision_t {
+ S = 0,
+ MS = 3,
+ US = 6,
+ NS = 9,
+ PS = 12,
+ FS = 15
+};
+/**
+ * \param precision the new precision to use
+ *
+ * This should be invoked before any Time object
+ * is created. i.e., it should be invoked at the very start
+ * of every simulation. The unit specified by this method
+ * is used as the unit of the internal simulation time
+ * which is stored as a 64 bit integer.
+ */
+void Set (precision_t precision);
+/**
+ * \returns the currently-used time precision.
+ */
+precision_t Get (void);
+
+} // namespace TimeStepPrecision
+
+
/**
* \brief keep track of time unit.
*
@@ -235,6 +265,9 @@
{
HighPrecision retval = lhs.GetHighPrecision ();
retval.Mul (rhs.GetHighPrecision ());
+ // std::cout << lhs.GetHighPrecision().GetInteger() << " * "
+ // << rhs.GetHighPrecision().GetInteger()
+ // << " = " << retval.GetInteger() << std::endl;
return TimeUnit<N1+N2> (retval);
}
template <int N1, int N2>
@@ -316,6 +349,8 @@
* - 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
@@ -328,11 +363,12 @@
* instance.
*/
double GetSeconds (void) const;
+
/**
* \returns an approximation in milliseconds of the time stored in this
* instance.
- */
- int32_t GetMilliSeconds (void) const;
+ */
+ int64_t GetMilliSeconds (void) const;
/**
* \returns an approximation in microseconds of the time stored in this
* instance.
@@ -343,6 +379,21 @@
* instance.
*/
int64_t GetNanoSeconds (void) const;
+ /**
+ * \returns an approximation in picoseconds of the time stored in this
+ * instance.
+ */
+ int64_t GetPicoSeconds (void) const;
+ /**
+ * \returns an approximation in femtoseconds of the time stored in this
+ * instance.
+ */
+ int64_t GetFemtoSeconds (void) const;
+ /**
+ * \returns an approximation of the time stored in this
+ * instance in the units specified in m_tsPrecision.
+ */
+ int64_t GetTimeStep (void) const;
// -*- The rest is the the same as in the generic template class -*-
public:
@@ -378,8 +429,18 @@
HighPrecision *PeekHighPrecision (void) {
return &m_data;
}
+
+ static uint64_t UnitsToTimestep (uint64_t unitValue,
+ uint64_t unitFactor);
private:
HighPrecision m_data;
+
+ /*
+ * \Returns the value of time_value in units of unitPrec. time_value
+ * must be specified in timestep units (which are the same as the
+ * m_tsPrecision units
+ */
+ int64_t ConvertToUnits (int64_t timeValue, uint64_t unitFactor) const;
};
/**
@@ -387,13 +448,17 @@
*
* This is an instance of type ns3::TimeUnit<1>: it is
* the return value of the ns3::Simulator::Now method
- * and is needed for the Simulator::Schedule methods
+ * and is needed for the Simulator::Schedule methods.
+ * The precision of the underlying Time unit can be
+ * changed with calls to TimeStepPrecision::Set.
*
- * Time instances can be created through any of the following classes:
+ * Time instances can be created through any of the following functions:
* - ns3::Seconds
* - ns3::MilliSeconds
* - ns3::MicroSeconds
* - ns3::NanoSeconds
+ * - ns3::PicoSeconds
+ * - ns3::FemtoSeconds
* - ns3::Now
*
* Time instances can be added, substracted, multipled and divided using
@@ -417,7 +482,7 @@
* instance.
*
* \code
- * int32_t GetMilliSeconds (void) const;
+ * int64_t GetMilliSeconds (void) const;
* \endcode
* returns an approximation in milliseconds of the time stored in this
* instance.
@@ -433,6 +498,18 @@
* \endcode
* returns an approximation in nanoseconds of the time stored in this
* instance.
+ *
+ * \code
+ * int64_t GetPicoSeconds (void) const;
+ * \endcode
+ * returns an approximation in picoseconds of the time stored in this
+ * instance.
+ *
+ * \code
+ * int64_t GetFemtoSeconds (void) const;
+ * \endcode
+ * returns an approximation in femtoseconds of the time stored in this
+ * instance.
*/
typedef TimeUnit<1> Time;
@@ -459,7 +536,7 @@
* Simulator::Schedule (MilliSeconds (5), ...);
* \endcode
*/
-Time MilliSeconds (uint32_t ms);
+Time MilliSeconds (uint64_t ms);
/**
* \brief create ns3::Time instances in units of microseconds.
*
@@ -480,20 +557,29 @@
* \endcode
*/
Time NanoSeconds (uint64_t ns);
-
/**
- * \brief create an ns3::Time instance which contains the
- * current simulation time.
+ * \brief create ns3::Time instances in units of picoseconds.
*
- * This is really a shortcut for the ns3::Simulator::Now method.
- * It is typically used as shown below to schedule an event
- * which expires at the absolute time "2 seconds":
+ * For example:
* \code
- * Simulator::Schedule (Seconds (2.0) - Now (), &my_function);
+ * Time t = PicoSeconds (2);
+ * Simulator::Schedule (PicoSeconds (5), ...);
* \endcode
*/
-Time Now (void);
+Time PicoSeconds (uint64_t ps);
+/**
+ * \brief create ns3::Time instances in units of femtoseconds.
+ *
+ * For example:
+ * \code
+ * Time t = FemtoSeconds (2);
+ * Simulator::Schedule (FemtoSeconds (5), ...);
+ * \endcode
+ */
+Time FemtoSeconds (uint64_t fs);
+// internal function not publicly documented
+Time TimeStep (uint64_t ts);
// Explicit instatiation of the TimeUnit template for N=0, with a few
// additional methods that should not be available for N != 0
@@ -539,6 +625,7 @@
HighPrecision *PeekHighPrecision (void) {
return &m_data;
}
+
private:
HighPrecision m_data;
};
--- a/src/simulator/scheduler-factory.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/scheduler-factory.cc Fri May 25 09:44:18 2007 +0200
@@ -88,7 +88,7 @@
StringEnumDefaultValue *
SchedulerFactory::GetDefault (void)
{
- static StringEnumDefaultValue value ("scheduler", "Event Scheduler algorithm");
+ static StringEnumDefaultValue value ("Scheduler", "Event Scheduler algorithm");
return &value;
}
--- a/src/simulator/scheduler-heap.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/scheduler-heap.cc Fri May 25 09:44:18 2007 +0200
@@ -139,11 +139,11 @@
bool
SchedulerHeap::IsLowerStrictly (Scheduler::EventKey const*a, Scheduler::EventKey const*b) const
{
- if (a->m_ns < b->m_ns)
+ if (a->m_ts < b->m_ts)
{
return true;
}
- else if (a->m_ns > b->m_ns)
+ else if (a->m_ts > b->m_ts)
{
return false;
}
@@ -227,7 +227,7 @@
{
m_heap.push_back (std::make_pair (event, key));
BottomUp ();
- return EventId (event, key.m_ns, key.m_uid);
+ return EventId (event, key.m_ts, key.m_uid);
}
EventImpl *
@@ -252,7 +252,7 @@
EventImpl *
SchedulerHeap::RealRemove (EventId id, Scheduler::EventKey *key)
{
- key->m_ns = id.GetNs ();
+ key->m_ts = id.GetTs ();
key->m_uid = id.GetUid ();
for (uint32_t i = 1; i < m_heap.size (); i++)
{
--- a/src/simulator/scheduler-list.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/scheduler-list.cc Fri May 25 09:44:18 2007 +0200
@@ -33,7 +33,7 @@
public:
SchedulerListFactory ()
{
- SchedulerFactory::AddDefault (this, "list");
+ SchedulerFactory::AddDefault (this, "List");
}
private:
virtual Scheduler *DoCreate (void) const
@@ -51,11 +51,11 @@
bool
SchedulerList::IsLower (Scheduler::EventKey const*a, Scheduler::EventKey const*b) const
{
- if (a->m_ns < b->m_ns)
+ if (a->m_ts < b->m_ts)
{
return true;
}
- else if (a->m_ns == b->m_ns &&
+ else if (a->m_ts == b->m_ts &&
a->m_uid < b->m_uid)
{
return true;
@@ -74,11 +74,11 @@
if (IsLower (&key, &i->second))
{
m_events.insert (i, std::make_pair (event, key));
- return EventId (event, key.m_ns, key.m_uid);
+ return EventId (event, key.m_ts, key.m_uid);
}
}
m_events.push_back (std::make_pair (event, key));
- return EventId (event, key.m_ns, key.m_uid);
+ return EventId (event, key.m_ts, key.m_uid);
}
bool
SchedulerList::RealIsEmpty (void) const
@@ -111,7 +111,7 @@
{
EventImpl *retval = i->first;
NS_ASSERT (id.GetEventImpl () == retval);
- key->m_ns = id.GetNs ();
+ key->m_ts = id.GetTs ();
key->m_uid = id.GetUid ();
m_events.erase (i);
return retval;
--- a/src/simulator/scheduler-map.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/scheduler-map.cc Fri May 25 09:44:18 2007 +0200
@@ -44,7 +44,7 @@
public:
SchedulerMapFactory ()
{
- SchedulerFactory::Add (this, "map");
+ SchedulerFactory::Add (this, "Map");
}
private:
virtual Scheduler *DoCreate (void) const
@@ -67,11 +67,11 @@
bool
SchedulerMap::EventKeyCompare::operator () (struct EventKey const&a, struct EventKey const&b)
{
- if (a.m_ns < b.m_ns)
+ if (a.m_ts < b.m_ts)
{
return true;
}
- else if (a.m_ns > b.m_ns)
+ else if (a.m_ts > b.m_ts)
{
return false;
}
@@ -93,7 +93,7 @@
std::pair<EventMapI,bool> result;
result = m_list.insert (std::make_pair (key, event));
NS_ASSERT (result.second);
- return EventId (event, key.m_ns, key.m_uid);
+ return EventId (event, key.m_ts, key.m_uid);
}
bool
@@ -125,7 +125,7 @@
EventImpl *
SchedulerMap::RealRemove (EventId id, Scheduler::EventKey *key)
{
- key->m_ns = id.GetNs ();
+ key->m_ts = id.GetTs ();
key->m_uid = id.GetUid ();
EventMapI i = m_list.find (*key);
EventImpl *retval = i->second;
--- a/src/simulator/scheduler.h Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/scheduler.h Fri May 25 09:44:18 2007 +0200
@@ -55,7 +55,7 @@
class Scheduler {
public:
struct EventKey {
- uint64_t m_ns;
+ uint64_t m_ts;
uint32_t m_uid;
};
--- a/src/simulator/simulator.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/simulator.cc Fri May 25 09:44:18 2007 +0200
@@ -72,7 +72,7 @@
private:
void ProcessOneEvent (void);
- uint64_t NextNs (void) const;
+ uint64_t NextTs (void) const;
typedef std::list<std::pair<EventImpl *,uint32_t> > Events;
Events m_destroy;
@@ -81,7 +81,7 @@
Scheduler *m_events;
uint32_t m_uid;
uint32_t m_currentUid;
- uint64_t m_currentNs;
+ uint64_t m_currentTs;
std::ofstream m_log;
std::ifstream m_inputLog;
bool m_logEnable;
@@ -103,7 +103,7 @@
// before ::Run is entered, the m_currentUid will be zero
m_currentUid = 0;
m_logEnable = false;
- m_currentNs = 0;
+ m_currentTs = 0;
m_unscheduledEvents = 0;
}
@@ -136,15 +136,15 @@
Scheduler::EventKey nextKey = m_events->PeekNextKey ();
m_events->RemoveNext ();
- NS_ASSERT (nextKey.m_ns >= m_currentNs);
+ NS_ASSERT (nextKey.m_ts >= m_currentTs);
--m_unscheduledEvents;
TRACE ("handle " << nextEv);
- m_currentNs = nextKey.m_ns;
+ m_currentTs = nextKey.m_ts;
m_currentUid = nextKey.m_uid;
if (m_logEnable)
{
- m_log << "e "<<nextKey.m_uid << " " << nextKey.m_ns << std::endl;
+ m_log << "e "<<nextKey.m_uid << " " << nextKey.m_ts << std::endl;
}
nextEv->Invoke ();
delete nextEv;
@@ -156,25 +156,24 @@
return m_events->IsEmpty ();
}
uint64_t
-SimulatorPrivate::NextNs (void) const
+SimulatorPrivate::NextTs (void) const
{
NS_ASSERT (!m_events->IsEmpty ());
Scheduler::EventKey nextKey = m_events->PeekNextKey ();
- return nextKey.m_ns;
+ return nextKey.m_ts;
}
Time
SimulatorPrivate::Next (void) const
{
- return NanoSeconds (NextNs ());
+ return TimeStep (NextTs ());
}
-
void
SimulatorPrivate::Run (void)
{
while (!m_events->IsEmpty () && !m_stop &&
- (m_stopAt == 0 || m_stopAt > NextNs ()))
+ (m_stopAt == 0 || m_stopAt > NextTs ()))
{
ProcessOneEvent ();
}
@@ -196,19 +195,19 @@
SimulatorPrivate::StopAt (Time const &at)
{
NS_ASSERT (at.IsPositive ());
- m_stopAt = at.GetNanoSeconds ();
+ m_stopAt = at.GetTimeStep ();
}
EventId
SimulatorPrivate::Schedule (Time const &time, EventImpl *event)
{
NS_ASSERT (time.IsPositive ());
- NS_ASSERT (time >= NanoSeconds (m_currentNs));
- uint64_t ns = (uint64_t) time.GetNanoSeconds ();
- Scheduler::EventKey key = {ns, m_uid};
+ NS_ASSERT (time >= TimeStep (m_currentTs));
+ uint64_t ts = (uint64_t) time.GetTimeStep ();
+ Scheduler::EventKey key = {ts, m_uid};
if (m_logEnable)
{
- m_log << "i "<<m_currentUid<<" "<<m_currentNs<<" "
- <<m_uid<<" "<<time.GetNanoSeconds () << std::endl;
+ m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
+ <<m_uid<<" "<<time.GetTimeStep () << std::endl;
}
m_uid++;
++m_unscheduledEvents;
@@ -217,12 +216,12 @@
void
SimulatorPrivate::ScheduleNow (EventImpl *event)
{
- uint64_t ns = m_currentNs;
- Scheduler::EventKey key = {ns, m_uid};
+ uint64_t ts = m_currentTs;
+ Scheduler::EventKey key = {ts, m_uid};
if (m_logEnable)
{
- m_log << "i "<<m_currentUid<<" "<<m_currentNs<<" "
- <<m_uid<<" "<<ns << std::endl;
+ m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
+ <<m_uid<<" "<<ts << std::endl;
}
m_uid++;
++m_unscheduledEvents;
@@ -234,7 +233,7 @@
m_destroy.push_back (std::make_pair (event, m_uid));
if (m_logEnable)
{
- m_log << "id " << m_currentUid << " " << Now ().GetNanoSeconds () << " "
+ m_log << "id " << m_currentUid << " " << Now ().GetTimeStep () << " "
<< m_uid << std::endl;
}
m_uid++;
@@ -243,7 +242,7 @@
Time
SimulatorPrivate::Now (void) const
{
- return NanoSeconds (m_currentNs);
+ return TimeStep (m_currentTs);
}
void
@@ -254,8 +253,8 @@
delete impl;
if (m_logEnable)
{
- m_log << "r " << m_currentUid << " " << m_currentNs << " "
- << key.m_uid << " " << key.m_ns << std::endl;
+ m_log << "r " << m_currentUid << " " << m_currentTs << " "
+ << key.m_uid << " " << key.m_ts << std::endl;
}
--m_unscheduledEvents;
}
@@ -270,8 +269,8 @@
SimulatorPrivate::IsExpired (EventId ev)
{
if (ev.GetEventImpl () == 0 ||
- ev.GetNs () < m_currentNs ||
- (ev.GetNs () == m_currentNs &&
+ ev.GetTs () < m_currentTs ||
+ (ev.GetTs () == m_currentTs &&
ev.GetUid () <= m_currentUid) ||
ev.GetEventImpl ()->IsCancelled ())
{
@@ -299,20 +298,20 @@
void Simulator::SetLinkedList (void)
{
- Bind ("scheduler", "list");
+ Bind ("Scheduler", "List");
}
void Simulator::SetBinaryHeap (void)
{
- Bind ("scheduler", "BinaryHeap");
+ Bind ("Scheduler", "BinaryHeap");
}
void Simulator::SetStdMap (void)
{
- Bind ("scheduler", "map");
+ Bind ("Scheduler", "Map");
}
void
Simulator::SetExternal (const std::string &external)
{
- Bind ("scheduler", external);
+ Bind ("Scheduler", external);
}
void Simulator::EnableLogTo (char const *filename)
{
@@ -444,12 +443,18 @@
return GetPriv ()->IsExpired (id);
}
+Time Now (void)
+{
+ return Time (Simulator::Now ());
+}
+
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
+#include "ns3/ptr.h"
namespace ns3 {
@@ -470,6 +475,9 @@
class SimulatorTests : public Test {
public:
SimulatorTests ();
+ // only here for testing of Ptr<>
+ void Ref (void);
+ void Unref (void);
virtual ~SimulatorTests ();
virtual bool RunTests (void);
private:
@@ -498,6 +506,12 @@
{}
SimulatorTests::~SimulatorTests ()
{}
+void
+SimulatorTests::Ref (void)
+{}
+void
+SimulatorTests::Unref (void)
+{}
uint64_t
SimulatorTests::NowUs (void)
{
@@ -630,6 +644,12 @@
Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar3, this, 0, 0, 0);
Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar4, this, 0, 0, 0, 0);
Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar5, this, 0, 0, 0, 0, 0);
+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar0, Ptr<SimulatorTests> (this));
+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar1, Ptr<SimulatorTests> (this), 0);
+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar2, Ptr<SimulatorTests> (this), 0, 0);
+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar3, Ptr<SimulatorTests> (this), 0, 0, 0);
+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar4, Ptr<SimulatorTests> (this), 0, 0, 0, 0);
+ Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar5, Ptr<SimulatorTests> (this), 0, 0, 0, 0, 0);
Simulator::ScheduleNow (&foo0);
Simulator::ScheduleNow (&foo1, 0);
Simulator::ScheduleNow (&foo2, 0, 0);
@@ -642,6 +662,12 @@
Simulator::ScheduleNow (&SimulatorTests::bar3, this, 0, 0, 0);
Simulator::ScheduleNow (&SimulatorTests::bar4, this, 0, 0, 0, 0);
Simulator::ScheduleNow (&SimulatorTests::bar5, this, 0, 0, 0, 0, 0);
+ Simulator::ScheduleNow (&SimulatorTests::bar0, Ptr<SimulatorTests> (this));
+ Simulator::ScheduleNow (&SimulatorTests::bar1, Ptr<SimulatorTests> (this), 0);
+ Simulator::ScheduleNow (&SimulatorTests::bar2, Ptr<SimulatorTests> (this), 0, 0);
+ Simulator::ScheduleNow (&SimulatorTests::bar3, Ptr<SimulatorTests> (this), 0, 0, 0);
+ Simulator::ScheduleNow (&SimulatorTests::bar4, Ptr<SimulatorTests> (this), 0, 0, 0, 0);
+ Simulator::ScheduleNow (&SimulatorTests::bar5, Ptr<SimulatorTests> (this), 0, 0, 0, 0, 0);
Simulator::ScheduleDestroy (&foo0);
Simulator::ScheduleDestroy (&foo1, 0);
Simulator::ScheduleDestroy (&foo2, 0, 0);
@@ -654,6 +680,12 @@
Simulator::ScheduleDestroy (&SimulatorTests::bar3, this, 0, 0, 0);
Simulator::ScheduleDestroy (&SimulatorTests::bar4, this, 0, 0, 0, 0);
Simulator::ScheduleDestroy (&SimulatorTests::bar5, this, 0, 0, 0, 0, 0);
+ Simulator::ScheduleDestroy (&SimulatorTests::bar0, Ptr<SimulatorTests> (this));
+ Simulator::ScheduleDestroy (&SimulatorTests::bar1, Ptr<SimulatorTests> (this), 0);
+ Simulator::ScheduleDestroy (&SimulatorTests::bar2, Ptr<SimulatorTests> (this), 0, 0);
+ Simulator::ScheduleDestroy (&SimulatorTests::bar3, Ptr<SimulatorTests> (this), 0, 0, 0);
+ Simulator::ScheduleDestroy (&SimulatorTests::bar4, Ptr<SimulatorTests> (this), 0, 0, 0, 0);
+ Simulator::ScheduleDestroy (&SimulatorTests::bar5, Ptr<SimulatorTests> (this), 0, 0, 0, 0, 0);
Simulator::Run ();
Simulator::Destroy ();
--- a/src/simulator/simulator.h Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/simulator.h Fri May 25 09:44:18 2007 +0200
@@ -37,11 +37,13 @@
* \brief Control the scheduling of simulation events.
*
* The internal simulation clock is maintained
- * as a 64-bit integer in nanosecond units. This means that it is
+ * as a 64-bit integer in a unit specified by the user
+ * through the TimeStepPrecision::Set function. This means that it is
* not possible to specify event expiration times with anything better
- * than nanosecond accuracy. Events whose expiration time is
- * the same are scheduled in FIFO order: the first event inserted in the
- * Scheduling queue is scheduled to expire first.
+ * than this user-specified accuracy. Events whose expiration time is
+ * the same modulo this accuracy are scheduled in FIFO order: the
+ * first event inserted in the scheduling queue is scheduled to
+ * expire first.
*
* A simple example of how to use the Simulator class to schedule events
* is shown below:
@@ -160,8 +162,8 @@
* @param obj the object on which to invoke the member method
* @returns an id for the scheduled event.
*/
- template <typename T>
- static EventId Schedule (Time const &time, void (T::*mem_ptr) (void), T *obj);
+ template <typename T, typename OBJ>
+ static EventId Schedule (Time const &time, void (T::*mem_ptr) (void), OBJ obj);
/**
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
@@ -169,8 +171,8 @@
* @param a1 the first argument to pass to the invoked method
* @returns an id for the scheduled event.
*/
- template <typename T, typename T1>
- static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), T* obj, T1 a1);
+ template <typename T, typename OBJ, typename T1>
+ static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
/**
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
@@ -179,8 +181,8 @@
* @param a2 the second argument to pass to the invoked method
* @returns an id for the scheduled event.
*/
- template <typename T, typename T1, typename T2>
- static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2);
+ template <typename T, typename OBJ, typename T1, typename T2>
+ static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
/**
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
@@ -190,8 +192,8 @@
* @param a3 the third argument to pass to the invoked method
* @returns an id for the scheduled event.
*/
- template <typename T, typename T1, typename T2, typename T3>
- static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3>
+ static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
/**
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
@@ -202,8 +204,8 @@
* @param a4 the fourth argument to pass to the invoked method
* @returns an id for the scheduled event.
*/
- template <typename T, typename T1, typename T2, typename T3, typename T4>
- static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
+ static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
/**
* @param time the relative expiration time of the event.
* @param mem_ptr member method pointer to invoke
@@ -215,9 +217,9 @@
* @param a5 the fifth argument to pass to the invoked method
* @returns an id for the scheduled event.
*/
- template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
- static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
+ static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
/**
* @param time the relative expiration time of the event.
* @param f the function to invoke
@@ -284,23 +286,23 @@
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
*/
- template <typename T>
- static void ScheduleNow (void (T::*mem_ptr) (void), T *obj);
+ template <typename T, typename OBJ>
+ static void ScheduleNow (void (T::*mem_ptr) (void), OBJ obj);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
*/
- template <typename T, typename T1>
- static void ScheduleNow (void (T::*mem_ptr) (T1), T* obj, T1 a1);
+ template <typename T, typename OBJ, typename T1>
+ static void ScheduleNow (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
* @param a2 the second argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2>
- static void ScheduleNow (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2);
+ template <typename T, typename OBJ, typename T1, typename T2>
+ static void ScheduleNow (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
@@ -308,8 +310,8 @@
* @param a2 the second argument to pass to the invoked method
* @param a3 the third argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2, typename T3>
- static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3>
+ static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
@@ -318,8 +320,8 @@
* @param a3 the third argument to pass to the invoked method
* @param a4 the fourth argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2, typename T3, typename T4>
- static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj,
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
+ static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj,
T1 a1, T2 a2, T3 a3, T4 a4);
/**
* @param mem_ptr member method pointer to invoke
@@ -330,8 +332,8 @@
* @param a4 the fourth argument to pass to the invoked method
* @param a5 the fifth argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
- static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
+ static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
/**
* @param f the function to invoke
@@ -388,23 +390,23 @@
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
*/
- template <typename T>
- static void ScheduleDestroy (void (T::*mem_ptr) (void), T *obj);
+ template <typename T, typename OBJ>
+ static void ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
*/
- template <typename T, typename T1>
- static void ScheduleDestroy (void (T::*mem_ptr) (T1), T* obj, T1 a1);
+ template <typename T, typename OBJ, typename T1>
+ static void ScheduleDestroy (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
* @param a1 the first argument to pass to the invoked method
* @param a2 the second argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2>
- static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2);
+ template <typename T, typename OBJ, typename T1, typename T2>
+ static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
@@ -412,8 +414,8 @@
* @param a2 the second argument to pass to the invoked method
* @param a3 the third argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2, typename T3>
- static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3>
+ static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
@@ -422,9 +424,9 @@
* @param a3 the third argument to pass to the invoked method
* @param a4 the fourth argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2, typename T3, typename T4>
- static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
+ static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4);
/**
* @param mem_ptr member method pointer to invoke
* @param obj the object on which to invoke the member method
@@ -434,9 +436,9 @@
* @param a4 the fourth argument to pass to the invoked method
* @param a5 the fifth argument to pass to the invoked method
*/
- template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
- static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
+ static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
/**
* @param f the function to invoke
*/
@@ -527,19 +529,19 @@
private:
Simulator ();
~Simulator ();
- template <typename T>
- static EventImpl *MakeEvent (void (T::*mem_ptr) (void), T *obj);
- template <typename T, typename T1>
- static EventImpl *MakeEvent (void (T::*mem_ptr) (T1), T* obj, T1 a1);
- template <typename T, typename T1, typename T2>
- static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2);
- template <typename T, typename T1, typename T2, typename T3>
- static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3);
- template <typename T, typename T1, typename T2, typename T3, typename T4>
- static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4);
- template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
- static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+ template <typename T, typename OBJ>
+ static EventImpl *MakeEvent (void (T::*mem_ptr) (void), OBJ obj);
+ template <typename T, typename OBJ, typename T1>
+ static EventImpl *MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
+ template <typename T, typename OBJ, typename T1, typename T2>
+ static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3>
+ static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
+ static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
+ template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
+ static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
static EventImpl *MakeEvent (void (*f) (void));
template <typename T1>
static EventImpl *MakeEvent (void (*f) (T1), T1 a1);
@@ -559,6 +561,19 @@
static SimulatorPrivate *m_priv;
};
+/**
+ * \brief create an ns3::Time instance which contains the
+ * current simulation time.
+ *
+ * This is really a shortcut for the ns3::Simulator::Now method.
+ * It is typically used as shown below to schedule an event
+ * which expires at the absolute time "2 seconds":
+ * \code
+ * Simulator::Schedule (Seconds (2.0) - Now (), &my_function);
+ * \endcode
+ */
+Time Now (void);
+
}; // namespace ns3
@@ -569,174 +584,185 @@
namespace ns3 {
template <typename T>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (void), T *obj)
+struct EventMemberImplTraits;
+
+template <typename T>
+struct EventMemberImplTraits<T *>
+{
+ static T &GetReference (T *p) {
+ return *p;
+ }
+};
+
+template <typename T, typename OBJ>
+EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (void), OBJ obj)
{
// zero argument version
class EventMemberImpl0 : public EventImpl {
public:
- typedef void (T::*F)(void);
- EventMemberImpl0 (T *obj, F function)
- : m_obj (obj),
- m_function (function)
- {}
- virtual ~EventMemberImpl0 () {}
+ typedef void (T::*F)(void);
+ EventMemberImpl0 (OBJ obj, F function)
+ : m_obj (obj),
+ m_function (function)
+ {}
+ virtual ~EventMemberImpl0 () {}
private:
- virtual void Notify (void) {
- (m_obj->*m_function) ();
- }
- T* m_obj;
- F m_function;
+ virtual void Notify (void) {
+ (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) ();
+ }
+ OBJ m_obj;
+ F m_function;
} *ev = new EventMemberImpl0 (obj, mem_ptr);
return ev;
}
-template <typename T, typename T1>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1), T* obj, T1 a1)
+template <typename T, typename OBJ, typename T1>
+EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1)
{
// one argument version
class EventMemberImpl1 : public EventImpl {
public:
- typedef void (T::*F)(T1);
- EventMemberImpl1 (T *obj, F function, T1 a1)
- : m_obj (obj),
- m_function (function),
- m_a1 (a1)
- {}
+ typedef void (T::*F)(T1);
+ EventMemberImpl1 (OBJ obj, F function, T1 a1)
+ : m_obj (obj),
+ m_function (function),
+ m_a1 (a1)
+ {}
protected:
- virtual ~EventMemberImpl1 () {}
+ virtual ~EventMemberImpl1 () {}
private:
- virtual void Notify (void) {
- (m_obj->*m_function) (m_a1);
- }
- T* m_obj;
- F m_function;
- T1 m_a1;
+ virtual void Notify (void) {
+ (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1);
+ }
+ OBJ m_obj;
+ F m_function;
+ T1 m_a1;
} *ev = new EventMemberImpl1 (obj, mem_ptr, a1);
return ev;
}
-template <typename T, typename T1, typename T2>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2)
+template <typename T, typename OBJ, typename T1, typename T2>
+EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2)
{
// two argument version
class EventMemberImpl2 : public EventImpl {
public:
- typedef void (T::*F)(T1, T2);
+ typedef void (T::*F)(T1, T2);
- EventMemberImpl2 (T *obj, F function, T1 a1, T2 a2)
- : m_obj (obj),
- m_function (function),
- m_a1 (a1),
- m_a2 (a2)
- { }
+ EventMemberImpl2 (OBJ obj, F function, T1 a1, T2 a2)
+ : m_obj (obj),
+ m_function (function),
+ m_a1 (a1),
+ m_a2 (a2)
+ { }
protected:
- virtual ~EventMemberImpl2 () {}
+ virtual ~EventMemberImpl2 () {}
private:
- virtual void Notify (void) {
- (m_obj->*m_function) (m_a1, m_a2);
- }
- T* m_obj;
- F m_function;
- T1 m_a1;
- T2 m_a2;
+ virtual void Notify (void) {
+ (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2);
+ }
+ OBJ m_obj;
+ F m_function;
+ T1 m_a1;
+ T2 m_a2;
} *ev = new EventMemberImpl2 (obj, mem_ptr, a1, a2);
return ev;
}
-template <typename T, typename T1, typename T2, typename T3>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3)
+template <typename T, typename OBJ, typename T1, typename T2, typename T3>
+EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3)
{
// three argument version
class EventMemberImpl3 : public EventImpl {
public:
- typedef void (T::*F)(T1, T2, T3);
+ typedef void (T::*F)(T1, T2, T3);
- EventMemberImpl3 (T *obj, F function, T1 a1, T2 a2, T3 a3)
- : m_obj (obj),
- m_function (function),
- m_a1 (a1),
- m_a2 (a2),
- m_a3 (a3)
- { }
+ EventMemberImpl3 (OBJ obj, F function, T1 a1, T2 a2, T3 a3)
+ : m_obj (obj),
+ m_function (function),
+ m_a1 (a1),
+ m_a2 (a2),
+ m_a3 (a3)
+ { }
protected:
- virtual ~EventMemberImpl3 () {}
+ virtual ~EventMemberImpl3 () {}
private:
- virtual void Notify (void) {
- (m_obj->*m_function) (m_a1, m_a2, m_a3);
- }
- T* m_obj;
- F m_function;
- T1 m_a1;
- T2 m_a2;
- T3 m_a3;
+ virtual void Notify (void) {
+ (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3);
+ }
+ OBJ m_obj;
+ F m_function;
+ T1 m_a1;
+ T2 m_a2;
+ T3 m_a3;
} *ev = new EventMemberImpl3 (obj, mem_ptr, a1, a2, a3);
return ev;
}
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4)
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
+EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4)
{
// four argument version
class EventMemberImpl4 : public EventImpl {
public:
- typedef void (T::*F)(T1, T2, T3, T4);
+ typedef void (T::*F)(T1, T2, T3, T4);
- EventMemberImpl4 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4)
- : m_obj (obj),
- m_function (function),
- m_a1 (a1),
- m_a2 (a2),
- m_a3 (a3),
- m_a4 (a4)
- { }
+ EventMemberImpl4 (OBJ obj, F function, T1 a1, T2 a2, T3 a3, T4 a4)
+ : m_obj (obj),
+ m_function (function),
+ m_a1 (a1),
+ m_a2 (a2),
+ m_a3 (a3),
+ m_a4 (a4)
+ { }
protected:
- virtual ~EventMemberImpl4 () {}
+ virtual ~EventMemberImpl4 () {}
private:
- virtual void Notify (void) {
- (m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4);
- }
- T* m_obj;
- F m_function;
- T1 m_a1;
- T2 m_a2;
- T3 m_a3;
- T4 m_a4;
+ virtual void Notify (void) {
+ (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4);
+ }
+ OBJ m_obj;
+ F m_function;
+ T1 m_a1;
+ T2 m_a2;
+ T3 m_a3;
+ T4 m_a4;
} *ev = new EventMemberImpl4 (obj, mem_ptr, a1, a2, a3, a4);
return ev;
}
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
+EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
// five argument version
class EventMemberImpl5 : public EventImpl {
public:
- typedef void (T::*F)(T1, T2, T3, T4, T5);
+ typedef void (T::*F)(T1, T2, T3, T4, T5);
- EventMemberImpl5 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
- : m_obj (obj),
- m_function (function),
- m_a1 (a1),
- m_a2 (a2),
- m_a3 (a3),
- m_a4 (a4),
- m_a5 (a5)
- { }
+ EventMemberImpl5 (OBJ obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+ : m_obj (obj),
+ m_function (function),
+ m_a1 (a1),
+ m_a2 (a2),
+ m_a3 (a3),
+ m_a4 (a4),
+ m_a5 (a5)
+ { }
protected:
- virtual ~EventMemberImpl5 () {}
+ virtual ~EventMemberImpl5 () {}
private:
- virtual void Notify (void) {
- (m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
- }
- T* m_obj;
- F m_function;
- T1 m_a1;
- T2 m_a2;
- T3 m_a3;
- T4 m_a4;
- T5 m_a5;
+ virtual void Notify (void) {
+ (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
+ }
+ OBJ m_obj;
+ F m_function;
+ T1 m_a1;
+ T2 m_a2;
+ T3 m_a3;
+ T4 m_a4;
+ T5 m_a5;
} *ev = new EventMemberImpl5 (obj, mem_ptr, a1, a2, a3, a4, a5);
return ev;
}
@@ -881,39 +907,39 @@
return ev;
}
-template <typename T>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (void), T *obj)
+template <typename T, typename OBJ>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (void), OBJ obj)
{
return Schedule (time, MakeEvent (mem_ptr, obj));
}
-template <typename T, typename T1>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1), T* obj, T1 a1)
+template <typename T, typename OBJ, typename T1>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj, T1 a1)
{
return Schedule (time, MakeEvent (mem_ptr, obj, a1));
}
-template <typename T, typename T1, typename T2>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2)
+template <typename T, typename OBJ, typename T1, typename T2>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2)
{
return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2));
}
-template <typename T, typename T1, typename T2, typename T3>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3)
+template <typename T, typename OBJ, typename T1, typename T2, typename T3>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3)
{
return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3));
}
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4)
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4)
{
return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
}
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
@@ -952,46 +978,46 @@
-template <typename T>
+template <typename T, typename OBJ>
void
-Simulator::ScheduleNow (void (T::*mem_ptr) (void), T *obj)
+Simulator::ScheduleNow (void (T::*mem_ptr) (void), OBJ obj)
{
ScheduleNow (MakeEvent (mem_ptr, obj));
}
-template <typename T, typename T1>
+template <typename T, typename OBJ, typename T1>
void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1), T* obj, T1 a1)
+Simulator::ScheduleNow (void (T::*mem_ptr) (T1), OBJ obj, T1 a1)
{
ScheduleNow (MakeEvent (mem_ptr, obj, a1));
}
-template <typename T, typename T1, typename T2>
+template <typename T, typename OBJ, typename T1, typename T2>
void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2)
+Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2)
{
ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2));
}
-template <typename T, typename T1, typename T2, typename T3>
+template <typename T, typename OBJ, typename T1, typename T2, typename T3>
void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3)
+Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3)
{
ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3));
}
-template <typename T, typename T1, typename T2, typename T3, typename T4>
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4)
+Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4)
{
ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
}
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
}
@@ -1033,46 +1059,46 @@
-template <typename T>
+template <typename T, typename OBJ>
void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (void), T *obj)
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj)
{
ScheduleDestroy (MakeEvent (mem_ptr, obj));
}
-template <typename T, typename T1>
+template <typename T, typename OBJ, typename T1>
void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1), T* obj, T1 a1)
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1), OBJ obj, T1 a1)
{
ScheduleDestroy (MakeEvent (mem_ptr, obj, a1));
}
-template <typename T, typename T1, typename T2>
+template <typename T, typename OBJ, typename T1, typename T2>
void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2)
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2)
{
ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2));
}
-template <typename T, typename T1, typename T2, typename T3>
+template <typename T, typename OBJ, typename T1, typename T2, typename T3>
void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3)
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3)
{
ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3));
}
-template <typename T, typename T1, typename T2, typename T3, typename T4>
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4)
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4)
{
ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
}
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj,
- T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj,
+ T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
{
ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
}
--- a/src/simulator/time.cc Sat May 19 13:41:50 2007 +0200
+++ b/src/simulator/time.cc Fri May 25 09:44:18 2007 +0200
@@ -1,6 +1,7 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2005,2006 INRIA
+ * Copyright (c) 2007 Emmanuelle Laprise
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -17,13 +18,49 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * TimeStep support by Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
*/
-#include "time.h"
-#include "simulator.h"
+#include "nstime.h"
#include "ns3/fatal-error.h"
+#include "ns3/default-value.h"
+#include <math.h>
namespace ns3 {
+namespace TimeStepPrecision {
+
+static const uint64_t MS_FACTOR = (uint64_t)pow(10,3);
+static const uint64_t US_FACTOR = (uint64_t)pow(10,6);
+static const uint64_t NS_FACTOR = (uint64_t)pow(10,9);
+static const uint64_t PS_FACTOR = (uint64_t)pow(10,12);
+static const uint64_t FS_FACTOR = (uint64_t)pow(10,15);
+static uint64_t g_tsPrecFactor = NS_FACTOR;
+
+static EnumDefaultValue<enum precision_t> g_precisionDefaultValue ("TimeStepPrecision",
+ "The time unit of the internal 64 bit integer time.",
+ NS, "NS",
+ S, "S",
+ MS, "MS",
+ US, "US",
+ PS, "PS",
+ FS, "FS",
+ 0, (void *)0);
+
+precision_t
+Get (void)
+{
+ return g_precisionDefaultValue.GetValue ();
+}
+
+void
+Set (precision_t precision)
+{
+ g_precisionDefaultValue.SetValue (precision);
+ g_tsPrecFactor = (uint64_t)pow(10, precision);
+}
+
+} // namespace TimeStepPrecision
+
TimeUnit<1>::TimeUnit(const std::string& s)
{
std::string::size_type n = s.find_first_not_of("0123456789.");
@@ -33,81 +70,192 @@
std::string trailer = s.substr(n, std::string::npos);
if (trailer == std::string("s"))
{
- m_data = HighPrecision (r * 1000000000.0);
+ m_data = HighPrecision (r * TimeStepPrecision::g_tsPrecFactor);
return;
}
if (trailer == std::string("ms"))
{
- m_data = HighPrecision ((int64_t)(r * 1000000), false);
+ m_data = HighPrecision ((int64_t)(r * (TimeStepPrecision::g_tsPrecFactor/pow(10,3))),
+ false);
return;
}
if (trailer == std::string("us"))
{
- m_data = HighPrecision ((int64_t)(r * 1000), false);
+ m_data = HighPrecision ((int64_t)(r * (TimeStepPrecision::g_tsPrecFactor/pow(10,6))),
+ false);
return;
}
if (trailer == std::string("ns"))
{
- m_data = HighPrecision ((int64_t)r, false);
+ m_data = HighPrecision ((int64_t)(r * (TimeStepPrecision::g_tsPrecFactor/pow(10,9))),
+ false);
+ return;
+ }
+ if (trailer == std::string("ps"))
+ {
+ m_data = HighPrecision ((int64_t)(r * (TimeStepPrecision::g_tsPrecFactor/pow(10,12))),
+ false);
+ return;
+ }
+ if (trailer == std::string("fs"))
+ {
+ m_data = HighPrecision ((int64_t)(r * (TimeStepPrecision::g_tsPrecFactor/pow(10,15))),
+ false);
return;
}
NS_FATAL_ERROR("Can't Parse Time "<<s);
}
//else
//they didn't provide units, assume seconds
- m_data = HighPrecision (atof(s.c_str()) * 1000000000.0);
+ m_data = HighPrecision (atof(s.c_str()) * TimeStepPrecision::g_tsPrecFactor);
}
+
double
TimeUnit<1>::GetSeconds (void) const
{
- double ns = GetHighPrecision ().GetDouble ();
- return ns/1000000000.0;
+ double timeValue = GetHighPrecision ().GetDouble ();
+ return timeValue/TimeStepPrecision::g_tsPrecFactor;
}
-int32_t
+
+int64_t
+TimeUnit<1>::ConvertToUnits (int64_t timeValue, uint64_t unitFactor) const
+{
+ uint64_t precFactor;
+ // In order to avoid conversion to double, precFactor can't be less 1
+ if (TimeStepPrecision::g_tsPrecFactor < unitFactor)
+ {
+ precFactor = unitFactor / TimeStepPrecision::g_tsPrecFactor;
+ timeValue = timeValue * precFactor;
+ }
+ else
+ {
+ precFactor = TimeStepPrecision::g_tsPrecFactor / unitFactor;
+ timeValue = timeValue / precFactor;
+ }
+ return timeValue;
+}
+
+
+int64_t
TimeUnit<1>::GetMilliSeconds (void) const
{
- int64_t ns = GetHighPrecision ().GetInteger ();
- ns /= 1000000;
- return ns;
+ int64_t ts = GetTimeStep();
+ int64_t ms = ConvertToUnits(ts, TimeStepPrecision::MS_FACTOR);
+
+ return ms;
}
int64_t
TimeUnit<1>::GetMicroSeconds (void) const
{
- int64_t ns = GetHighPrecision ().GetInteger ();
- return ns/1000;
+ int64_t ts = GetTimeStep();
+ int64_t us = ConvertToUnits(ts, TimeStepPrecision::US_FACTOR);
+
+ return us;
}
int64_t
TimeUnit<1>::GetNanoSeconds (void) const
{
- return GetHighPrecision ().GetInteger ();
+ int64_t ts = GetTimeStep();
+ int64_t ns = ConvertToUnits(ts, TimeStepPrecision::NS_FACTOR);
+
+ return ns;
+}
+int64_t
+TimeUnit<1>::GetPicoSeconds (void) const
+{
+ int64_t ts = GetTimeStep();
+ int64_t ps = ConvertToUnits(ts, TimeStepPrecision::PS_FACTOR);
+
+ return ps;
}
+int64_t
+TimeUnit<1>::GetFemtoSeconds (void) const
+{
+ int64_t ts = GetTimeStep();
+ int64_t fs = ConvertToUnits(ts, TimeStepPrecision::FS_FACTOR);
+
+ return fs;
+}
+
+/**
+ * This returns the value with the precision returned by TimeStepPrecision::Get
+ */
+int64_t
+TimeUnit<1>::GetTimeStep (void) const
+{
+ int64_t timeValue = GetHighPrecision ().GetInteger ();
+ return timeValue;
+}
+
std::ostream&
operator<< (std::ostream& os, Time const& time)
{
- os << time.GetNanoSeconds () << "ns";
+ os << time.GetTimeStep () << "ts";
return os;
}
Time Seconds (double seconds)
{
- return Time (HighPrecision (seconds * 1000000000.0));
+ double d_sec = seconds * TimeStepPrecision::g_tsPrecFactor;
+ return Time (HighPrecision (d_sec));
+ // return Time (HighPrecision ((int64_t)d_sec, false));
}
-Time MilliSeconds (uint32_t ms)
+
+uint64_t
+TimeUnit<1>::UnitsToTimestep (uint64_t unitValue,
+ uint64_t unitFactor)
{
- return Time (HighPrecision (ms * 1000000, false));
+ uint64_t precFactor;
+ // In order to avoid conversion to double, precFactor can't be less 1
+ if (TimeStepPrecision::g_tsPrecFactor < unitFactor)
+ {
+ precFactor = unitFactor / TimeStepPrecision::g_tsPrecFactor;
+ unitValue = unitValue / precFactor;
+ }
+ else
+ {
+ precFactor = TimeStepPrecision::g_tsPrecFactor / unitFactor;
+ unitValue = unitValue * precFactor;
+ }
+ return unitValue;
}
+
+Time MilliSeconds (uint64_t ms)
+{
+ uint64_t ts = TimeUnit<1>::UnitsToTimestep(ms, TimeStepPrecision::MS_FACTOR);
+ return TimeStep(ts);
+}
+
Time MicroSeconds (uint64_t us)
{
- return Time (HighPrecision (us * 1000, false));
+ uint64_t ts = TimeUnit<1>::UnitsToTimestep(us, TimeStepPrecision::US_FACTOR);
+ return TimeStep(ts);
}
+
Time NanoSeconds (uint64_t ns)
{
- return Time (HighPrecision (ns, false));
+ uint64_t ts = TimeUnit<1>::UnitsToTimestep(ns, TimeStepPrecision::NS_FACTOR);
+ return TimeStep(ts);
+}
+Time PicoSeconds (uint64_t ps)
+{
+ uint64_t ts = TimeUnit<1>::UnitsToTimestep(ps, TimeStepPrecision::PS_FACTOR);
+ return TimeStep(ts);
}
-Time Now (void)
+Time FemtoSeconds (uint64_t fs)
{
- return Time (Simulator::Now ());
+ uint64_t ts = TimeUnit<1>::UnitsToTimestep(fs, TimeStepPrecision::FS_FACTOR);
+ return TimeStep(ts);
+}
+
+/*
+ * The timestep value passed to this function must be of the precision
+ * of TimeStepPrecision::Get
+ */
+Time TimeStep (uint64_t ts)
+{
+ return Time (HighPrecision (ts, false));
}
TimeUnit<0>::TimeUnit (double scalar)
@@ -136,6 +284,46 @@
TimeTests ();
virtual ~TimeTests ();
virtual bool RunTests (void);
+
+ /*
+ * Verifies that a calculated time value is as expected using
+ * doubles since GetSeconds() returns a double
+ */
+ void CheckTimeSec(std::string test_id, double actual, double expected,
+ bool *flag, double precMultFactor = 1,
+ bool verbose = false);
+
+ /*
+ * Verifies that a calculated time value is as expected.
+ */
+ void CheckTime(std::string test_id, int64_t actual, int64_t expected,
+ bool *flag, double precMultFactor = 1,
+ bool verbose = false);
+
+ /*
+ * Verifies the +, -, * and / operations for the TimeUnit<1> or Time class
+ */
+ void CheckOperations(Time t0, Time t1, bool *ok, bool verbose = false);
+
+ /*
+ * Verifies that the TimeUnit class stores values with the precision
+ * set in the variable TimeStepPrecision::Get
+ * Checks that overflow and underflow occur at expected numbers
+ */
+ void CheckPrecision(TimeStepPrecision::precision_t prec, uint64_t val, bool *ok,
+ bool verbose = false);
+
+ /*
+ * Verifies that the conversion between units in the class
+ * TimeUnit<1> or Time is done correctly. This is verified both when
+ * setting and retrieving a Time value
+ */
+ void CheckConversions(uint64_t tval, bool *ok, bool verbose = false);
+
+ /*
+ * These are the old tests that used to be run
+ */
+ void CheckOld(bool *ok);
};
TimeTests::TimeTests ()
@@ -143,21 +331,102 @@
{}
TimeTests::~TimeTests ()
{}
+
bool TimeTests::RunTests (void)
{
bool ok = true;
+ Time t0, t1;
+
+ CheckOld(&ok);
+
+ t0 = MilliSeconds ((uint64_t)10.0);
+ t1 = MilliSeconds ((uint64_t)11.0);
+
+ CheckOperations(t0, t1, &ok);
+
+ // t0 = Seconds ((uint64_t)10.0);
+ // t1 = Seconds ((uint64_t)11.0);
+
+ // CheckOperations(t0, t1, &ok);
+
+ CheckConversions((uint64_t)5, &ok);
+ CheckConversions((uint64_t)0, &ok);
+ CheckConversions((uint64_t)783, &ok);
+ CheckConversions((uint64_t)1132, &ok);
+ // CheckConversions((uint64_t)3341039, &ok);
+
+ // Now vary the precision and check the conversions
+ if (TimeStepPrecision::Get () != TimeStepPrecision::NS) {
+ ok = false;
+ }
+
+ CheckPrecision(TimeStepPrecision::US, 7, &ok);
+
+ CheckConversions((uint64_t)7, &ok);
+ CheckConversions((uint64_t)546, &ok);
+ CheckConversions((uint64_t)6231, &ok);
+ // CheckConversions((uint64_t)1234639, &ok);
+
+ CheckPrecision(TimeStepPrecision::MS, 3, &ok);
+
+ CheckConversions((uint64_t)3, &ok);
+ CheckConversions((uint64_t)134, &ok);
+ CheckConversions((uint64_t)2341, &ok);
+ // CheckConversions((uint64_t)8956239, &ok);
+
+ CheckPrecision(TimeStepPrecision::PS, 21, &ok);
+
+ CheckConversions((uint64_t)4, &ok);
+ CheckConversions((uint64_t)342, &ok);
+ CheckConversions((uint64_t)1327, &ok);
+ // CheckConversions((uint64_t)5439627, &ok);
+
+ CheckPrecision(TimeStepPrecision::NS, 12, &ok);
+ CheckConversions((uint64_t)12, &ok);
+
+ CheckPrecision(TimeStepPrecision::S, 7, &ok);
+ CheckConversions((uint64_t)7, &ok);
+
+ CheckPrecision(TimeStepPrecision::FS, 5, &ok);
+ CheckConversions((uint64_t)5, &ok);
+
+ TimeStepPrecision::Set (TimeStepPrecision::NS);
+
+ Bind ("TimeStepPrecision", "S");
+ Bind ("TimeStepPrecision", "MS");
+ Bind ("TimeStepPrecision", "US");
+ Bind ("TimeStepPrecision", "NS");
+ Bind ("TimeStepPrecision", "PS");
+ Bind ("TimeStepPrecision", "FS");
+
+ return ok;
+}
+
+void TimeTests::CheckOld (bool *ok)
+{
+ double dt0, dt1, dt2;
+ int64_t it0, it1;
+
Time t0 = Seconds (10.0);
- //std::cout << "t0="<<t0.GetSeconds ()<<" (expected 10.0)"<<std::endl;
+ CheckTimeSec("old 1", t0.GetSeconds(), 10.0, ok);
+
Time t1 = Seconds (11.0);
- //std::cout << "t1="<<t1.GetSeconds ()<<" (expected 11.0)"<<std::endl;
+ CheckTimeSec("old 2", t1.GetSeconds(), 11.0, ok);
+
t0 = Seconds (1.5);
- //std::cout << "t0="<<t0.GetSeconds ()<<" (expected +1.5)"<<std::endl;
+ CheckTimeSec("old 3", t0.GetSeconds(), 1.5, ok);
+
t0 = Seconds (-1.5);
- //std::cout << "t0="<<t0.GetSeconds ()<<" (expected -1.5)"<<std::endl;
+ CheckTimeSec("old 4", t0.GetSeconds(), -1.5, ok);
- t0 = Seconds (10.0);
- t1 = Seconds (11.0);
+ t0 = MilliSeconds ((uint64_t)10.0);
+ dt0 = t0.GetSeconds();
+ CheckTimeSec("old 5", dt0, 0.01, ok);
+
+ t1 = MilliSeconds ((uint64_t)11.0);
+ dt1 = t1.GetSeconds();
+ CheckTimeSec("old 6", dt1, 0.011, ok);
Time t2, t3;
@@ -166,44 +435,31 @@
{
ok = false;
}
+ dt2 = t2.GetSeconds();
+ CheckTimeSec("old 7", dt2, dt1-dt0, ok);
+
t2 = t1 - t1;
if (!t2.IsZero ())
{
ok = false;
}
+ dt2 = t2.GetSeconds();
+ CheckTimeSec("old 8", dt2, dt1-dt1, ok);
+
t2 = t0 - t1;
if (!t2.IsStrictlyNegative ())
{
ok = false;
}
+ dt2 = t2.GetSeconds();
+ CheckTimeSec("old 9", dt2, dt0-dt1, ok);
- t2 = t0 - t1;
- t3 = t2 * t0 / t1;
- t3 = t0 * t2 / t1;
- t3 = t0 * t1 / t2;
- t3 = t0 * (t1 / t2);
- t3 = (t0 * t1) / t2;
- t3 = t0 / t1 * t2;
- t3 = (t0 / t1) * t2;
- TimeInvert ti0;
- ti0 = t0 / (t1 * t2);
- t3 = t0 * Scalar (10.0);
- t3 = Scalar (10.0) * t0;
- t3 = Scalar (10.0) * t0 / t2 * t1;
- t3 = (Scalar (10.0) * t0 ) / t2 * t1;
- Scalar s0 = t0 / t1;
- Scalar s1;
- s1 = t0 * t1 / (t2 * t0);
- TimeUnit<0> tu0;
- tu0 = s0;
- TimeUnit<1> tu1;
- tu1 = t0;
- TimeUnit<2> tu2;
- tu2 = t0 * t1;
- TimeUnit<3> tu3;
- tu3 = t0 * tu2;
- TimeUnit<-2> tu4;
- tu4 = t0 / tu3;
+ t1 = NanoSeconds(15);
+ it0 = t0.GetNanoSeconds();
+ it1 = t1.GetNanoSeconds();
+ TimeUnit<-2> tu4 = t0 / (t1 * t1 * t1);
+ CheckTime("old 10", tu4.GetHighPrecision().GetInteger(), it0 / (it1*it1*it1),
+ ok, 1e9);
Time tmp = MilliSeconds (0);
if ((tmp != NanoSeconds (0)) ||
@@ -215,20 +471,274 @@
Time t4;
t4 = Seconds (10.0) * Scalar (1.5);
- //std::cout << "10.0s * 1.5 = " << t4.GetSeconds () << "s" << std::endl;
+ CheckTimeSec("old 11", t4.GetSeconds(), 10, ok);
+
Time t5;
t5 = NanoSeconds (10) * Scalar (1.5);
- //std::cout << "10ns * 1.5 = " << t5.GetNanoSeconds () << "ns" <<
- //std::endl;
+ CheckTime("old 12", t5.GetNanoSeconds(), 10, ok);
+
+ t4 = Seconds (10.0) * Scalar (15) / Scalar (10);
+ CheckTimeSec("old 13", t4.GetSeconds(), 15, ok);
+
+ t5 = NanoSeconds (10) * Scalar (15) / Scalar (10);
+ CheckTime("old 14", t5.GetNanoSeconds(), 15, ok);
+
double foo = (t1 + t2).GetSeconds ();
+ dt1 = t1.GetSeconds();
+ dt2 = t2.GetSeconds();
+ CheckTimeSec("old 15", foo, dt1+dt2, ok);
+
foo += (t4 == t5)? 1 : 0;
+ CheckTimeSec("old 16", foo, dt1+dt2, ok);
foo = (t1/t2).GetDouble ();
+ CheckTimeSec("old 17", foo, dt1/dt2, ok);
+}
- return ok;
+
+void TimeTests::CheckOperations(Time t0, Time t1, bool *ok, bool verbose)
+{
+
+ if (verbose)
+ std::cout << std::endl << "Check operations: "
+ << t0 << " " << t1 << std::endl;
+
+ Time t2, t3;
+ double it0, it1, it2, it3, itu2, itu3;
+ int64_t iti0;
+
+ it0 = t0.GetSeconds();
+ it1 = t1.GetSeconds();
+
+ t2 = t0 - t1;
+ it2 = t2.GetSeconds();
+ CheckTimeSec("ops 1", it2, it0-it1, ok);
+
+ t3 = t2 * t0 / t0;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 2a", it3, it2*it0/it0, ok);
+
+ t3 = t2 * t0 / t1;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 2", it3, it2*it0/it1, ok);
+
+ t3 = t0 * t2 / t1;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 3", it3, it0*it2/it1, ok);
+
+ t3 = t0 * t1 / t2;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 4", it3, it0*it1/it2, ok);
+
+ t3 = t0 * (t1 / t2);
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 5", it3, it0*(it1/it2), ok);
+
+ t3 = (t0 * t1) / t2;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 6", it3, (it0*it1)/it2, ok);
+
+ t3 = t0 / t1 * t2;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 7", it3, it0/it1*it2, ok);
+
+ t3 = (t0 / t1) * t2;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 8", it3, (it0/it1)*it2, ok);
+
+ t3 = t0 * Scalar (10.0);
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 9", it3, it0*10, ok);
+
+ t3 = Scalar (10.0) * t0;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 10", it3, 10 * it0, ok);
+
+ t3 = Scalar (10.0) * t0 / t2 * t1;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 11", it3, 10 * it0 / it2 * it1, ok);
+
+ t3 = (Scalar (10.0) * t0 ) / t2 * t1;
+ it3 = t3.GetSeconds();
+ CheckTimeSec("ops 12", it3, (10 * it0) / it2 * it1, ok);
+
+ TimeInvert ti0;
+ ti0 = t0 / (t1 * t2);
+ iti0 = ti0.GetHighPrecision().GetInteger();
+ // This check is not quite working yet.
+ // CheckTime("ops 13", iti0, (int64_t)(it0/(it1*it2)), ok);
+
+ Scalar s0 = t0 / t1;
+ CheckTimeSec("ops 14", s0.GetDouble(), it0/it1, ok);
+
+ Scalar s1;
+ s1 = t0 * t1 / (t2 * t0);
+ CheckTimeSec("ops 15", s1.GetDouble(), it0*it1/(it2*it0), ok);
+
+ TimeUnit<0> tu0;
+ tu0 = s0;
+ CheckTimeSec("ops 16", tu0.GetDouble(), s0.GetDouble(), ok);
+
+ TimeUnit<1> tu1;
+ tu1 = t0;
+ CheckTimeSec("ops 17", tu1.GetSeconds(), it0, ok);
+
+ TimeUnit<2> tu2;
+ tu2 = t0 * t1;
+ CheckTimeSec("ops 18", tu2.GetHighPrecision().GetInteger()/(1e18),
+ it0 * it1, ok);
+ itu2 = tu2.GetHighPrecision().GetInteger()/(1e18);
+
+ TimeUnit<3> tu3;
+ tu3 = t0 / Scalar(10e6) * tu2;
+ CheckTimeSec("ops 19", tu3.GetHighPrecision().GetInteger()/(1e27),
+ it0 / 1000000 * itu2, ok);
+ itu3 = tu3.GetHighPrecision().GetInteger()/(1e27);
}
+void TimeTests::CheckConversions(uint64_t tval, bool *ok, bool verbose) {
+ Time t_sec, t_ms, t_us, t_ns, t_ps, t_fs;
+
+ if (verbose)
+ std::cout << std::endl << "Check conversions: " << tval << std::endl;
+
+ // First check the seconds
+ t_sec = Seconds((double)tval);
+ CheckTimeSec("conv sec sec", t_sec.GetSeconds(), (double)tval, ok);
+ CheckTime("conv sec ms", t_sec.GetMilliSeconds(), (int64_t)(tval*1e3), ok, 1e3);
+ CheckTime("conv sec us", t_sec.GetMicroSeconds(), (int64_t)(tval*1e6), ok, 1e6);
+ CheckTime("conv sec ns", t_sec.GetNanoSeconds(), (int64_t)(tval*1e9), ok, 1e9);
+ CheckTime("conv sec ps", t_sec.GetPicoSeconds(),
+ (int64_t)(tval*1e12), ok, 1e12);
+ CheckTime("conv sec fs", t_sec.GetFemtoSeconds(),
+ (int64_t)(tval*1e15), ok, 1e15);
+
+ // Then check the milliseconds
+ t_ms = MilliSeconds(tval);
+ CheckTimeSec("conv ms sec", t_ms.GetSeconds(), (double)tval/1e3, ok);
+ CheckTime("conv ms ms", t_ms.GetMilliSeconds(), (int64_t)(tval), ok, 1e3);
+ CheckTime("conv ms us", t_ms.GetMicroSeconds(), (int64_t)(tval*1e3), ok, 1e6);
+ CheckTime("conv ms ns", t_ms.GetNanoSeconds(), (int64_t)(tval*1e6), ok, 1e9);
+ CheckTime("conv ms ps", t_ms.GetPicoSeconds(), (int64_t)(tval*1e9), ok, 1e12);
+ CheckTime("conv ms fs", t_ms.GetFemtoSeconds(), (int64_t)(tval*1e12), ok, 1e15);
+
+ // Then check the microseconds
+ t_us = MicroSeconds(tval);
+ CheckTimeSec("conv us sec", t_us.GetSeconds(), (double)tval/1e6, ok);
+ CheckTime("conv us ms", t_us.GetMilliSeconds(), (int64_t)(tval/1e3), ok, 1e3);
+ CheckTime("conv us us", t_us.GetMicroSeconds(), (int64_t)(tval), ok, 1e6);
+ CheckTime("conv us ns", t_us.GetNanoSeconds(), (int64_t)(tval*1e3), ok, 1e9);
+ CheckTime("conv us ps", t_us.GetPicoSeconds(), (int64_t)(tval*1e6), ok, 1e12);
+ CheckTime("conv us fs", t_us.GetFemtoSeconds(), (int64_t)(tval*1e9), ok, 1e15);
+
+ // Then check the nanoseconds
+ t_ns = NanoSeconds(tval);
+ CheckTimeSec("conv ns sec", t_ns.GetSeconds(), (double)tval/1e9, ok);
+ CheckTime("conv ns ms", t_ns.GetMilliSeconds(), (int64_t)(tval/1e6), ok, 1e3);
+ CheckTime("conv ns us", t_ns.GetMicroSeconds(), (int64_t)(tval/1e3), ok, 1e6);
+ CheckTime("conv ns ns", t_ns.GetNanoSeconds(), (int64_t)(tval), ok, 1e9);
+ CheckTime("conv ns ps", t_ns.GetPicoSeconds(), (int64_t)(tval*1e3), ok, 1e12);
+ CheckTime("conv ns fs", t_ns.GetFemtoSeconds(), (int64_t)(tval*1e6), ok, 1e15);
+
+ // Then check the picoseconds
+ t_ps = PicoSeconds(tval);
+ CheckTimeSec("conv ps sec", t_ps.GetSeconds(), (double)tval/1e12, ok);
+ CheckTime("conv ps ms", t_ps.GetMilliSeconds(), (int64_t)(tval/1e9), ok, 1e3);
+ CheckTime("conv ps us", t_ps.GetMicroSeconds(), (int64_t)(tval/1e6), ok, 1e6);
+ CheckTime("conv ps ns", t_ps.GetNanoSeconds(), (int64_t)(tval/1e3), ok, 1e9);
+ CheckTime("conv ps ps", t_ps.GetPicoSeconds(), (int64_t)(tval), ok, 1e12);
+ CheckTime("conv ps fs", t_ps.GetFemtoSeconds(), (int64_t)(tval*1e3), ok, 1e15);
+
+ // Then check the femtoseconds
+ t_fs = FemtoSeconds(tval);
+ CheckTimeSec("conv fs sec", t_fs.GetSeconds(), (double)tval/1e15, ok);
+ CheckTime("conv fs ms", t_fs.GetMilliSeconds(), (int64_t)(tval/1e12), ok, 1e3);
+ CheckTime("conv fs us", t_fs.GetMicroSeconds(), (int64_t)(tval/1e9), ok, 1e6);
+ CheckTime("conv fs ns", t_fs.GetNanoSeconds(), (int64_t)(tval/1e6), ok, 1e9);
+ CheckTime("conv fs ps", t_fs.GetPicoSeconds(), (int64_t)(tval/1e3), ok, 1e12);
+ CheckTime("conv fs fs", t_fs.GetFemtoSeconds(), (int64_t)(tval), ok, 1e15);
+
+
+}
+
+void TimeTests::CheckPrecision(TimeStepPrecision::precision_t prec, uint64_t val, bool *ok,
+ bool verbose) {
+ if (verbose) {
+ std::cout << "check precision 10^-" << prec << std::endl;
+ }
+
+ TimeStepPrecision::Set (prec);
+ if (TimeStepPrecision::Get () != prec) {
+ ok = false;
+ }
+
+ /* These still need to be fixed.
+ // The smallest value that can be stored is 1x10^(-prec)
+ Time smallest = Seconds(pow(10,-prec));
+ CheckTimeSec("Prec small: ", smallest.GetSeconds(), pow(10,-prec), ok, 0.1,
+ true);
+
+ double d_ts = pow(10,-prec) - pow(10, -(prec+3));
+ Time too_small = Seconds(d_ts);
+ CheckTimeSec("Prec too small: ", too_small.GetSeconds(), 0, ok, 0.1, true);
+
+ double d_la = 0xFFFFFFFF*pow(10,-prec);
+ Time largest = Seconds(d_la);
+ CheckTimeSec("Prec large: ", largest.GetSeconds(), d_la, ok, 0.1, true);
+
+ double d_tl = (0xFFFFFFFF*pow(10,-prec)) + 1;
+ Time too_large = Seconds(d_tl);
+ if ((largest.GetSeconds() + 1) == too_large.GetSeconds())
+ std::cout << "Overflow did not occur." << std::endl;
+
+ NS_ASSERT(d_la+1 == d_tl);
+ */
+}
+
+void TimeTests::CheckTimeSec (std::string test_id, double actual,
+ double expected, bool *flag, double precMultFactor,
+ bool verbose)
+{
+ double prec = pow(10,-((double)(ns3::TimeStepPrecision::Get ()))) * precMultFactor;
+ if ((actual < (expected-prec)) || (actual > (expected+prec))) {
+ std::cout << "FAIL " << test_id
+ << " Expected:" << expected
+ << " Actual: " << actual
+ << " Precision: " << prec << std::endl;
+ *flag = false;
+ } else {
+ if (verbose) {
+ std::cout << "PASS " << test_id
+ << " Expected:" << expected
+ << " Actual: " << actual
+ << " Precision: " << prec << std::endl;
+ }
+ }
+}
+
+void TimeTests::CheckTime (std::string test_id, int64_t actual,
+ int64_t expected, bool *flag, double precMultFactor,
+ bool verbose)
+{
+ double prec = pow(10,-((double)(ns3::TimeStepPrecision::Get ()))) * precMultFactor;
+ if ((actual < (expected-prec)) || (actual > (expected+prec))) {
+ std::cout << "FAIL " << test_id
+ << " Expected:" << expected
+ << " Actual: " << actual
+ << " Precision: " << prec << std::endl;
+ *flag = false;
+ } else {
+ if (verbose) {
+ std::cout << "PASS " << test_id
+ << " Expected:" << expected
+ << " Actual: " << actual
+ << " Precision: " << prec << std::endl;
+ }
+ }
+}
+
+
static TimeTests g_time_tests;
};
--- a/src/wscript Sat May 19 13:41:50 2007 +0200
+++ b/src/wscript Fri May 25 09:44:18 2007 +0200
@@ -1,7 +1,14 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import os
+import shutil
+
+import Action
+import Common
+import Object
import Params
+
all_modules = [
'core',
'common',
@@ -15,29 +22,68 @@
def set_options(opt):
opt.sub_options('simulator')
- opt.add_option('--disable-rpath',
- help=("Don't link programs with rpath"),
- action="store_true", default=False,
- dest='disable_rpath')
-
-
+
def configure(conf):
conf.sub_config('core')
conf.sub_config('simulator')
- conf.env['DISABLE_RPATH'] = Params.g_options.disable_rpath
-
def build(bld):
+ Object.register('ns3header', Ns3Header)
+ Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE')
- ## Add a global RPATH pointing to each module, so that programs can find the libs
- ## Note: this is slightly evil; we get away because our programs
- ## and libs are not supposed to be installed system wide.
env = bld.env_of_name('default')
- if not env['DISABLE_RPATH']:
- for module in all_modules:
- node = bld.m_curdirnode.find_dir(module)
- env.append_value('RPATH', '-Wl,--rpath=%s' % (node.abspath(env),))
+ for module in all_modules:
+ node = bld.m_curdirnode.find_dir(module)
+ node_path = node.abspath(env)
+ env.append_value('NS3_MODULE_PATH', node_path)
bld.add_subdirs(all_modules)
+
+class Ns3Header(Object.genobj):
+ """A set of NS-3 header files"""
+ def __init__(self, env=None):
+ Object.genobj.__init__(self, 'other')
+ self.inst_var = 'INCLUDEDIR'
+ self.inst_dir = 'ns3'
+ self.env = env
+ if not self.env:
+ self.env = Params.g_build.m_allenvs['default']
+
+ def apply(self):
+ ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3")
+ inputs = []
+ outputs = []
+ for filename in self.to_list(self.source):
+ src_node = self.path.find_source(filename)
+ if src_node is None:
+ Params.fatal("source ns3 header file %s not found" % (filename,))
+ dst_node = ns3_dir_node.find_build(os.path.basename(filename))
+ assert dst_node is not None
+ inputs.append(src_node)
+ outputs.append(dst_node)
+ task = self.create_task('ns3_headers', self.env, 1)
+ task.set_inputs(inputs)
+ task.set_outputs(outputs)
+
+ def install(self):
+ for i in self.m_tasks:
+ current = Params.g_build.m_curdirnode
+ lst = map(lambda a: a.relpath_gen(current), i.m_outputs)
+ Common.install_files(self.inst_var, self.inst_dir, lst)
+
+def _ns3_headers_inst(task):
+ assert len(task.m_inputs) == len(task.m_outputs)
+ inputs = [node.srcpath(task.m_env) for node in task.m_inputs]
+ outputs = [node.bldpath(task.m_env) for node in task.m_outputs]
+ for src, dst in zip(inputs, outputs):
+ try:
+ os.chmod(dst, 0600)
+ except OSError:
+ pass
+ shutil.copy2(src, dst)
+ ## make the headers in builddir read-only, to prevent
+ ## accidental modification
+ os.chmod(dst, 0400)
+ return 0
--- a/wscript Sat May 19 13:41:50 2007 +0200
+++ b/wscript Fri May 25 09:44:18 2007 +0200
@@ -1,78 +1,30 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import os
+import sys
+import shlex
+import shutil
import Params
import Object
-import Action
-import Common
-import shutil
-import subprocess
+import pproc as subprocess
Params.g_autoconfig = 1
# the following two variables are used by the target "waf dist"
-VERSION = '3.0.1'
-APPNAME = 'ns-3-waf'
+VERSION = file("VERSION").read().strip()
+APPNAME = 'ns'
# these variables are mandatory ('/' are converted automatically)
srcdir = '.'
blddir = 'build'
-class Ns3Header(Object.genobj):
- """A set of NS-3 header files"""
- def __init__(self, env=None):
- Object.genobj.__init__(self, 'other')
- self.inst_var = 'INCLUDEDIR'
- self.inst_dir = 'ns3'
- self.env = env
- if not self.env:
- self.env = Params.g_build.m_allenvs['default']
-
- def apply(self):
- ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3")
- inputs = []
- outputs = []
- for filename in self.to_list(self.source):
- src_node = self.path.find_source(filename)
- if src_node is None:
- Params.fatal("source ns3 header file %s not found" % (filename,))
- dst_node = ns3_dir_node.find_build(os.path.basename(filename))
- assert dst_node is not None
- inputs.append(src_node)
- outputs.append(dst_node)
- task = self.create_task('ns3_headers', self.env, 1)
- task.set_inputs(inputs)
- task.set_outputs(outputs)
-
- def install(self):
- for i in self.m_tasks:
- current = Params.g_build.m_curdirnode
- lst = map(lambda a: a.relpath_gen(current), i.m_outputs)
- Common.install_files(self.inst_var, self.inst_dir, lst)
-
-def _ns3_headers_inst(task):
- assert len(task.m_inputs) == len(task.m_outputs)
- inputs = [node.srcpath(task.m_env) for node in task.m_inputs]
- outputs = [node.bldpath(task.m_env) for node in task.m_outputs]
- for src, dst in zip(inputs, outputs):
- try:
- os.chmod(dst, 0600)
- except OSError:
- pass
- shutil.copy2(src, dst)
- ## make the headers in builddir read-only, to prevent
- ## accidental modification
- os.chmod(dst, 0400)
- return 0
-
-def init():
- Object.register('ns3header', Ns3Header)
- Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE')
+def dist_hook(srcdir, blddir):
+ shutil.rmtree("doc/html")
+ shutil.rmtree("doc/latex")
def set_options(opt):
# options provided by the modules
- if not opt.tool_options('msvc'):
- opt.tool_options('g++')
+ opt.tool_options('compiler_cxx')
opt.add_option('--enable-gcov',
help=('Enable code coverage analysis'),
@@ -90,14 +42,22 @@
action="store_true", default=False,
dest='doxygen')
+ opt.add_option('--run',
+ help=('Run a locally built program'),
+ type="string", default='', dest='run')
+
+ opt.add_option('--shell',
+ help=('Run a shell with an environment suitably modified to run locally built programs'),
+ action="store_true", default=False,
+ dest='shell')
+
# options provided in a script in a subdirectory named "src"
opt.sub_options('src')
def configure(conf):
- if not conf.check_tool('msvc'):
- if not conf.check_tool('g++'):
- Params.fatal("No suitable compiler found")
+ if not conf.check_tool('compiler_cxx'):
+ Params.fatal("No suitable compiler found")
# create the second environment, set the variant and set its name
@@ -123,6 +83,9 @@
variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE')
variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')
+ if sys.platform == 'win32':
+ variant_env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
+
conf.sub_config('src')
@@ -136,48 +99,126 @@
def shutdown():
- import UnitTest
- ut = UnitTest.unit_test()
- ut.change_to_testfile_dir = True
- ut.want_to_see_test_output = True
- ut.want_to_see_test_error = True
- ut.run()
+ #import UnitTest
+ #ut = UnitTest.unit_test()
+ #ut.change_to_testfile_dir = True
+ #ut.want_to_see_test_output = True
+ #ut.want_to_see_test_error = True
+ #ut.run()
#ut.print_results()
+ if Params.g_commands['check']:
+ run_program('run-tests')
+
if Params.g_options.lcov_report:
- env = Params.g_build.env_of_name('default')
- variant_name = env['NS3_ACTIVE_VARIANT']
-
- if 'gcov' not in variant_name:
- Params.fatal("project not configured for code coverage;"
- " reconfigure with --enable-gcov")
-
- os.chdir(blddir)
- try:
- lcov_report_dir = os.path.join(variant_name, 'lcov-report')
- create_dir_command = "rm -rf " + lcov_report_dir
- create_dir_command += " && mkdir " + lcov_report_dir + ";"
-
- if subprocess.Popen(create_dir_command, shell=True).wait():
- raise SystemExit(1)
-
- info_file = os.path.join(lcov_report_dir, variant_name + '.info')
- lcov_command = "../utils/lcov/lcov -c -d . -o " + info_file
- lcov_command += " --source-dirs=" + os.getcwd()
- lcov_command += ":" + os.path.join(
- os.getcwd(), variant_name, 'include')
- if subprocess.Popen(lcov_command, shell=True).wait():
- raise SystemExit(1)
-
- genhtml_command = "../utils/lcov/genhtml -o " + lcov_report_dir
- genhtml_command += " " + info_file
- if subprocess.Popen(genhtml_command, shell=True).wait():
- raise SystemExit(1)
- finally:
- os.chdir("..")
+ lcov_report()
if Params.g_options.doxygen:
- doxygen_config = os.path.join('doc', 'doxygen.conf')
- if subprocess.Popen(['doxygen', doxygen_config]).wait():
+ doxygen()
+
+ if Params.g_options.run:
+ run_program(Params.g_options.run)
+
+ elif Params.g_options.shell:
+ run_shell()
+
+def _find_program(program_name):
+ for obj in Object.g_allobjs:
+ if obj.target == program_name:
+ return obj
+ raise ValueError("progam '%s' not found" % (program_name,))
+
+def _run_argv(argv):
+ env = Params.g_build.env_of_name('default')
+ if sys.platform == 'linux2':
+ pathvar = 'LD_LIBRARY_PATH'
+ pathsep = ':'
+ elif sys.platform == 'darwin':
+ pathvar = 'DYLD_LIBRARY_PATH'
+ pathsep = ':'
+ elif sys.platform == 'win32':
+ pathvar = 'PATH'
+ pathsep = ';'
+ else:
+ Params.warning(("Don't know how to configure "
+ "dynamic library path for the platform '%s'") % (sys.platform,))
+ pathvar = None
+ pathsep = None
+
+ os_env = dict(os.environ)
+ if pathvar is not None:
+ if pathvar in os_env:
+ os_env[pathvar] = pathsep.join([os_env[pathvar]] + list(env['NS3_MODULE_PATH']))
+ else:
+ os_env[pathvar] = pathsep.join(list(env['NS3_MODULE_PATH']))
+
+ retval = subprocess.Popen(argv, env=os_env).wait()
+ if retval:
+ raise SystemExit(retval)
+
+
+def run_program(program_string):
+ env = Params.g_build.env_of_name('default')
+ argv = shlex.split(program_string)
+ program_name = argv[0]
+
+ try:
+ program_obj = _find_program(program_name)
+ except ValueError:
+ Params.fatal("progam '%s' not found" % (program_name,))
+
+ try:
+ program_node, = program_obj.m_linktask.m_outputs
+ except AttributeError:
+ Params.fatal("%s does not appear to be a program" % (program_name,))
+
+ execvec = [program_node.abspath(env)] + argv[1:]
+ return _run_argv(execvec)
+
+
+def run_shell():
+ if sys.platform == 'win32':
+ shell = os.environ.get("COMSPEC", "cmd.exe")
+ else:
+ shell = os.environ.get("SHELL", "/bin/sh")
+ _run_argv([shell])
+
+
+def doxygen():
+ doxygen_config = os.path.join('doc', 'doxygen.conf')
+ if subprocess.Popen(['doxygen', doxygen_config]).wait():
+ raise SystemExit(1)
+
+
+def lcov_report():
+ env = Params.g_build.env_of_name('default')
+ variant_name = env['NS3_ACTIVE_VARIANT']
+
+ if 'gcov' not in variant_name:
+ Params.fatal("project not configured for code coverage;"
+ " reconfigure with --enable-gcov")
+
+ os.chdir(blddir)
+ try:
+ lcov_report_dir = os.path.join(variant_name, 'lcov-report')
+ create_dir_command = "rm -rf " + lcov_report_dir
+ create_dir_command += " && mkdir " + lcov_report_dir + ";"
+
+ if subprocess.Popen(create_dir_command, shell=True).wait():
raise SystemExit(1)
+ info_file = os.path.join(lcov_report_dir, variant_name + '.info')
+ lcov_command = "../utils/lcov/lcov -c -d . -o " + info_file
+ lcov_command += " --source-dirs=" + os.getcwd()
+ lcov_command += ":" + os.path.join(
+ os.getcwd(), variant_name, 'include')
+ if subprocess.Popen(lcov_command, shell=True).wait():
+ raise SystemExit(1)
+
+ genhtml_command = "../utils/lcov/genhtml -o " + lcov_report_dir
+ genhtml_command += " " + info_file
+ if subprocess.Popen(genhtml_command, shell=True).wait():
+ raise SystemExit(1)
+ finally:
+ os.chdir("..")
+