merge
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 25 May 2007 09:44:18 +0200
changeset 704 31df575a9360
parent 703 f96426fb9826 (current diff)
parent 695 90a68c1c4328 (diff)
child 705 8fa68ba2cf00
merge
INSTALL
SConstruct
doc/codingstd.tex
src/common/smartset.h
src/common/smartvector.h
src/core/reference-list-test.cc
src/core/reference-list.h
--- 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("..")
+