From 96535936a596fdd29cf5c63da861ef8162cf0177 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 17 May 2007 14:22:27 +0100 Subject: [PATCH 01/48] Make WAF check for the abstract tool 'compiler_cxx', instead of manually checking for multiple compilers. --- wscript | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/wscript b/wscript index a15f4e78a..9e4d993d2 100644 --- a/wscript +++ b/wscript @@ -71,8 +71,7 @@ def init(): 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'), @@ -95,9 +94,8 @@ def set_options(opt): 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 From 6f9b937819ad55349bd362e9cb32f5322c5d48b1 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 17 May 2007 15:59:23 +0200 Subject: [PATCH 02/48] add gcc 4.2 to list of supported compilers --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index c1a85a736..42b8007ea 100644 --- a/README +++ b/README @@ -84,7 +84,7 @@ found in the 'examples' directory. 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. - MacOS X ppc and x86 The current codebase is expected to fail to build on From 6e7e5822fbf09e900513d9b8b1e1db3765deeac7 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 17 May 2007 15:15:56 +0100 Subject: [PATCH 03/48] Fix some case sensitivity issues on win32-specific code. --- src/core/win32-system-wall-clock-ms.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/win32-system-wall-clock-ms.cc b/src/core/win32-system-wall-clock-ms.cc index db81d580c..8043d2589 100644 --- a/src/core/win32-system-wall-clock-ms.cc +++ b/src/core/win32-system-wall-clock-ms.cc @@ -25,8 +25,8 @@ namespace ns3 { class SystemWallClockMsPrivate { public: - void start (void); - unsigned long long end (void); + void Start (void); + unsigned long long End (void); private: }; From 4c68aff164b51f928f286589255987cf8e692c4b Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 17 May 2007 15:50:20 +0100 Subject: [PATCH 04/48] Rename the SocketErrno enumeration values, from ESOMETHING to ERROR_SOMETHING, to avoid conflict with errno #define's; fixes compilation in mingw32. --- src/internet-node/udp-socket.cc | 10 +++++----- src/node/socket.h | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/internet-node/udp-socket.cc b/src/internet-node/udp-socket.cc index 8c6c3dcfc..dd58652ad 100644 --- a/src/internet-node/udp-socket.cc +++ b/src/internet-node/udp-socket.cc @@ -30,7 +30,7 @@ UdpSocket::UdpSocket (Ptr node, Ptr udp) : 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 @@ UdpSocket::DoAccept(ns3::Callback, const Ipv4Address&, uint16_ ns3::Callback > 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 @@ UdpSocket::DoSend (const uint8_t* buffer, { if (!m_connected) { - m_errno = ENOTCONN; + m_errno = ERROR_NOTCONN; return -1; } Packet p; @@ -193,7 +193,7 @@ UdpSocket::DoSendPacketTo (const Packet &p, Ipv4Address daddr, uint16_t dport, } if (m_shutdownSend) { - m_errno = ESHUTDOWN; + m_errno = ERROR_SHUTDOWN; return -1; } m_udp->Send (p, m_endPoint->GetLocalAddress (), daddr, @@ -213,7 +213,7 @@ UdpSocket::DoSendTo(const Ipv4Address &address, { if (m_connected) { - m_errno = EISCONN; + m_errno = ERROR_ISCONN; return -1; } Packet p; diff --git a/src/node/socket.h b/src/node/socket.h index ee710ca75..1c352e166 100644 --- a/src/node/socket.h +++ b/src/node/socket.h @@ -46,13 +46,13 @@ public: 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 }; From b3b7a98b8e0fcd8d621a7bfb43bf975b0165145e Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 17 May 2007 17:02:03 +0100 Subject: [PATCH 05/48] In WAF win32 builds, add -Wl,--enable-runtime-pseudo-reloc to LINKFLAGS to solve dll linking problems. --- wscript | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wscript b/wscript index 9e4d993d2..c7f668f46 100644 --- a/wscript +++ b/wscript @@ -1,5 +1,6 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- import os +import sys import Params import Object @@ -121,6 +122,9 @@ def configure(conf): 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') From 78f81de607eb4dce5cb018bfcf72fc1100d18ac6 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 17 May 2007 17:34:19 +0100 Subject: [PATCH 06/48] Make WAF scripts modify PATH in environment to allow child processes to find the ns-3 DLLs, instead of using --rpath, which doesn't work on win32. This way at least waf check is able to run the unit tests now. --- src/wscript | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/wscript b/src/wscript index 614dccbae..45d10365f 100644 --- a/src/wscript +++ b/src/wscript @@ -1,5 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import os +import sys import Params all_modules = [ @@ -37,7 +39,10 @@ def build(bld): 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),)) + if sys.platform == 'win32': + os.environ["PATH"] = ';'.join([os.environ["PATH"], node.abspath(env)]) + else: + env.append_value('RPATH', '-Wl,--rpath=%s' % (node.abspath(env),)) bld.add_subdirs(all_modules) From d386be9d5df41b5b2ca25ccf08080e9e0fc9a3d4 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 17 May 2007 18:22:10 +0100 Subject: [PATCH 07/48] WAF: import the WAF subprocess replacement module 'pproc', to make it work on Python 2.3. --- wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wscript b/wscript index c7f668f46..c8a4b3c32 100644 --- a/wscript +++ b/wscript @@ -7,7 +7,7 @@ import Object import Action import Common import shutil -import subprocess +import pproc as subprocess Params.g_autoconfig = 1 From 777438f7fc620861e011917cbbff150c65d46425 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Fri, 18 May 2007 11:27:20 +0100 Subject: [PATCH 08/48] WAF: the correct form of the rpath option should be -rpath, not --rpath; fixed. --- src/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wscript b/src/wscript index 45d10365f..0c01fc06f 100644 --- a/src/wscript +++ b/src/wscript @@ -42,7 +42,7 @@ def build(bld): if sys.platform == 'win32': os.environ["PATH"] = ';'.join([os.environ["PATH"], node.abspath(env)]) else: - env.append_value('RPATH', '-Wl,--rpath=%s' % (node.abspath(env),)) + env.append_value('RPATH', '-Wl,-rpath=%s' % (node.abspath(env),)) bld.add_subdirs(all_modules) From 8d9a65d2262511d1fb9f757b121bf45deb7189c4 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Fri, 18 May 2007 16:09:13 +0100 Subject: [PATCH 09/48] WAF: enable -rpath by default only on linux2, with configure options to override this default choice --- src/wscript | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/wscript b/src/wscript index 0c01fc06f..362a7c003 100644 --- a/src/wscript +++ b/src/wscript @@ -17,17 +17,20 @@ all_modules = [ def set_options(opt): opt.sub_options('simulator') + opt.add_option('--enable-rpath', + help=("Link programs with rpath"), + action="store_true", dest='enable_rpath', + default=(sys.platform != 'linux2')) opt.add_option('--disable-rpath', help=("Don't link programs with rpath"), - action="store_true", default=False, - dest='disable_rpath') - + action="store_false", dest='enable_rpath', + default=(sys.platform != 'linux2')) def configure(conf): conf.sub_config('core') conf.sub_config('simulator') - conf.env['DISABLE_RPATH'] = Params.g_options.disable_rpath + conf.env['ENABLE_RPATH'] = Params.g_options.enable_rpath def build(bld): @@ -36,7 +39,7 @@ def build(bld): ## 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']: + if not env['ENABLE_RPATH']: for module in all_modules: node = bld.m_curdirnode.find_dir(module) if sys.platform == 'win32': From fdfcb957111a2ae228fffaa80338b269fcface68 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 18 May 2007 17:26:28 +0200 Subject: [PATCH 10/48] change version number to match ns convention --- SConstruct | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 6a187c7af..a283414e5 100644 --- a/SConstruct +++ b/SConstruct @@ -4,9 +4,9 @@ import build ns3 = build.Ns3() ns3.build_dir = 'build-dir' -ns3.version = '0.2' +ns3.version = '3.0.2' 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/contributing.txt') From 8dd140d50d8504a33f06f1863f75c6c5672ffe77 Mon Sep 17 00:00:00 2001 From: Raj Bhattacharjea Date: Fri, 18 May 2007 11:41:43 -0400 Subject: [PATCH 11/48] Make scons dist work on osx --- build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.py b/build.py index 25a38e4fa..c486ab171 100644 --- a/build.py +++ b/build.py @@ -504,7 +504,7 @@ class Ns3: # 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: From 12840fd46c04a0c59dceab218e3096f14532be42 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 18 May 2007 18:03:48 +0200 Subject: [PATCH 12/48] update the documentation section --- README | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README b/README index 42b8007ea..91ac01939 100644 --- a/README +++ b/README @@ -123,18 +123,17 @@ quite likely that you will want to get started on reading 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 +142,17 @@ It includes: 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 ----------------------------------------------- From 418ceadc2b5151e43c66f13c0a6ce1389990e16b Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 18 May 2007 18:06:00 +0200 Subject: [PATCH 13/48] add doc/architecture.pdf to dist --- SConstruct | 1 + 1 file changed, 1 insertion(+) diff --git a/SConstruct b/SConstruct index a283414e5..e6372aac3 100644 --- a/SConstruct +++ b/SConstruct @@ -9,6 +9,7 @@ ns3.name = 'ns3' 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/mercurial.txt') From 234aafe368b71316eb021a7be47d920d7150ccf3 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 18 May 2007 10:27:42 -0700 Subject: [PATCH 14/48] minor changes due to documentation review --- INSTALL | 35 -------- README | 29 +++--- RELEASE_NOTES | 6 +- VERSION | 2 +- doc/build-waf.txt | 25 +++--- doc/build.txt | 3 + doc/codingstd.txt | 210 +++++++++++++++++++++++++++++++++++++++++++ doc/contributing.txt | 20 +++-- doc/mercurial.txt | 3 +- 9 files changed, 264 insertions(+), 69 deletions(-) delete mode 100644 INSTALL create mode 100644 doc/codingstd.txt diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 36b34f92d..000000000 --- a/INSTALL +++ /dev/null @@ -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 - diff --git a/README b/README index 91ac01939..1443c2df7 100644 --- a/README +++ b/README @@ -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 @@ Table of Content: 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 @@ process. 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 @@ number of very simple network simulation models: - 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 @@ simple as possible: 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 @@ -92,14 +93,14 @@ the following platforms: - 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 +113,7 @@ cd build-dir/dbg-shared/bin 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 ------------------------------------------- @@ -166,4 +167,4 @@ familiar with it. 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" diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 5e0c28ee7..8e02e3ee2 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -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 @@ Release 0.2 (2007/05/XX) - 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. diff --git a/VERSION b/VERSION index cb2b00e4f..b50214693 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.1 +3.0.2 diff --git a/doc/build-waf.txt b/doc/build-waf.txt index a560b3bff..0327f41db 100644 --- a/doc/build-waf.txt +++ b/doc/build-waf.txt @@ -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,7 @@ Other waf usages include: Run code coverage analysis (assuming the project was configured with --enable-gcov) -=== Extending NS-3 === +=== Extending ns-3 === To add new modules: 1. Create the module directory under src (or src/devices, or whatever); @@ -38,7 +43,7 @@ To add new modules: 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 +70,7 @@ def build(bld): === 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 +82,8 @@ tested to work correctly with ns3, although 'trunk' will likely work 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 diff --git a/doc/build.txt b/doc/build.txt index 4cf112c0e..b23be1e5d 100644 --- a/doc/build.txt +++ b/doc/build.txt @@ -16,6 +16,9 @@ the executable binaries generated link explicitely against the right libraries. This saves you the pain of having to setup environment variables to point to the right libraries. +(Note: An experimental, alternative build system is described +in build-waf.txt) + 1) Options ---------- diff --git a/doc/codingstd.txt b/doc/codingstd.txt new file mode 100644 index 000000000..6369035e9 --- /dev/null +++ b/doc/codingstd.txt @@ -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 + */ + +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 + */ +#include "my-class.h" + +namespace ns3 { + +MyClass::MyClass () +{} + +... + +} // namespace ns3 + diff --git a/doc/contributing.txt b/doc/contributing.txt index f0a8b7b83..13da6989d 100644 --- a/doc/contributing.txt +++ b/doc/contributing.txt @@ -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 @@ the open-source roots of the project: 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 diff --git a/doc/mercurial.txt b/doc/mercurial.txt index 5e6f8cb4a..fefc88f39 100644 --- a/doc/mercurial.txt +++ b/doc/mercurial.txt @@ -3,7 +3,7 @@ Introduction 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 @@ push upwards (developers access only): -------------------------------------- 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 From e8d95c4e7ef0e3934b71f92de02d3f8dc2e6dd5f Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 18 May 2007 11:13:57 -0700 Subject: [PATCH 15/48] Pick up codingstd.txt in dist; point interested waf users to build-waf.txt in the development branch --- SConstruct | 1 + doc/build.txt | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index e6372aac3..5c1c6939b 100644 --- a/SConstruct +++ b/SConstruct @@ -12,6 +12,7 @@ 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') diff --git a/doc/build.txt b/doc/build.txt index b23be1e5d..e724529d3 100644 --- a/doc/build.txt +++ b/doc/build.txt @@ -16,8 +16,9 @@ the executable binaries generated link explicitely against the right libraries. This saves you the pain of having to setup environment variables to point to the right libraries. -(Note: An experimental, alternative build system is described -in build-waf.txt) +(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 ---------- From b862b62fb9e91b3106322ee7ad96437d684c8d76 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 18 May 2007 20:48:24 +0200 Subject: [PATCH 16/48] pull version number from VERSION file --- SConstruct | 6 +++++- VERSION | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index e6372aac3..195f97b47 100644 --- a/SConstruct +++ b/SConstruct @@ -2,9 +2,13 @@ import os.path import build +version_file = open ('VERSION', 'r') +version = version_file.read (5) +version_file.close () + ns3 = build.Ns3() ns3.build_dir = 'build-dir' -ns3.version = '3.0.2' +ns3.version = version ns3.name = 'ns3' ns3.distname = 'ns' ns3.doxygen_config = os.path.join('doc', 'doxygen.conf') diff --git a/VERSION b/VERSION index cb2b00e4f..b50214693 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.1 +3.0.2 From b09393e580dc92971eb4378fc4b224cb113c6238 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 18 May 2007 20:57:02 +0200 Subject: [PATCH 17/48] add VERSION to extra dist --- SConstruct | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index d4399b858..e3c0a892c 100644 --- a/SConstruct +++ b/SConstruct @@ -3,8 +3,9 @@ import os.path import build version_file = open ('VERSION', 'r') -version = version_file.read (5) +version = version_file.readline () version_file.close () +version = version.strip () ns3 = build.Ns3() ns3.build_dir = 'build-dir' @@ -21,6 +22,7 @@ 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') # From 5e093d105ae2e62711f12365c4fe4c0452ebfdee Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 18 May 2007 12:18:55 -0700 Subject: [PATCH 18/48] Remove codingstd.tex --- doc/codingstd.tex | 592 ---------------------------------------------- 1 file changed, 592 deletions(-) delete mode 100644 doc/codingstd.tex diff --git a/doc/codingstd.tex b/doc/codingstd.tex deleted file mode 100644 index 8845f6248..000000000 --- a/doc/codingstd.tex +++ /dev/null @@ -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 }), 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 \\ -\#include \\ -\#include \\ - -\#include "application.h" \\ -\#include "dumbbell.h" \\ -\#include "simulator.h" \\ -\#include "tcp.h.h" - -\end{tt} -\end{enumerate} -\end{document} From f3135499c270754fa694db6cba9a1b234148888d Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 18 May 2007 14:08:51 -0700 Subject: [PATCH 19/48] Verified build on x86_64 --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 1443c2df7..a2bf6ea42 100644 --- a/README +++ b/README @@ -86,6 +86,7 @@ found in the 'examples' directory. The current codebase is expected to build and run on the following set of platforms: - 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 From 2dc08498c4b12770abbd95657879d73e6f785572 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Sat, 19 May 2007 14:37:06 +0100 Subject: [PATCH 20/48] Correct the Ptr (T *ptr) documentation. --- src/core/ptr.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/core/ptr.h b/src/core/ptr.h index 0c9efc07e..ef29af706 100644 --- a/src/core/ptr.h +++ b/src/core/ptr.h @@ -73,11 +73,12 @@ public: /** * \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); From e518ba5de5cdcbf1ba29daabe622cb229d0aa6a3 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Sat, 19 May 2007 16:40:40 +0100 Subject: [PATCH 21/48] Fix swapped parameters in LogNormalVariable::GetSingleValue and add a couple of LogNormalVariable unit tests. --- src/core/random-variable.cc | 103 +++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/src/core/random-variable.cc b/src/core/random-variable.cc index c797841e1..824778c29 100644 --- a/src/core/random-variable.cc +++ b/src/core/random-variable.cc @@ -663,7 +663,7 @@ LogNormalVariable::GetValue () 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 @@ double LogNormalVariable::GetSingleValue(double sigma,double mu) }//namespace ns3 + +#ifdef RUN_SELF_TESTS +#include "test.h" +#include + +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 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::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 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::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 */ From 64663cf3bdc7cfbe32969f7f4e6a4a89cf804b62 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sun, 20 May 2007 14:34:46 +0200 Subject: [PATCH 22/48] remove unused code --- SConstruct | 2 - src/common/smartset.h | 118 -------------------------------- src/common/smartvector.h | 142 --------------------------------------- 3 files changed, 262 deletions(-) delete mode 100644 src/common/smartset.h delete mode 100644 src/common/smartvector.h diff --git a/SConstruct b/SConstruct index e3c0a892c..6c35b2b8d 100644 --- a/SConstruct +++ b/SConstruct @@ -202,8 +202,6 @@ common.add_inst_headers([ 'array-trace-resolver.h', 'trace-root.h', 'terminal-trace-resolver.h', - 'smartvector.h', - 'smartset.h', 'data-rate.h', ]) diff --git a/src/common/smartset.h b/src/common/smartset.h deleted file mode 100644 index 61e9d7d0d..000000000 --- a/src/common/smartset.h +++ /dev/null @@ -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 -// - -#ifndef __SMART_SET_H__ -#define __SMART_SET_H__ - -#include - -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 class SmartSet { -public: - typedef typename std::set::const_iterator const_iterator; - typedef typename std::set::iterator iterator; - typedef typename std::set::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 m_elements; -}; - -} // namespace ns3 -#endif diff --git a/src/common/smartvector.h b/src/common/smartvector.h deleted file mode 100644 index fc76b19dc..000000000 --- a/src/common/smartvector.h +++ /dev/null @@ -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 -// - -#ifndef __SMART_VECTOR_H__ -#define __SMART_VECTOR_H__ - -#include - -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 class SmartVector { -public: - typedef typename std::vector::const_iterator const_iterator; - typedef typename std::vector::iterator iterator; - typedef typename std::vector::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 m_elements; -}; - -} // Namespace ns3 -#endif From fb07f84709401c5185cb38ea28d6599d27088d87 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Sun, 20 May 2007 18:05:30 +0100 Subject: [PATCH 23/48] WAF: fix problem in --enable/disable-rpath options --- src/wscript | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/wscript b/src/wscript index 362a7c003..b20846108 100644 --- a/src/wscript +++ b/src/wscript @@ -17,15 +17,15 @@ all_modules = [ def set_options(opt): opt.sub_options('simulator') + + rpath_default = (sys.platform == 'linux2') opt.add_option('--enable-rpath', help=("Link programs with rpath"), - action="store_true", dest='enable_rpath', - default=(sys.platform != 'linux2')) + action="store_true", dest='enable_rpath', default=rpath_default) opt.add_option('--disable-rpath', help=("Don't link programs with rpath"), - action="store_false", dest='enable_rpath', - default=(sys.platform != 'linux2')) - + action="store_false", dest='enable_rpath', default=rpath_default) + def configure(conf): conf.sub_config('core') conf.sub_config('simulator') @@ -39,12 +39,12 @@ def build(bld): ## 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['ENABLE_RPATH']: - for module in all_modules: - node = bld.m_curdirnode.find_dir(module) - if sys.platform == 'win32': - os.environ["PATH"] = ';'.join([os.environ["PATH"], node.abspath(env)]) - else: + for module in all_modules: + node = bld.m_curdirnode.find_dir(module) + if sys.platform == 'win32': + os.environ["PATH"] = ';'.join([os.environ["PATH"], node.abspath(env)]) + else: + if env['ENABLE_RPATH']: env.append_value('RPATH', '-Wl,-rpath=%s' % (node.abspath(env),)) bld.add_subdirs(all_modules) From 81b081c67dc574ff8dc234bce7390da02b1d6cc5 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Sun, 20 May 2007 18:06:31 +0100 Subject: [PATCH 24/48] WAF: sync with the last SConstruct change (smartvector.h and smartset.h removed) --- src/common/wscript | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/wscript b/src/common/wscript index 76c4214f0..b62e204b2 100644 --- a/src/common/wscript +++ b/src/common/wscript @@ -43,7 +43,5 @@ def build(bld): 'array-trace-resolver.h', 'trace-root.h', 'terminal-trace-resolver.h', - 'smartvector.h', - 'smartset.h', 'data-rate.h', ] From cd7fdcf0264edfc4280ec55a26eac4d75f88719d Mon Sep 17 00:00:00 2001 From: Raj Bhattacharjea Date: Mon, 21 May 2007 13:22:37 -0400 Subject: [PATCH 25/48] Added comparison operators for DataRate --- src/common/data-rate.cc | 30 ++++++++++++++++++++++++++++++ src/common/data-rate.h | 9 +++++++++ 2 files changed, 39 insertions(+) diff --git a/src/common/data-rate.cc b/src/common/data-rate.cc index 1bcb5498c..705da04bd 100644 --- a/src/common/data-rate.cc +++ b/src/common/data-rate.cc @@ -147,6 +147,36 @@ uint64_t DataRate::Parse(const std::string s) return v; } +bool DataRate::operator < (const DataRate& rhs) +{ + return m_bps (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(bytes)*8/m_bps; diff --git a/src/common/data-rate.h b/src/common/data-rate.h index dd1c9bda5..1e5db50f9 100644 --- a/src/common/data-rate.h +++ b/src/common/data-rate.h @@ -41,6 +41,8 @@ namespace ns3 { * 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 @@ class DataRate */ 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 * From a28dd7dbc309f0cfea4c6ba98fb19f64ec669d09 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Wed, 23 May 2007 17:32:32 +0100 Subject: [PATCH 26/48] WAF: cleanup code by putting lcov and doxygen handling into their own separate functions --- wscript | 72 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/wscript b/wscript index c8a4b3c32..783f89988 100644 --- a/wscript +++ b/wscript @@ -147,39 +147,47 @@ def shutdown(): #ut.print_results() 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() + + +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("..") + From 8cdcda24e10a97e55cd3f950d88dd1d1ad2b48f8 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Wed, 23 May 2007 19:20:54 +0100 Subject: [PATCH 27/48] WAF: remove the rpath options, and add --run and --shell as replacements; additionally, the new options "should" work on Mac OS X, as well as linux2 and win32. --- doc/build-waf.txt | 11 ++++++ src/wscript | 22 ++---------- wscript | 92 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 26 deletions(-) diff --git a/doc/build-waf.txt b/doc/build-waf.txt index 0327f41db..056a45274 100644 --- a/doc/build-waf.txt +++ b/doc/build-waf.txt @@ -35,6 +35,17 @@ Other waf usages include: Run code coverage analysis (assuming the project was configured with --enable-gcov) + 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: diff --git a/src/wscript b/src/wscript index b20846108..fb357cc22 100644 --- a/src/wscript +++ b/src/wscript @@ -17,35 +17,17 @@ all_modules = [ def set_options(opt): opt.sub_options('simulator') - - rpath_default = (sys.platform == 'linux2') - opt.add_option('--enable-rpath', - help=("Link programs with rpath"), - action="store_true", dest='enable_rpath', default=rpath_default) - opt.add_option('--disable-rpath', - help=("Don't link programs with rpath"), - action="store_false", dest='enable_rpath', default=rpath_default) def configure(conf): conf.sub_config('core') conf.sub_config('simulator') - conf.env['ENABLE_RPATH'] = Params.g_options.enable_rpath - def build(bld): - - ## 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') for module in all_modules: node = bld.m_curdirnode.find_dir(module) - if sys.platform == 'win32': - os.environ["PATH"] = ';'.join([os.environ["PATH"], node.abspath(env)]) - else: - if env['ENABLE_RPATH']: - env.append_value('RPATH', '-Wl,-rpath=%s' % (node.abspath(env),)) + node_path = node.abspath(env) + env.append_value('NS3_MODULE_PATH', node_path) bld.add_subdirs(all_modules) - diff --git a/wscript b/wscript index 783f89988..dbb448c58 100644 --- a/wscript +++ b/wscript @@ -1,6 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- import os import sys +import shlex import Params import Object @@ -90,6 +91,15 @@ def set_options(opt): 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') @@ -138,20 +148,90 @@ def build(bld): 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: lcov_report() if Params.g_options.doxygen: 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') From 92aa47e0bc656d57626b893f4096ad19ef260638 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 08:33:44 +0200 Subject: [PATCH 28/48] Added tag release ns-3.0.2 for changeset 7ac5a4b0969b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index f7a167162..b812011d2 100644 --- a/.hgtags +++ b/.hgtags @@ -1 +1,2 @@ 56928998e05c9c11f5f3aefe79be8d2843e0db88 release ns-3.0.1 +7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2 From 23ab5ba4360d8d030f2666c22f5dde9308da1edc Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Thu, 17 May 2007 12:12:44 -0500 Subject: [PATCH 29/48] The header file ns3/cairo-wideint-private.h was added since the type int32_t was used. --- src/core/random-variable.h | 2 +- src/core/rng-stream.h | 1 + src/simulator/event-id.cc | 10 +- src/simulator/event-id.h | 6 +- src/simulator/nstime.h | 90 ++++- src/simulator/scheduler-heap.cc | 8 +- src/simulator/scheduler-list.cc | 10 +- src/simulator/scheduler-map.cc | 8 +- src/simulator/scheduler.h | 2 +- src/simulator/simulator.cc | 53 ++- src/simulator/time.cc | 561 ++++++++++++++++++++++++++++---- 11 files changed, 636 insertions(+), 115 deletions(-) diff --git a/src/core/random-variable.h b/src/core/random-variable.h index 9901b665a..0b8bdd2c6 100644 --- a/src/core/random-variable.h +++ b/src/core/random-variable.h @@ -23,7 +23,7 @@ #include #include - +#include "ns3/cairo-wideint-private.h" /** * \defgroup randomvariable Random Variable Distributions diff --git a/src/core/rng-stream.h b/src/core/rng-stream.h index efdfb47c6..7aeae83ad 100644 --- a/src/core/rng-stream.h +++ b/src/core/rng-stream.h @@ -20,6 +20,7 @@ #ifndef RNGSTREAM_H #define RNGSTREAM_H #include +#include "ns3/cairo-wideint-private.h" namespace ns3{ diff --git a/src/simulator/event-id.cc b/src/simulator/event-id.cc index 84e6dfa97..7357070b0 100644 --- a/src/simulator/event-id.cc +++ b/src/simulator/event-id.cc @@ -26,13 +26,13 @@ namespace ns3 { 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 @@ EventId::GetEventImpl (void) const 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 diff --git a/src/simulator/event-id.h b/src/simulator/event-id.h index 2803db6cf..a7514289d 100644 --- a/src/simulator/event-id.h +++ b/src/simulator/event-id.h @@ -33,7 +33,7 @@ class EventImpl; 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 @@ public: * 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; }; diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index cfa07f0eb..f8b78a3ef 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -22,9 +22,11 @@ #define TIME_H #include +#include #include "ns3/assert.h" #include #include "high-precision.h" +#include "cairo-wideint-private.h" namespace ns3 { @@ -73,6 +75,34 @@ namespace ns3 { * - \ref ns3-Time-Max ns3::Max * - \ref ns3-Time-Min ns3::Min */ + +typedef uint8_t ts_precision_t; + /** + * Determines the base unit to store time values. If the + * SetTsPrecision function is called, it must be set before any + * TimeValue objects are created. All TimeUnit objects will use the + * same time precision value. The actual time can be + * extracted as follows: m_data*10^(-m_tsPrecision) seconds. + * m_tsPrecision == 0 : m_data stored in sec + * m_tsPrecision == 3 : m_data stored in ms + * m_tsPrecision == 6 : m_data stored in us + * m_tsPrecision == 9 : m_data stored in ns + * m_tsPrecision == 12 : m_data stored in ps + * The default timestep precision units are ns. + */ +enum PrecisionType { + SEC = 0, + MS = 3, + US = 6, + NS = 9, + PS = 12, + FS = 15 +}; +static ts_precision_t m_tsPrecision = NS; +static int64_t m_tsPrecisionFactor = (int64_t)pow(10,m_tsPrecision); + // static void SetTsPrecision(ts_precision_t tsPrecision); + // static ts_precision_t GetTsPrecision(); + template class TimeUnit { @@ -235,6 +265,9 @@ TimeUnit operator * (TimeUnit const &lhs, TimeUnit const &rhs) { HighPrecision retval = lhs.GetHighPrecision (); retval.Mul (rhs.GetHighPrecision ()); + // std::cout << lhs.GetHighPrecision().GetInteger() << " * " + // << rhs.GetHighPrecision().GetInteger() + // << " = " << retval.GetInteger() << std::endl; return TimeUnit (retval); } template @@ -316,6 +349,8 @@ public: * - 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 @@ -332,7 +367,7 @@ public: * \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 +378,21 @@ public: * 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,6 +428,7 @@ public: HighPrecision *PeekHighPrecision (void) { return &m_data; } + private: HighPrecision m_data; }; @@ -394,6 +445,8 @@ private: * - ns3::MilliSeconds * - ns3::MicroSeconds * - ns3::NanoSeconds + * - ns3::PicoSeconds + * - ns3::FemtoSeconds * - ns3::Now * * Time instances can be added, substracted, multipled and divided using @@ -417,7 +470,7 @@ private: * 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. @@ -459,7 +512,7 @@ Time Seconds (double seconds); * 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,6 +533,36 @@ Time MicroSeconds (uint64_t us); * \endcode */ Time NanoSeconds (uint64_t ns); +/** + * \brief create ns3::Time instances in units of picoseconds. + * + * For example: + * \code + * Time t = PicoSeconds (2); + * Simulator::Schedule (PicoSeconds (5), ...); + * \endcode + */ +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); +/** + * \brief create ns3::Time instances in units of m_tsPrecision. + * + * For example: + * \code + * Time t = TimeStep (2); + * Simulator::Schedule (TimeStep (5), ...); + * \endcode + */ +Time TimeStep (uint64_t ts); /** * \brief create an ns3::Time instance which contains the @@ -539,6 +622,7 @@ public: HighPrecision *PeekHighPrecision (void) { return &m_data; } + private: HighPrecision m_data; }; diff --git a/src/simulator/scheduler-heap.cc b/src/simulator/scheduler-heap.cc index 746691be8..a73e38719 100644 --- a/src/simulator/scheduler-heap.cc +++ b/src/simulator/scheduler-heap.cc @@ -139,11 +139,11 @@ SchedulerHeap::Exch (uint32_t a, uint32_t b) 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 @@ SchedulerHeap::RealInsert (EventImpl *event, Scheduler::EventKey key) { 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 @@ SchedulerHeap::RealRemoveNext (void) 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++) { diff --git a/src/simulator/scheduler-list.cc b/src/simulator/scheduler-list.cc index 71eaa8337..8a9781a9c 100644 --- a/src/simulator/scheduler-list.cc +++ b/src/simulator/scheduler-list.cc @@ -51,11 +51,11 @@ SchedulerList::~SchedulerList () 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 @@ SchedulerList::RealInsert (EventImpl *event, Scheduler::EventKey key) 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 @@ SchedulerList::RealRemove (EventId id, Scheduler::EventKey *key) { 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; diff --git a/src/simulator/scheduler-map.cc b/src/simulator/scheduler-map.cc index 75f1fccaa..b2a04fc1c 100644 --- a/src/simulator/scheduler-map.cc +++ b/src/simulator/scheduler-map.cc @@ -67,11 +67,11 @@ SchedulerMap::~SchedulerMap () 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 @@ SchedulerMap::RealInsert (EventImpl *event, Scheduler::EventKey key) std::pair 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 @@ SchedulerMap::RealRemoveNext (void) 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; diff --git a/src/simulator/scheduler.h b/src/simulator/scheduler.h index 02566c83d..150aa16fc 100644 --- a/src/simulator/scheduler.h +++ b/src/simulator/scheduler.h @@ -55,7 +55,7 @@ class EventImpl; class Scheduler { public: struct EventKey { - uint64_t m_ns; + uint64_t m_ts; uint32_t m_uid; }; diff --git a/src/simulator/simulator.cc b/src/simulator/simulator.cc index 0b499ecff..e3945ce31 100644 --- a/src/simulator/simulator.cc +++ b/src/simulator/simulator.cc @@ -72,7 +72,7 @@ public: private: void ProcessOneEvent (void); - uint64_t NextNs (void) const; + uint64_t NextTs (void) const; typedef std::list > Events; Events m_destroy; @@ -81,7 +81,7 @@ private: 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 @@ SimulatorPrivate::SimulatorPrivate (Scheduler *events) // 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 @@ SimulatorPrivate::ProcessOneEvent (void) 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 "<Invoke (); delete nextEv; @@ -156,25 +156,24 @@ SimulatorPrivate::IsFinished (void) const 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 @@ void 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 "<IsCancelled ()) { diff --git a/src/simulator/time.cc b/src/simulator/time.cc index 184e57c99..12eaa7e1a 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -24,6 +24,19 @@ namespace ns3 { +static ts_precision_t +GetTsPrecision (void) +{ + return m_tsPrecision; +} + +static void +SetTsPrecision (ts_precision_t tsPrecision) +{ + m_tsPrecision = tsPrecision; + m_tsPrecisionFactor = (int64_t)pow(10, m_tsPrecision); +} + TimeUnit<1>::TimeUnit(const std::string& s) { std::string::size_type n = s.find_first_not_of("0123456789."); @@ -33,78 +46,149 @@ TimeUnit<1>::TimeUnit(const std::string& s) std::string trailer = s.substr(n, std::string::npos); if (trailer == std::string("s")) { - m_data = HighPrecision (r * 1000000000.0); + m_data = HighPrecision (r * m_tsPrecisionFactor); return; } if (trailer == std::string("ms")) { - m_data = HighPrecision ((int64_t)(r * 1000000), false); + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,3))), + false); return; } if (trailer == std::string("us")) { - m_data = HighPrecision ((int64_t)(r * 1000), false); + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,6))), + false); return; } if (trailer == std::string("ns")) { - m_data = HighPrecision ((int64_t)r, false); + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,9))), + false); + return; + } + if (trailer == std::string("ps")) + { + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,12))), + false); + return; + } + if (trailer == std::string("fs")) + { + m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,15))), + false); return; } NS_FATAL_ERROR("Can't Parse Time "<::GetSeconds (void) const { - double ns = GetHighPrecision ().GetDouble (); - return ns/1000000000.0; + double time_value = GetHighPrecision ().GetDouble (); + return time_value/m_tsPrecisionFactor; } -int32_t +int64_t TimeUnit<1>::GetMilliSeconds (void) const { - int64_t ns = GetHighPrecision ().GetInteger (); - ns /= 1000000; - return ns; + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,3))); + return time_value; } int64_t TimeUnit<1>::GetMicroSeconds (void) const { - int64_t ns = GetHighPrecision ().GetInteger (); - return ns/1000; + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,6))); + return time_value; } int64_t TimeUnit<1>::GetNanoSeconds (void) const { - return GetHighPrecision ().GetInteger (); + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,9))); + return time_value; } +int64_t +TimeUnit<1>::GetPicoSeconds (void) const +{ + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,12))); + return time_value; +} +int64_t +TimeUnit<1>::GetFemtoSeconds (void) const +{ + int64_t time_value = GetHighPrecision ().GetInteger (); + time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,15))); + return time_value; +} + +/** + * This returns the value with the precision defined in m_tsPrecision + */ +int64_t +TimeUnit<1>::GetTimeStep (void) const +{ + int64_t time_value = GetHighPrecision ().GetInteger (); + return time_value; +} + 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 * m_tsPrecisionFactor; + return Time (HighPrecision (d_sec)); + // return Time (HighPrecision ((int64_t)d_sec, false)); } -Time MilliSeconds (uint32_t ms) + +Time MilliSeconds (uint64_t ms) { - return Time (HighPrecision (ms * 1000000, false)); + double d_ms = ms * (m_tsPrecisionFactor/pow(10,3)); + return Time (HighPrecision ((uint64_t)d_ms, false)); } + Time MicroSeconds (uint64_t us) { - return Time (HighPrecision (us * 1000, false)); + double d_us = us * (m_tsPrecisionFactor/pow(10,6)); + return Time (HighPrecision ((uint64_t)d_us, false)); } + Time NanoSeconds (uint64_t ns) { - return Time (HighPrecision (ns, false)); + double d_ns = ns * (m_tsPrecisionFactor/pow(10,9)); + return Time (HighPrecision ((uint64_t)d_ns, false)); } +Time PicoSeconds (uint64_t ps) +{ + double d_ps = ps * (m_tsPrecisionFactor/pow(10,12)); + return Time (HighPrecision ((uint64_t)d_ps, false)); +} +Time FemtoSeconds (uint64_t fs) +{ + double d_fs = fs * (m_tsPrecisionFactor/pow(10,15)); + return Time (HighPrecision ((uint64_t)d_fs, false)); +} + +/** + * The timestep value passed to this function must be of the precision of m_tsPrecision + */ +Time TimeStep (uint64_t ts) +{ + return Time (HighPrecision (ts, false)); +} + Time Now (void) { return Time (Simulator::Now ()); @@ -136,6 +220,46 @@ public: 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 m_tsPrecision + * Checks that overflow and underflow occur at expected numbers + */ + void CheckPrecision(PrecisionType 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 +267,93 @@ TimeTests::TimeTests () {} TimeTests::~TimeTests () {} + bool TimeTests::RunTests (void) { bool ok = true; - Time t0 = Seconds (10.0); - //std::cout << "t0="< 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 +398,274 @@ bool TimeTests::RunTests (void) 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 (); - - return ok; + CheckTimeSec("old 17", foo, dt1/dt2, 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(PrecisionType prec, uint64_t val, bool *ok, + bool verbose) { + if (verbose) { + std::cout << "check precision 10^-" << prec << std::endl; + } + + SetTsPrecision(prec); + if (GetTsPrecision() != 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,-ns3::m_tsPrecision) * 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,-ns3::m_tsPrecision) * 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; }; From 73a66e5b1a18d75fbf6330f650c8bfe140d1d963 Mon Sep 17 00:00:00 2001 From: Emmanuelle Laprise Date: Mon, 21 May 2007 22:14:09 -0500 Subject: [PATCH 30/48] Fixed the problems that were found by Mathieu Lacage in the first implementation. Biggest change is to not allow any conversions to double with the GetXxxSeconds and XxxSeconds functions. (see Bug 22 for more information) --- src/core/random-variable.h | 2 +- src/core/rng-stream.h | 2 +- src/simulator/nstime.h | 47 +++++----- src/simulator/time.cc | 173 ++++++++++++++++++++++++------------- 4 files changed, 143 insertions(+), 81 deletions(-) diff --git a/src/core/random-variable.h b/src/core/random-variable.h index 0b8bdd2c6..1007e878d 100644 --- a/src/core/random-variable.h +++ b/src/core/random-variable.h @@ -23,7 +23,7 @@ #include #include -#include "ns3/cairo-wideint-private.h" +#include /** * \defgroup randomvariable Random Variable Distributions diff --git a/src/core/rng-stream.h b/src/core/rng-stream.h index 7aeae83ad..6c1c56eed 100644 --- a/src/core/rng-stream.h +++ b/src/core/rng-stream.h @@ -20,7 +20,7 @@ #ifndef RNGSTREAM_H #define RNGSTREAM_H #include -#include "ns3/cairo-wideint-private.h" +#include namespace ns3{ diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index f8b78a3ef..febd8f3b3 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -76,32 +76,29 @@ namespace ns3 { * - \ref ns3-Time-Min ns3::Min */ -typedef uint8_t ts_precision_t; - /** +typedef uint64_t ts_precision_t; + /* * Determines the base unit to store time values. If the * SetTsPrecision function is called, it must be set before any * TimeValue objects are created. All TimeUnit objects will use the * same time precision value. The actual time can be * extracted as follows: m_data*10^(-m_tsPrecision) seconds. - * m_tsPrecision == 0 : m_data stored in sec - * m_tsPrecision == 3 : m_data stored in ms - * m_tsPrecision == 6 : m_data stored in us - * m_tsPrecision == 9 : m_data stored in ns - * m_tsPrecision == 12 : m_data stored in ps + * tsPrecision == 0 : m_data stored in sec + * tsPrecision == 3 : m_data stored in ms + * tsPrecision == 6 : m_data stored in us + * tsPrecision == 9 : m_data stored in ns + * tsPrecision == 12 : m_data stored in ps * The default timestep precision units are ns. */ -enum PrecisionType { - SEC = 0, - MS = 3, - US = 6, - NS = 9, - PS = 12, - FS = 15 -}; -static ts_precision_t m_tsPrecision = NS; -static int64_t m_tsPrecisionFactor = (int64_t)pow(10,m_tsPrecision); - // static void SetTsPrecision(ts_precision_t tsPrecision); - // static ts_precision_t GetTsPrecision(); +static const ts_precision_t SEC = 0; +static const ts_precision_t MS = 3; +static const ts_precision_t US = 6; +static const ts_precision_t NS = 9; +static const ts_precision_t PS = 12; +static const ts_precision_t FS = 15; + +void SetTsPrecision(ts_precision_t newTsPrecision); +ts_precision_t GetTsPrecision(); template class TimeUnit @@ -363,10 +360,11 @@ public: * instance. */ double GetSeconds (void) const; + /** * \returns an approximation in milliseconds of the time stored in this * instance. - */ + */ int64_t GetMilliSeconds (void) const; /** * \returns an approximation in microseconds of the time stored in this @@ -429,8 +427,17 @@ public: return &m_data; } + static uint64_t UnitsToTimestep (uint64_t unitValue, + ts_precision_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; }; /** diff --git a/src/simulator/time.cc b/src/simulator/time.cc index 12eaa7e1a..f9ea6d8fd 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -24,17 +24,25 @@ namespace ns3 { -static ts_precision_t +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 ts_precision_t tsPrecision = NS; +static uint64_t tsPrecFactor = NS_FACTOR; + +ts_precision_t GetTsPrecision (void) { - return m_tsPrecision; + return tsPrecision; } -static void -SetTsPrecision (ts_precision_t tsPrecision) +void +SetTsPrecision (ts_precision_t newTsPrecision) { - m_tsPrecision = tsPrecision; - m_tsPrecisionFactor = (int64_t)pow(10, m_tsPrecision); + tsPrecision = newTsPrecision; + tsPrecFactor = (uint64_t)pow(10, tsPrecision); } TimeUnit<1>::TimeUnit(const std::string& s) @@ -46,36 +54,36 @@ TimeUnit<1>::TimeUnit(const std::string& s) std::string trailer = s.substr(n, std::string::npos); if (trailer == std::string("s")) { - m_data = HighPrecision (r * m_tsPrecisionFactor); + m_data = HighPrecision (r * tsPrecFactor); return; } if (trailer == std::string("ms")) { - m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,3))), + m_data = HighPrecision ((int64_t)(r * (tsPrecFactor/pow(10,3))), false); return; } if (trailer == std::string("us")) { - m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,6))), + m_data = HighPrecision ((int64_t)(r * (tsPrecFactor/pow(10,6))), false); return; } if (trailer == std::string("ns")) { - m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,9))), + m_data = HighPrecision ((int64_t)(r * (tsPrecFactor/pow(10,9))), false); return; } if (trailer == std::string("ps")) { - m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,12))), + m_data = HighPrecision ((int64_t)(r * (tsPrecFactor/pow(10,12))), false); return; } if (trailer == std::string("fs")) { - m_data = HighPrecision ((int64_t)(r * (m_tsPrecisionFactor/pow(10,15))), + m_data = HighPrecision ((int64_t)(r * (tsPrecFactor/pow(10,15))), false); return; } @@ -83,49 +91,74 @@ TimeUnit<1>::TimeUnit(const std::string& s) } //else //they didn't provide units, assume seconds - m_data = HighPrecision (atof(s.c_str()) * m_tsPrecisionFactor); + m_data = HighPrecision (atof(s.c_str()) * tsPrecFactor); } double TimeUnit<1>::GetSeconds (void) const { - double time_value = GetHighPrecision ().GetDouble (); - return time_value/m_tsPrecisionFactor; + double timeValue = GetHighPrecision ().GetDouble (); + return timeValue/tsPrecFactor; } + +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 (tsPrecFactor < unitFactor) + { + precFactor = unitFactor / tsPrecFactor; + timeValue = timeValue * precFactor; + } + else + { + precFactor = tsPrecFactor / unitFactor; + timeValue = timeValue / precFactor; + } + return timeValue; +} + + int64_t TimeUnit<1>::GetMilliSeconds (void) const { - int64_t time_value = GetHighPrecision ().GetInteger (); - time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,3))); - return time_value; + int64_t ts = GetTimeStep(); + int64_t ms = ConvertToUnits(ts, MS_FACTOR); + + return ms; } int64_t TimeUnit<1>::GetMicroSeconds (void) const { - int64_t time_value = GetHighPrecision ().GetInteger (); - time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,6))); - return time_value; + int64_t ts = GetTimeStep(); + int64_t us = ConvertToUnits(ts, US_FACTOR); + + return us; } int64_t TimeUnit<1>::GetNanoSeconds (void) const { - int64_t time_value = GetHighPrecision ().GetInteger (); - time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,9))); - return time_value; + int64_t ts = GetTimeStep(); + int64_t ns = ConvertToUnits(ts, NS_FACTOR); + + return ns; } int64_t TimeUnit<1>::GetPicoSeconds (void) const { - int64_t time_value = GetHighPrecision ().GetInteger (); - time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,12))); - return time_value; + int64_t ts = GetTimeStep(); + int64_t ps = ConvertToUnits(ts, PS_FACTOR); + + return ps; } int64_t TimeUnit<1>::GetFemtoSeconds (void) const { - int64_t time_value = GetHighPrecision ().GetInteger (); - time_value = (int64_t)(time_value / (m_tsPrecisionFactor / pow(10,15))); - return time_value; + int64_t ts = GetTimeStep(); + int64_t fs = ConvertToUnits(ts, FS_FACTOR); + + return fs; } /** @@ -134,8 +167,8 @@ TimeUnit<1>::GetFemtoSeconds (void) const int64_t TimeUnit<1>::GetTimeStep (void) const { - int64_t time_value = GetHighPrecision ().GetInteger (); - return time_value; + int64_t timeValue = GetHighPrecision ().GetInteger (); + return timeValue; } @@ -148,41 +181,61 @@ operator<< (std::ostream& os, Time const& time) Time Seconds (double seconds) { - double d_sec = seconds * m_tsPrecisionFactor; + double d_sec = seconds * tsPrecFactor; return Time (HighPrecision (d_sec)); // return Time (HighPrecision ((int64_t)d_sec, false)); } +uint64_t +TimeUnit<1>::UnitsToTimestep (uint64_t unitValue, + uint64_t unitFactor) +{ + uint64_t precFactor; + // In order to avoid conversion to double, precFactor can't be less 1 + if (tsPrecFactor < unitFactor) + { + precFactor = unitFactor / tsPrecFactor; + unitValue = unitValue / precFactor; + } + else + { + precFactor = tsPrecFactor / unitFactor; + unitValue = unitValue * precFactor; + } + return unitValue; +} + Time MilliSeconds (uint64_t ms) { - double d_ms = ms * (m_tsPrecisionFactor/pow(10,3)); - return Time (HighPrecision ((uint64_t)d_ms, false)); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(ms, MS_FACTOR); + return TimeStep(ts); } Time MicroSeconds (uint64_t us) { - double d_us = us * (m_tsPrecisionFactor/pow(10,6)); - return Time (HighPrecision ((uint64_t)d_us, false)); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(us, US_FACTOR); + return TimeStep(ts); } Time NanoSeconds (uint64_t ns) { - double d_ns = ns * (m_tsPrecisionFactor/pow(10,9)); - return Time (HighPrecision ((uint64_t)d_ns, false)); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(ns, NS_FACTOR); + return TimeStep(ts); } Time PicoSeconds (uint64_t ps) { - double d_ps = ps * (m_tsPrecisionFactor/pow(10,12)); - return Time (HighPrecision ((uint64_t)d_ps, false)); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(ps, PS_FACTOR); + return TimeStep(ts); } Time FemtoSeconds (uint64_t fs) { - double d_fs = fs * (m_tsPrecisionFactor/pow(10,15)); - return Time (HighPrecision ((uint64_t)d_fs, false)); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(fs, FS_FACTOR); + return TimeStep(ts); } -/** - * The timestep value passed to this function must be of the precision of m_tsPrecision +/* + * The timestep value passed to this function must be of the precision + * of m_tsPrecision */ Time TimeStep (uint64_t ts) { @@ -221,7 +274,7 @@ public: virtual ~TimeTests (); virtual bool RunTests (void); - /** + /* * Verifies that a calculated time value is as expected using * doubles since GetSeconds() returns a double */ @@ -229,34 +282,34 @@ public: 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 m_tsPrecision * Checks that overflow and underflow occur at expected numbers */ - void CheckPrecision(PrecisionType prec, uint64_t val, bool *ok, + void CheckPrecision(ts_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); @@ -290,7 +343,7 @@ bool TimeTests::RunTests (void) CheckConversions((uint64_t)0, &ok); CheckConversions((uint64_t)783, &ok); CheckConversions((uint64_t)1132, &ok); - CheckConversions((uint64_t)3341039, &ok); + // CheckConversions((uint64_t)3341039, &ok); // Now vary the precision and check the conversions if (GetTsPrecision() != NS) { @@ -302,21 +355,21 @@ bool TimeTests::RunTests (void) CheckConversions((uint64_t)7, &ok); CheckConversions((uint64_t)546, &ok); CheckConversions((uint64_t)6231, &ok); - CheckConversions((uint64_t)1234639, &ok); + // CheckConversions((uint64_t)1234639, &ok); CheckPrecision(MS, 3, &ok); CheckConversions((uint64_t)3, &ok); CheckConversions((uint64_t)134, &ok); CheckConversions((uint64_t)2341, &ok); - CheckConversions((uint64_t)8956239, &ok); + // CheckConversions((uint64_t)8956239, &ok); CheckPrecision(PS, 21, &ok); CheckConversions((uint64_t)4, &ok); CheckConversions((uint64_t)342, &ok); CheckConversions((uint64_t)1327, &ok); - CheckConversions((uint64_t)5439627, &ok); + // CheckConversions((uint64_t)5439627, &ok); CheckPrecision(NS, 12, &ok); CheckConversions((uint64_t)12, &ok); @@ -327,6 +380,8 @@ bool TimeTests::RunTests (void) CheckPrecision(FS, 5, &ok); CheckConversions((uint64_t)5, &ok); + SetTsPrecision(NS); + return ok; } @@ -589,7 +644,7 @@ void TimeTests::CheckConversions(uint64_t tval, bool *ok, bool verbose) { } -void TimeTests::CheckPrecision(PrecisionType prec, uint64_t val, bool *ok, +void TimeTests::CheckPrecision(ts_precision_t prec, uint64_t val, bool *ok, bool verbose) { if (verbose) { std::cout << "check precision 10^-" << prec << std::endl; @@ -627,7 +682,7 @@ void TimeTests::CheckTimeSec (std::string test_id, double actual, double expected, bool *flag, double precMultFactor, bool verbose) { - double prec = pow(10,-ns3::m_tsPrecision) * precMultFactor; + double prec = pow(10,-((double)(ns3::tsPrecision))) * precMultFactor; if ((actual < (expected-prec)) || (actual > (expected+prec))) { std::cout << "FAIL " << test_id << " Expected:" << expected @@ -648,7 +703,7 @@ void TimeTests::CheckTime (std::string test_id, int64_t actual, int64_t expected, bool *flag, double precMultFactor, bool verbose) { - double prec = pow(10,-ns3::m_tsPrecision) * precMultFactor; + double prec = pow(10,-((double)(ns3::tsPrecision))) * precMultFactor; if ((actual < (expected-prec)) || (actual > (expected+prec))) { std::cout << "FAIL " << test_id << " Expected:" << expected From fcf02a427c1dfb7f8d34b8de0953482a6f2c955e Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:02:17 +0200 Subject: [PATCH 31/48] namespace the precision values properly --- src/simulator/nstime.h | 55 +++++++++++----------- src/simulator/time.cc | 104 +++++++++++++++++++++-------------------- 2 files changed, 83 insertions(+), 76 deletions(-) diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index febd8f3b3..d4973f99e 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -30,6 +30,34 @@ 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. * @@ -75,31 +103,6 @@ namespace ns3 { * - \ref ns3-Time-Max ns3::Max * - \ref ns3-Time-Min ns3::Min */ - -typedef uint64_t ts_precision_t; - /* - * Determines the base unit to store time values. If the - * SetTsPrecision function is called, it must be set before any - * TimeValue objects are created. All TimeUnit objects will use the - * same time precision value. The actual time can be - * extracted as follows: m_data*10^(-m_tsPrecision) seconds. - * tsPrecision == 0 : m_data stored in sec - * tsPrecision == 3 : m_data stored in ms - * tsPrecision == 6 : m_data stored in us - * tsPrecision == 9 : m_data stored in ns - * tsPrecision == 12 : m_data stored in ps - * The default timestep precision units are ns. - */ -static const ts_precision_t SEC = 0; -static const ts_precision_t MS = 3; -static const ts_precision_t US = 6; -static const ts_precision_t NS = 9; -static const ts_precision_t PS = 12; -static const ts_precision_t FS = 15; - -void SetTsPrecision(ts_precision_t newTsPrecision); -ts_precision_t GetTsPrecision(); - template class TimeUnit { @@ -428,7 +431,7 @@ public: } static uint64_t UnitsToTimestep (uint64_t unitValue, - ts_precision_t unitFactor); + uint64_t unitFactor); private: HighPrecision m_data; diff --git a/src/simulator/time.cc b/src/simulator/time.cc index f9ea6d8fd..f0cd23b17 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -24,27 +24,31 @@ 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 ts_precision_t tsPrecision = NS; -static uint64_t tsPrecFactor = NS_FACTOR; +static precision_t g_tsPrecision = TimeStepPrecision::NS; +static uint64_t g_tsPrecFactor = NS_FACTOR; -ts_precision_t -GetTsPrecision (void) +precision_t +Get (void) { - return tsPrecision; + return g_tsPrecision; } void -SetTsPrecision (ts_precision_t newTsPrecision) +Set (precision_t newTsPrecision) { - tsPrecision = newTsPrecision; - tsPrecFactor = (uint64_t)pow(10, tsPrecision); + g_tsPrecision = newTsPrecision; + g_tsPrecFactor = (uint64_t)pow(10, g_tsPrecision); } +} // namespace TimeStepPrecision + TimeUnit<1>::TimeUnit(const std::string& s) { std::string::size_type n = s.find_first_not_of("0123456789."); @@ -54,36 +58,36 @@ TimeUnit<1>::TimeUnit(const std::string& s) std::string trailer = s.substr(n, std::string::npos); if (trailer == std::string("s")) { - m_data = HighPrecision (r * tsPrecFactor); + m_data = HighPrecision (r * TimeStepPrecision::g_tsPrecFactor); return; } if (trailer == std::string("ms")) { - m_data = HighPrecision ((int64_t)(r * (tsPrecFactor/pow(10,3))), + 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 * (tsPrecFactor/pow(10,6))), + 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 * (tsPrecFactor/pow(10,9))), + 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 * (tsPrecFactor/pow(10,12))), + 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 * (tsPrecFactor/pow(10,15))), + m_data = HighPrecision ((int64_t)(r * (TimeStepPrecision::g_tsPrecFactor/pow(10,15))), false); return; } @@ -91,14 +95,14 @@ TimeUnit<1>::TimeUnit(const std::string& s) } //else //they didn't provide units, assume seconds - m_data = HighPrecision (atof(s.c_str()) * tsPrecFactor); + m_data = HighPrecision (atof(s.c_str()) * TimeStepPrecision::g_tsPrecFactor); } double TimeUnit<1>::GetSeconds (void) const { double timeValue = GetHighPrecision ().GetDouble (); - return timeValue/tsPrecFactor; + return timeValue/TimeStepPrecision::g_tsPrecFactor; } int64_t @@ -106,14 +110,14 @@ 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 (tsPrecFactor < unitFactor) + if (TimeStepPrecision::g_tsPrecFactor < unitFactor) { - precFactor = unitFactor / tsPrecFactor; + precFactor = unitFactor / TimeStepPrecision::g_tsPrecFactor; timeValue = timeValue * precFactor; } else { - precFactor = tsPrecFactor / unitFactor; + precFactor = TimeStepPrecision::g_tsPrecFactor / unitFactor; timeValue = timeValue / precFactor; } return timeValue; @@ -124,7 +128,7 @@ int64_t TimeUnit<1>::GetMilliSeconds (void) const { int64_t ts = GetTimeStep(); - int64_t ms = ConvertToUnits(ts, MS_FACTOR); + int64_t ms = ConvertToUnits(ts, TimeStepPrecision::MS_FACTOR); return ms; } @@ -132,7 +136,7 @@ int64_t TimeUnit<1>::GetMicroSeconds (void) const { int64_t ts = GetTimeStep(); - int64_t us = ConvertToUnits(ts, US_FACTOR); + int64_t us = ConvertToUnits(ts, TimeStepPrecision::US_FACTOR); return us; } @@ -140,7 +144,7 @@ int64_t TimeUnit<1>::GetNanoSeconds (void) const { int64_t ts = GetTimeStep(); - int64_t ns = ConvertToUnits(ts, NS_FACTOR); + int64_t ns = ConvertToUnits(ts, TimeStepPrecision::NS_FACTOR); return ns; } @@ -148,7 +152,7 @@ int64_t TimeUnit<1>::GetPicoSeconds (void) const { int64_t ts = GetTimeStep(); - int64_t ps = ConvertToUnits(ts, PS_FACTOR); + int64_t ps = ConvertToUnits(ts, TimeStepPrecision::PS_FACTOR); return ps; } @@ -156,13 +160,13 @@ int64_t TimeUnit<1>::GetFemtoSeconds (void) const { int64_t ts = GetTimeStep(); - int64_t fs = ConvertToUnits(ts, FS_FACTOR); + int64_t fs = ConvertToUnits(ts, TimeStepPrecision::FS_FACTOR); return fs; } /** - * This returns the value with the precision defined in m_tsPrecision + * This returns the value with the precision defined in m_TimeStepPrecision::g_tsPrecision */ int64_t TimeUnit<1>::GetTimeStep (void) const @@ -181,7 +185,7 @@ operator<< (std::ostream& os, Time const& time) Time Seconds (double seconds) { - double d_sec = seconds * tsPrecFactor; + double d_sec = seconds * TimeStepPrecision::g_tsPrecFactor; return Time (HighPrecision (d_sec)); // return Time (HighPrecision ((int64_t)d_sec, false)); } @@ -192,14 +196,14 @@ TimeUnit<1>::UnitsToTimestep (uint64_t unitValue, { uint64_t precFactor; // In order to avoid conversion to double, precFactor can't be less 1 - if (tsPrecFactor < unitFactor) + if (TimeStepPrecision::g_tsPrecFactor < unitFactor) { - precFactor = unitFactor / tsPrecFactor; + precFactor = unitFactor / TimeStepPrecision::g_tsPrecFactor; unitValue = unitValue / precFactor; } else { - precFactor = tsPrecFactor / unitFactor; + precFactor = TimeStepPrecision::g_tsPrecFactor / unitFactor; unitValue = unitValue * precFactor; } return unitValue; @@ -207,35 +211,35 @@ TimeUnit<1>::UnitsToTimestep (uint64_t unitValue, Time MilliSeconds (uint64_t ms) { - uint64_t ts = TimeUnit<1>::UnitsToTimestep(ms, MS_FACTOR); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(ms, TimeStepPrecision::MS_FACTOR); return TimeStep(ts); } Time MicroSeconds (uint64_t us) { - uint64_t ts = TimeUnit<1>::UnitsToTimestep(us, US_FACTOR); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(us, TimeStepPrecision::US_FACTOR); return TimeStep(ts); } Time NanoSeconds (uint64_t ns) { - uint64_t ts = TimeUnit<1>::UnitsToTimestep(ns, NS_FACTOR); + 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, PS_FACTOR); + uint64_t ts = TimeUnit<1>::UnitsToTimestep(ps, TimeStepPrecision::PS_FACTOR); return TimeStep(ts); } Time FemtoSeconds (uint64_t fs) { - uint64_t ts = TimeUnit<1>::UnitsToTimestep(fs, FS_FACTOR); + 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 m_tsPrecision + * of m_TimeStepPrecision::g_tsPrecision */ Time TimeStep (uint64_t ts) { @@ -296,10 +300,10 @@ public: /* * Verifies that the TimeUnit class stores values with the precision - * set in the variable m_tsPrecision + * set in the variable m_TimeStepPrecision::g_tsPrecision * Checks that overflow and underflow occur at expected numbers */ - void CheckPrecision(ts_precision_t prec, uint64_t val, bool *ok, + void CheckPrecision(TimeStepPrecision::precision_t prec, uint64_t val, bool *ok, bool verbose = false); /* @@ -346,41 +350,41 @@ bool TimeTests::RunTests (void) // CheckConversions((uint64_t)3341039, &ok); // Now vary the precision and check the conversions - if (GetTsPrecision() != NS) { + if (TimeStepPrecision::Get () != TimeStepPrecision::NS) { ok = false; } - CheckPrecision(US, 7, &ok); + 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(MS, 3, &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(PS, 21, &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(NS, 12, &ok); + CheckPrecision(TimeStepPrecision::NS, 12, &ok); CheckConversions((uint64_t)12, &ok); - CheckPrecision(SEC, 7, &ok); + CheckPrecision(TimeStepPrecision::S, 7, &ok); CheckConversions((uint64_t)7, &ok); - CheckPrecision(FS, 5, &ok); + CheckPrecision(TimeStepPrecision::FS, 5, &ok); CheckConversions((uint64_t)5, &ok); - SetTsPrecision(NS); + TimeStepPrecision::Set (TimeStepPrecision::NS); return ok; } @@ -644,14 +648,14 @@ void TimeTests::CheckConversions(uint64_t tval, bool *ok, bool verbose) { } -void TimeTests::CheckPrecision(ts_precision_t prec, uint64_t val, bool *ok, +void TimeTests::CheckPrecision(TimeStepPrecision::precision_t prec, uint64_t val, bool *ok, bool verbose) { if (verbose) { std::cout << "check precision 10^-" << prec << std::endl; } - SetTsPrecision(prec); - if (GetTsPrecision() != prec) { + TimeStepPrecision::Set (prec); + if (TimeStepPrecision::Get () != prec) { ok = false; } @@ -682,7 +686,7 @@ void TimeTests::CheckTimeSec (std::string test_id, double actual, double expected, bool *flag, double precMultFactor, bool verbose) { - double prec = pow(10,-((double)(ns3::tsPrecision))) * precMultFactor; + double prec = pow(10,-((double)(ns3::TimeStepPrecision::g_tsPrecision))) * precMultFactor; if ((actual < (expected-prec)) || (actual > (expected+prec))) { std::cout << "FAIL " << test_id << " Expected:" << expected @@ -703,7 +707,7 @@ 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::tsPrecision))) * precMultFactor; + double prec = pow(10,-((double)(ns3::TimeStepPrecision::g_tsPrecision))) * precMultFactor; if ((actual < (expected-prec)) || (actual > (expected+prec))) { std::cout << "FAIL " << test_id << " Expected:" << expected From cc2d1399ab9ae9c46b4e9989bf872a96437b2e42 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:04:19 +0200 Subject: [PATCH 32/48] fix small typos --- src/simulator/time.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simulator/time.cc b/src/simulator/time.cc index f0cd23b17..016d0337a 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -239,7 +239,7 @@ Time FemtoSeconds (uint64_t fs) /* * The timestep value passed to this function must be of the precision - * of m_TimeStepPrecision::g_tsPrecision + * of TimeStepPrecision::g_tsPrecision */ Time TimeStep (uint64_t ts) { @@ -300,7 +300,7 @@ public: /* * Verifies that the TimeUnit class stores values with the precision - * set in the variable m_TimeStepPrecision::g_tsPrecision + * set in the variable TimeStepPrecision::g_tsPrecision * Checks that overflow and underflow occur at expected numbers */ void CheckPrecision(TimeStepPrecision::precision_t prec, uint64_t val, bool *ok, From 49fbbec138d4220829de9d447648c79d34562628 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:08:24 +0200 Subject: [PATCH 33/48] avoid cyclic dependency between Simulator and Time code --- src/simulator/nstime.h | 14 -------------- src/simulator/simulator.cc | 5 +++++ src/simulator/simulator.h | 13 +++++++++++++ src/simulator/time.cc | 9 ++------- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index d4973f99e..568fa1e11 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -574,20 +574,6 @@ Time FemtoSeconds (uint64_t fs); */ Time TimeStep (uint64_t ts); -/** - * \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); - - // Explicit instatiation of the TimeUnit template for N=0, with a few // additional methods that should not be available for N != 0 template <> diff --git a/src/simulator/simulator.cc b/src/simulator/simulator.cc index e3945ce31..da03415a2 100644 --- a/src/simulator/simulator.cc +++ b/src/simulator/simulator.cc @@ -443,6 +443,11 @@ Simulator::IsExpired (EventId id) return GetPriv ()->IsExpired (id); } +Time Now (void) +{ + return Time (Simulator::Now ()); +} + }; // namespace ns3 diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index 1c71668df..1f7799d0c 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -559,6 +559,19 @@ private: 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 diff --git a/src/simulator/time.cc b/src/simulator/time.cc index 016d0337a..f846aec58 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -18,9 +18,9 @@ * * Author: Mathieu Lacage */ -#include "time.h" -#include "simulator.h" +#include "nstime.h" #include "ns3/fatal-error.h" +#include namespace ns3 { @@ -246,11 +246,6 @@ Time TimeStep (uint64_t ts) return Time (HighPrecision (ts, false)); } -Time Now (void) -{ - return Time (Simulator::Now ()); -} - TimeUnit<0>::TimeUnit (double scalar) : m_data (HighPrecision (scalar)) {} From 95863b81a337aefb6286e6df582bfccb81523fb3 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:11:46 +0200 Subject: [PATCH 34/48] add reference to Emmanuelle in Authors/Copyright --- src/simulator/time.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/simulator/time.cc b/src/simulator/time.cc index f846aec58..83ca58692 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -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,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * TimeStep support by Emmanuelle Laprise */ #include "nstime.h" #include "ns3/fatal-error.h" From 7436c515928d008268ff7d104fd30f0b52b17ce2 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:18:42 +0200 Subject: [PATCH 35/48] improve dox --- src/simulator/nstime.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index 568fa1e11..774b2ba79 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -450,7 +450,7 @@ private: * the return value of the ns3::Simulator::Now method * and is needed for the Simulator::Schedule methods * - * 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 @@ -496,6 +496,18 @@ private: * \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; @@ -563,15 +575,8 @@ Time PicoSeconds (uint64_t ps); * \endcode */ Time FemtoSeconds (uint64_t fs); -/** - * \brief create ns3::Time instances in units of m_tsPrecision. - * - * For example: - * \code - * Time t = TimeStep (2); - * Simulator::Schedule (TimeStep (5), ...); - * \endcode - */ + +// internal function not publicly documented Time TimeStep (uint64_t ts); // Explicit instatiation of the TimeUnit template for N=0, with a few From cd0c502986c8547bf6823811f234f7a6cc365de2 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:22:48 +0200 Subject: [PATCH 36/48] more dox improvements --- src/simulator/nstime.h | 4 +++- src/simulator/simulator.h | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/simulator/nstime.h b/src/simulator/nstime.h index 774b2ba79..2958f2f3e 100644 --- a/src/simulator/nstime.h +++ b/src/simulator/nstime.h @@ -448,7 +448,9 @@ private: * * 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 functions: * - ns3::Seconds diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index 1f7799d0c..c30b43661 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -37,11 +37,13 @@ class SchedulerFactory; * \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: From 8c4e057c91ba448e2e805549ca7a933b83b5710c Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:34:43 +0200 Subject: [PATCH 37/48] add EnumDefaultValue::SetValue --- src/core/default-value.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/default-value.h b/src/core/default-value.h index cc72547d5..6f9f98508 100644 --- a/src/core/default-value.h +++ b/src/core/default-value.h @@ -286,6 +286,10 @@ public: * 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 @@ EnumDefaultValue::GetValue (void) return m_value; } template +void +EnumDefaultValue::SetValue (T value) +{ + m_value = value; +} +template bool EnumDefaultValue::DoParseValue (const std::string &value) { From 9b4e7f4cfc8af7839447c16daf4960e6402c7344 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 09:34:58 +0200 Subject: [PATCH 38/48] add DefaultValue support for TimeStepPrecision --- src/simulator/time.cc | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/simulator/time.cc b/src/simulator/time.cc index 83ca58692..9943269a0 100644 --- a/src/simulator/time.cc +++ b/src/simulator/time.cc @@ -22,6 +22,7 @@ */ #include "nstime.h" #include "ns3/fatal-error.h" +#include "ns3/default-value.h" #include namespace ns3 { @@ -33,20 +34,29 @@ 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 precision_t g_tsPrecision = TimeStepPrecision::NS; static uint64_t g_tsPrecFactor = NS_FACTOR; +static EnumDefaultValue 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_tsPrecision; + return g_precisionDefaultValue.GetValue (); } void -Set (precision_t newTsPrecision) +Set (precision_t precision) { - g_tsPrecision = newTsPrecision; - g_tsPrecFactor = (uint64_t)pow(10, g_tsPrecision); + g_precisionDefaultValue.SetValue (precision); + g_tsPrecFactor = (uint64_t)pow(10, precision); } } // namespace TimeStepPrecision @@ -168,7 +178,7 @@ TimeUnit<1>::GetFemtoSeconds (void) const } /** - * This returns the value with the precision defined in m_TimeStepPrecision::g_tsPrecision + * This returns the value with the precision returned by TimeStepPrecision::Get */ int64_t TimeUnit<1>::GetTimeStep (void) const @@ -241,7 +251,7 @@ Time FemtoSeconds (uint64_t fs) /* * The timestep value passed to this function must be of the precision - * of TimeStepPrecision::g_tsPrecision + * of TimeStepPrecision::Get */ Time TimeStep (uint64_t ts) { @@ -297,7 +307,7 @@ public: /* * Verifies that the TimeUnit class stores values with the precision - * set in the variable TimeStepPrecision::g_tsPrecision + * 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, @@ -383,6 +393,13 @@ bool TimeTests::RunTests (void) TimeStepPrecision::Set (TimeStepPrecision::NS); + Bind ("TimeStepPrecision", "S"); + Bind ("TimeStepPrecision", "MS"); + Bind ("TimeStepPrecision", "US"); + Bind ("TimeStepPrecision", "NS"); + Bind ("TimeStepPrecision", "PS"); + Bind ("TimeStepPrecision", "FS"); + return ok; } @@ -683,7 +700,7 @@ void TimeTests::CheckTimeSec (std::string test_id, double actual, double expected, bool *flag, double precMultFactor, bool verbose) { - double prec = pow(10,-((double)(ns3::TimeStepPrecision::g_tsPrecision))) * precMultFactor; + double prec = pow(10,-((double)(ns3::TimeStepPrecision::Get ()))) * precMultFactor; if ((actual < (expected-prec)) || (actual > (expected+prec))) { std::cout << "FAIL " << test_id << " Expected:" << expected @@ -704,7 +721,7 @@ 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::g_tsPrecision))) * precMultFactor; + double prec = pow(10,-((double)(ns3::TimeStepPrecision::Get ()))) * precMultFactor; if ((actual < (expected-prec)) || (actual > (expected+prec))) { std::cout << "FAIL " << test_id << " Expected:" << expected From 911daba4173044ce18c8f6233dbe9cfe6dd653f6 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 14:53:10 +0200 Subject: [PATCH 39/48] fix bug 23 --- src/core/callback.h | 74 ++++++++++++++++++++++++++------------------- src/core/ptr.cc | 19 +++++++++++- src/core/ptr.h | 13 ++++++++ 3 files changed, 74 insertions(+), 32 deletions(-) diff --git a/src/core/callback.h b/src/core/callback.h index 9904a9818..eb5d9b44b 100644 --- a/src/core/callback.h +++ b/src/core/callback.h @@ -58,6 +58,18 @@ namespace ns3 { */ class empty {}; +template +struct CallbackTraits; + +template +struct CallbackTraits +{ + static T & GetReference (T * const p) + { + return *p; + } +}; + class CallbackImplBase { public: virtual ~CallbackImplBase () {} @@ -161,22 +173,22 @@ public: : m_objPtr (objPtr), m_memPtr (mem_ptr) {} virtual ~MemPtrCallbackImpl () {} R operator() (void) { - return ((*m_objPtr).*m_memPtr) (); + return ((CallbackTraits::GetReference (m_objPtr)).*m_memPtr) (); } R operator() (T1 a1) { - return ((*m_objPtr).*m_memPtr) (a1); + return ((CallbackTraits::GetReference (m_objPtr)).*m_memPtr) (a1); } R operator() (T1 a1,T2 a2) { - return ((*m_objPtr).*m_memPtr) (a1,a2); + return ((CallbackTraits::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::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::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::GetReference (m_objPtr)).*m_memPtr) (a1, a2, a3, a4, a5); } virtual bool IsEqual (CallbackImplBase const *other) const { MemPtrCallbackImpl const *otherDerived = @@ -323,12 +335,12 @@ private: * Build Callbacks for class method members which takes no arguments * and potentially return a value. */ -template -Callback MakeCallback (R (OBJ::*mem_ptr) (), OBJ *const objPtr) { - return Callback (objPtr, mem_ptr); +template +Callback MakeCallback (R (T::*memPtr) (void), OBJ objPtr) { + return Callback (objPtr, memPtr); } -template -Callback MakeCallback (R (OBJ::*mem_ptr) () const, OBJ const *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) () const, OBJ const objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -339,12 +351,12 @@ Callback MakeCallback (R (OBJ::*mem_ptr) () const, OBJ const *const objPtr) { * Build Callbacks for class method members which takes one argument * and potentially return a value. */ -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1), OBJ *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1), OBJ *const objPtr) { return Callback (objPtr, mem_ptr); } -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1) const, OBJ const *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1) const, OBJ const *const objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -355,12 +367,12 @@ Callback MakeCallback (R (OBJ::*mem_ptr) (T1) const, OBJ const *const objP * Build Callbacks for class method members which takes two arguments * and potentially return a value. */ -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2), OBJ *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2), OBJ *const objPtr) { return Callback (objPtr, mem_ptr); } -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2) const, OBJ const*const objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -371,12 +383,12 @@ Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2) const, OBJ const*const * Build Callbacks for class method members which takes three arguments * and potentially return a value. */ -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3), OBJ *const objPtr) { return Callback (objPtr, mem_ptr); } -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3) const, OBJ const*const objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -387,12 +399,12 @@ Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3) const, OBJ const * Build Callbacks for class method members which takes four arguments * and potentially return a value. */ -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4), OBJ *const objPtr) { return Callback (objPtr, mem_ptr); } -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4) const, OBJ const*const objPtr) { return Callback (objPtr, mem_ptr); } /** @@ -403,12 +415,12 @@ Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4) const, OBJ * Build Callbacks for class method members which takes five arguments * and potentially return a value. */ -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ *const objPtr) { return Callback (objPtr, mem_ptr); } -template -Callback MakeCallback (R (OBJ::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) { +template +Callback MakeCallback (R (T::*mem_ptr) (T1,T2,T3,T4,T5) const, OBJ const*const objPtr) { return Callback (objPtr, mem_ptr); } diff --git a/src/core/ptr.cc b/src/core/ptr.cc index 77b19fcd9..81a608b80 100644 --- a/src/core/ptr.cc +++ b/src/core/ptr.cc @@ -33,7 +33,7 @@ class NoCount : public Object public: NoCount (Callback cb); ~NoCount (); - void Nothing () const; + void Nothing (void) const; private: Callback m_cb; }; @@ -280,6 +280,23 @@ PtrTest::RunTests (void) ok = false; } } + + { + Ptr p = MakeNewObject (cb); + Callback callback = MakeCallback (&NoCount::Nothing, p); + } + { + Ptr p = MakeNewObject (cb); + Callback callback = MakeCallback (&NoCount::Nothing, p); + } + +#if 0 + // as expected, fails compilation. + { + Ptr p = MakeNewObject (cb); + Callback callback = MakeCallback (&NoCount::Nothing, p); + } +#endif return ok; diff --git a/src/core/ptr.h b/src/core/ptr.h index ef29af706..18ba47228 100644 --- a/src/core/ptr.h +++ b/src/core/ptr.h @@ -171,6 +171,19 @@ bool operator != (Ptr const &lhs, Ptr const &rhs); template Ptr const_pointer_cast (Ptr const&p); +template +struct CallbackTraits; + +template +struct CallbackTraits > +{ + static T & GetReference (Ptr const p) + { + return *GetPointer (p); + } +}; + + } // namespace ns3 From 1bab5a3625f7df3f5bb2497ed4651c719517d168 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 14:58:24 +0200 Subject: [PATCH 40/48] add Callback::Nullify method --- src/core/callback-test.cc | 9 +++++++++ src/core/callback.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/core/callback-test.cc b/src/core/callback-test.cc index 4cc1b77fb..9e8cf259f 100644 --- a/src/core/callback-test.cc +++ b/src/core/callback-test.cc @@ -192,8 +192,17 @@ CallbackTest::RunTests (void) f1 (1); g1 (2); + a1.Nullify (); + b1.Nullify (); + c1.Nullify (); + d1.Nullify (); + e1.Nullify (); + g1.Nullify (); + Test8 (f1); + f1.Nullify (); + Callback a2; if (IsWrong ()) diff --git a/src/core/callback.h b/src/core/callback.h index eb5d9b44b..8f8fd1104 100644 --- a/src/core/callback.h +++ b/src/core/callback.h @@ -269,6 +269,9 @@ public: bool IsNull (void) { return (m_impl.Get () == 0)?true:false; } + void Nullify (void) { + m_impl = 0; + } Callback () : m_impl () {} R operator() (void) const { From df1cd3d5da4fb3aeda186e8528e5d4ed9963706e Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 15:23:11 +0200 Subject: [PATCH 41/48] remove ReferenceList: fix bug 27 --- SConstruct | 2 - src/core/callback.h | 75 ++++++++++---------- src/core/reference-list-test.cc | 120 -------------------------------- src/core/reference-list.h | 118 ------------------------------- 4 files changed, 39 insertions(+), 276 deletions(-) delete mode 100644 src/core/reference-list-test.cc delete mode 100644 src/core/reference-list.h diff --git a/SConstruct b/SConstruct index 6c35b2b8d..8e2e4b92f 100644 --- a/SConstruct +++ b/SConstruct @@ -31,7 +31,6 @@ ns3.add_extra_dist ('VERSION') core = build.Ns3Module('core', 'src/core') ns3.add(core) core.add_sources([ - 'reference-list-test.cc', 'callback-test.cc', 'debug.cc', 'assert.cc', @@ -63,7 +62,6 @@ core.add_headers ([ ]) core.add_inst_headers([ 'system-wall-clock-ms.h', - 'reference-list.h', 'callback.h', 'ptr.h', 'object.h', diff --git a/src/core/callback.h b/src/core/callback.h index 8f8fd1104..efeb44be2 100644 --- a/src/core/callback.h +++ b/src/core/callback.h @@ -22,7 +22,7 @@ #ifndef CALLBACK_H #define CALLBACK_H -#include "reference-list.h" +#include "ptr.h" #include "fatal-error.h" namespace ns3 { @@ -72,8 +72,21 @@ struct CallbackTraits 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 @@ -128,7 +141,7 @@ template { public: FunctorCallbackImpl (T const &functor) - : m_functor (functor) {} + : m_functor (functor) {} virtual ~FunctorCallbackImpl () {} R operator() (void) { return m_functor (); @@ -170,7 +183,7 @@ template { 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 ((CallbackTraits::GetReference (m_objPtr)).*m_memPtr) (); @@ -254,20 +267,20 @@ public: // always properly disambiguited by the c++ compiler template Callback (FUNCTOR const &functor, bool, bool) - : m_impl (new FunctorCallbackImpl (functor)) + : m_impl (MakeNewObject > (functor)) {} template Callback (OBJ_PTR const &objPtr, MEM_PTR mem_ptr) - : m_impl (new MemPtrCallbackImpl (objPtr, mem_ptr)) + : m_impl (MakeNewObject > (objPtr, mem_ptr)) {} - Callback (ReferenceList *> const &impl) + Callback (Ptr > 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; @@ -275,22 +288,22 @@ public: 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) { @@ -319,10 +332,10 @@ public: *this = *goodType; } private: - virtual CallbackImplBase *PeekImpl (void) const { - return m_impl.Get (); + virtual CallbackImpl *PeekImpl (void) const { + return PeekPointer (m_impl); } - ReferenceList*> m_impl; + Ptr > m_impl; }; /** @@ -614,44 +627,34 @@ private: template Callback MakeBoundCallback (R (*fnPtr) (TX), TX a) { - ReferenceList*> impl = - ReferenceList*> ( - new BoundFunctorCallbackImpl (fnPtr, a) - ); + Ptr > impl = + MakeNewObject >(fnPtr, a); return Callback (impl); } template Callback MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) { - ReferenceList*> impl = - ReferenceList*> ( - new BoundFunctorCallbackImpl (fnPtr, a) - ); + Ptr > impl = + MakeNewObject > (fnPtr, a); return Callback (impl); } template Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2), TX a) { - ReferenceList*> impl = - ReferenceList*> ( - new BoundFunctorCallbackImpl (fnPtr, a) - ); + Ptr > impl = + MakeNewObject > (fnPtr, a); return Callback (impl); } template Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4), TX a) { - ReferenceList*> impl = - ReferenceList*> ( - new BoundFunctorCallbackImpl (fnPtr, a) - ); + Ptr > impl = + MakeNewObject > (fnPtr, a); return Callback (impl); } template Callback MakeBoundCallback (R (*fnPtr) (TX,T1,T2,T3,T4,T5), TX a) { - ReferenceList*> impl = - ReferenceList*> ( - new BoundFunctorCallbackImpl (fnPtr, a) - ); + Ptr > impl = + MakeNewObject > (fnPtr, a); return Callback (impl); } diff --git a/src/core/reference-list-test.cc b/src/core/reference-list-test.cc deleted file mode 100644 index fdbad33ac..000000000 --- a/src/core/reference-list-test.cc +++ /dev/null @@ -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 - */ -#include "reference-list.h" -#include "test.h" - -#ifdef RUN_SELF_TESTS - -#define noREFTEST_DEBUG 1 - -#ifdef REFTEST_DEBUG -#include -#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); -}; - -RefTest::RefTest () - : ns3::Test ("ReferenceList") -{} - -void -RefTest::OneTest (ns3::ReferenceList a) -{ - a->Trace (); -} - -bool -RefTest::RunTests (void) -{ - bool ok = true; - - { - ns3::ReferenceList tmp; - { - ns3::ReferenceList 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 tmp; - } - - { - ns3::ReferenceList tmp (new A ()); - } - - { - ns3::ReferenceList tmp; - tmp.Set (new A ()); - } - - { - TRACE ("test assignement"); - ns3::ReferenceList a0 (new A ()); - ns3::ReferenceList a1 (new A ()); - a0 = a1; - } - - - - return ok; -} - - -static RefTest gRefTest = RefTest (); - -}; // namespace - -#endif /* RUN_SELF_TESTS */ diff --git a/src/core/reference-list.h b/src/core/reference-list.h deleted file mode 100644 index 08a4452bb..000000000 --- a/src/core/reference-list.h +++ /dev/null @@ -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 - */ -#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 -class ReferenceList; - -template -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 */ From 01d21b3ea20571979fdcb634393eedab450db5df Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 15:37:00 +0200 Subject: [PATCH 42/48] add tests and fix leak --- src/core/ptr.cc | 2 ++ src/core/ptr.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/ptr.cc b/src/core/ptr.cc index 81a608b80..275a11324 100644 --- a/src/core/ptr.cc +++ b/src/core/ptr.cc @@ -284,10 +284,12 @@ PtrTest::RunTests (void) { Ptr p = MakeNewObject (cb); Callback callback = MakeCallback (&NoCount::Nothing, p); + callback (); } { Ptr p = MakeNewObject (cb); Callback callback = MakeCallback (&NoCount::Nothing, p); + callback (); } #if 0 diff --git a/src/core/ptr.h b/src/core/ptr.h index 18ba47228..ca3957be8 100644 --- a/src/core/ptr.h +++ b/src/core/ptr.h @@ -179,11 +179,12 @@ struct CallbackTraits > { static T & GetReference (Ptr const p) { - return *GetPointer (p); + return *PeekPointer (p); } }; + } // namespace ns3 From c0af811d131c9868d6b8310a81e406c344a27355 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 24 May 2007 14:53:43 +0100 Subject: [PATCH 43/48] WAF: reference-list* were removed --- src/core/wscript | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/wscript b/src/core/wscript index 3131d55c8..703951031 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -24,7 +24,6 @@ def build(bld): 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 @@ def build(bld): headers = bld.create_obj('ns3header') headers.source = [ 'system-wall-clock-ms.h', - 'reference-list.h', 'callback.h', 'ptr.h', 'object.h', From 25c6350a88b638171a0d0f986725691ea35bf17a Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 16:08:03 +0200 Subject: [PATCH 44/48] fix bug 24 --- src/core/ptr.h | 11 + src/simulator/simulator.cc | 28 +++ src/simulator/simulator.h | 407 +++++++++++++++++++------------------ 3 files changed, 248 insertions(+), 198 deletions(-) diff --git a/src/core/ptr.h b/src/core/ptr.h index ca3957be8..5b4ae1538 100644 --- a/src/core/ptr.h +++ b/src/core/ptr.h @@ -183,6 +183,17 @@ struct CallbackTraits > } }; +template +struct EventMemberImplTraits; + +template +struct EventMemberImplTraits > +{ + static T &GetReference (Ptr p) { + return *PeekPointer (p); + } +}; + } // namespace ns3 diff --git a/src/simulator/simulator.cc b/src/simulator/simulator.cc index da03415a2..a499326c6 100644 --- a/src/simulator/simulator.cc +++ b/src/simulator/simulator.cc @@ -454,6 +454,7 @@ Time Now (void) #ifdef RUN_SELF_TESTS #include "ns3/test.h" +#include "ns3/ptr.h" namespace ns3 { @@ -474,6 +475,9 @@ static void foo5 (int, int, int, int, int) 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: @@ -502,6 +506,12 @@ SimulatorTests::SimulatorTests () {} SimulatorTests::~SimulatorTests () {} +void +SimulatorTests::Ref (void) +{} +void +SimulatorTests::Unref (void) +{} uint64_t SimulatorTests::NowUs (void) { @@ -634,6 +644,12 @@ SimulatorTests::RunTests (void) 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 (this)); + Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar1, Ptr (this), 0); + Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar2, Ptr (this), 0, 0); + Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar3, Ptr (this), 0, 0, 0); + Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar4, Ptr (this), 0, 0, 0, 0); + Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar5, Ptr (this), 0, 0, 0, 0, 0); Simulator::ScheduleNow (&foo0); Simulator::ScheduleNow (&foo1, 0); Simulator::ScheduleNow (&foo2, 0, 0); @@ -646,6 +662,12 @@ SimulatorTests::RunTests (void) 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 (this)); + Simulator::ScheduleNow (&SimulatorTests::bar1, Ptr (this), 0); + Simulator::ScheduleNow (&SimulatorTests::bar2, Ptr (this), 0, 0); + Simulator::ScheduleNow (&SimulatorTests::bar3, Ptr (this), 0, 0, 0); + Simulator::ScheduleNow (&SimulatorTests::bar4, Ptr (this), 0, 0, 0, 0); + Simulator::ScheduleNow (&SimulatorTests::bar5, Ptr (this), 0, 0, 0, 0, 0); Simulator::ScheduleDestroy (&foo0); Simulator::ScheduleDestroy (&foo1, 0); Simulator::ScheduleDestroy (&foo2, 0, 0); @@ -658,6 +680,12 @@ SimulatorTests::RunTests (void) 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 (this)); + Simulator::ScheduleDestroy (&SimulatorTests::bar1, Ptr (this), 0); + Simulator::ScheduleDestroy (&SimulatorTests::bar2, Ptr (this), 0, 0); + Simulator::ScheduleDestroy (&SimulatorTests::bar3, Ptr (this), 0, 0, 0); + Simulator::ScheduleDestroy (&SimulatorTests::bar4, Ptr (this), 0, 0, 0, 0); + Simulator::ScheduleDestroy (&SimulatorTests::bar5, Ptr (this), 0, 0, 0, 0, 0); Simulator::Run (); Simulator::Destroy (); diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index c30b43661..02cf6741c 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -162,8 +162,8 @@ public: * @param obj the object on which to invoke the member method * @returns an id for the scheduled event. */ - template - static EventId Schedule (Time const &time, void (T::*mem_ptr) (void), T *obj); + template + 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 @@ -171,8 +171,8 @@ public: * @param a1 the first argument to pass to the invoked method * @returns an id for the scheduled event. */ - template - static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), T* obj, T1 a1); + template + 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 @@ -181,8 +181,8 @@ public: * @param a2 the second argument to pass to the invoked method * @returns an id for the scheduled event. */ - template - static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2); + template + 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 @@ -192,8 +192,8 @@ public: * @param a3 the third argument to pass to the invoked method * @returns an id for the scheduled event. */ - template - static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3); + template + 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 @@ -204,8 +204,8 @@ public: * @param a4 the fourth argument to pass to the invoked method * @returns an id for the scheduled event. */ - template - 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 + 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 @@ -217,9 +217,9 @@ public: * @param a5 the fifth argument to pass to the invoked method * @returns an id for the scheduled event. */ - template - 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 + 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 @@ -286,23 +286,23 @@ public: * @param mem_ptr member method pointer to invoke * @param obj the object on which to invoke the member method */ - template - static void ScheduleNow (void (T::*mem_ptr) (void), T *obj); + template + 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 - static void ScheduleNow (void (T::*mem_ptr) (T1), T* obj, T1 a1); + template + 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 - static void ScheduleNow (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2); + template + 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 @@ -310,8 +310,8 @@ public: * @param a2 the second argument to pass to the invoked method * @param a3 the third argument to pass to the invoked method */ - template - static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3); + template + 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 @@ -320,8 +320,8 @@ public: * @param a3 the third argument to pass to the invoked method * @param a4 the fourth argument to pass to the invoked method */ - template - static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, + template + 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 @@ -332,8 +332,8 @@ public: * @param a4 the fourth argument to pass to the invoked method * @param a5 the fifth argument to pass to the invoked method */ - template - static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj, + template + 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 @@ -390,23 +390,23 @@ public: * @param mem_ptr member method pointer to invoke * @param obj the object on which to invoke the member method */ - template - static void ScheduleDestroy (void (T::*mem_ptr) (void), T *obj); + template + 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 - static void ScheduleDestroy (void (T::*mem_ptr) (T1), T* obj, T1 a1); + template + 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 - static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2); + template + 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 @@ -414,8 +414,8 @@ public: * @param a2 the second argument to pass to the invoked method * @param a3 the third argument to pass to the invoked method */ - template - static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3); + template + 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 @@ -424,9 +424,9 @@ public: * @param a3 the third argument to pass to the invoked method * @param a4 the fourth argument to pass to the invoked method */ - template - static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, - T1 a1, T2 a2, T3 a3, T4 a4); + template + 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 @@ -436,9 +436,9 @@ public: * @param a4 the fourth argument to pass to the invoked method * @param a5 the fifth argument to pass to the invoked method */ - template - 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 + 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 */ @@ -529,19 +529,19 @@ public: private: Simulator (); ~Simulator (); - template - static EventImpl *MakeEvent (void (T::*mem_ptr) (void), T *obj); - template - static EventImpl *MakeEvent (void (T::*mem_ptr) (T1), T* obj, T1 a1); - template - static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2); - template - static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3); - template - static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4); - template - 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 + static EventImpl *MakeEvent (void (T::*mem_ptr) (void), OBJ obj); + template + static EventImpl *MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1); + template + static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2); + template + static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3); + template + static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); + template + 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 static EventImpl *MakeEvent (void (*f) (T1), T1 a1); @@ -584,174 +584,185 @@ Time Now (void); namespace ns3 { template -EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (void), T *obj) +struct EventMemberImplTraits; + +template +struct EventMemberImplTraits +{ + static T &GetReference (T *p) { + return *p; + } +}; + +template +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::GetReference (m_obj).*m_function) (); + } + OBJ m_obj; + F m_function; } *ev = new EventMemberImpl0 (obj, mem_ptr); return ev; } -template -EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1), T* obj, T1 a1) +template +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::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 -EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2) +template +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::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 -EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3) +template +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::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 -EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4) +template +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::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 -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 +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::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; } @@ -896,39 +907,39 @@ EventImpl *Simulator::MakeEvent (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3 return ev; } -template -EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (void), T *obj) +template +EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (void), OBJ obj) { return Schedule (time, MakeEvent (mem_ptr, obj)); } -template -EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1), T* obj, T1 a1) +template +EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj, T1 a1) { return Schedule (time, MakeEvent (mem_ptr, obj, a1)); } -template -EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2) +template +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 -EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3) +template +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 -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 +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 -EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj, +template +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)); @@ -967,46 +978,46 @@ EventId Simulator::Schedule (Time const &time, void (*f) (T1,T2,T3,T4,T5), T1 a1 -template +template 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 +template 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 +template 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 +template 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 +template 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 +template 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)); } @@ -1048,46 +1059,46 @@ Simulator::ScheduleNow (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, -template +template 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 +template 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 +template 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 +template 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 +template 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 +template 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)); } From 80247a993d423cde0ee90d33812fea8315d5a148 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 24 May 2007 16:15:41 +0200 Subject: [PATCH 45/48] uniformize the DefaultValues used by the Event Schedulers --- src/simulator/scheduler-factory.cc | 2 +- src/simulator/scheduler-list.cc | 2 +- src/simulator/scheduler-map.cc | 2 +- src/simulator/simulator.cc | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/simulator/scheduler-factory.cc b/src/simulator/scheduler-factory.cc index fff4914bb..760b2ea8b 100644 --- a/src/simulator/scheduler-factory.cc +++ b/src/simulator/scheduler-factory.cc @@ -88,7 +88,7 @@ SchedulerFactory::Add (const SchedulerFactory *factory, StringEnumDefaultValue * SchedulerFactory::GetDefault (void) { - static StringEnumDefaultValue value ("scheduler", "Event Scheduler algorithm"); + static StringEnumDefaultValue value ("Scheduler", "Event Scheduler algorithm"); return &value; } diff --git a/src/simulator/scheduler-list.cc b/src/simulator/scheduler-list.cc index 8a9781a9c..fe5b3317b 100644 --- a/src/simulator/scheduler-list.cc +++ b/src/simulator/scheduler-list.cc @@ -33,7 +33,7 @@ static class SchedulerListFactory : public SchedulerFactory public: SchedulerListFactory () { - SchedulerFactory::AddDefault (this, "list"); + SchedulerFactory::AddDefault (this, "List"); } private: virtual Scheduler *DoCreate (void) const diff --git a/src/simulator/scheduler-map.cc b/src/simulator/scheduler-map.cc index b2a04fc1c..46ad3bae5 100644 --- a/src/simulator/scheduler-map.cc +++ b/src/simulator/scheduler-map.cc @@ -44,7 +44,7 @@ static class SchedulerMapFactory : public SchedulerFactory public: SchedulerMapFactory () { - SchedulerFactory::Add (this, "map"); + SchedulerFactory::Add (this, "Map"); } private: virtual Scheduler *DoCreate (void) const diff --git a/src/simulator/simulator.cc b/src/simulator/simulator.cc index a499326c6..226f7357a 100644 --- a/src/simulator/simulator.cc +++ b/src/simulator/simulator.cc @@ -298,20 +298,20 @@ SimulatorPrivate *Simulator::m_priv = 0; 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) { From 381103678d9b36c0370520186d1e0166966f64fc Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 24 May 2007 17:54:51 +0100 Subject: [PATCH 46/48] WAF: cleanup the main wscript file by moving the definition of the ns3header object type into src/wscript --- src/wscript | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++- wscript | 53 ------------------------------------------------ 2 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/wscript b/src/wscript index fb357cc22..551a26e1b 100644 --- a/src/wscript +++ b/src/wscript @@ -1,9 +1,14 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- import os -import sys +import shutil + +import Action +import Common +import Object import Params + all_modules = [ 'core', 'common', @@ -24,6 +29,9 @@ def configure(conf): def build(bld): + Object.register('ns3header', Ns3Header) + Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE') + env = bld.env_of_name('default') for module in all_modules: node = bld.m_curdirnode.find_dir(module) @@ -31,3 +39,51 @@ def build(bld): 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 diff --git a/wscript b/wscript index dbb448c58..3c60292fd 100644 --- a/wscript +++ b/wscript @@ -5,9 +5,6 @@ import shlex import Params import Object -import Action -import Common -import shutil import pproc as subprocess Params.g_autoconfig = 1 @@ -20,56 +17,6 @@ APPNAME = 'ns-3-waf' 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 set_options(opt): # options provided by the modules From 923f4aeb8f1a4987db2d709006aeac09202d2a46 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 24 May 2007 17:59:30 +0100 Subject: [PATCH 47/48] WAF: correct values of VERSION and APPNAME, for waf dist --- wscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wscript b/wscript index 3c60292fd..046a40bf5 100644 --- a/wscript +++ b/wscript @@ -10,8 +10,8 @@ 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 = '.' From acbfbc29b3364719c8d7b6e8f287a007924aa98f Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Thu, 24 May 2007 19:21:50 +0100 Subject: [PATCH 48/48] WAF: add a dist_hook function to exclude the generated documentation from waf dist --- wscript | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wscript b/wscript index 046a40bf5..7e12cd170 100644 --- a/wscript +++ b/wscript @@ -2,6 +2,7 @@ import os import sys import shlex +import shutil import Params import Object @@ -17,6 +18,9 @@ APPNAME = 'ns' srcdir = '.' blddir = 'build' +def dist_hook(srcdir, blddir): + shutil.rmtree("doc/html") + shutil.rmtree("doc/latex") def set_options(opt): # options provided by the modules