--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-random-walk.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,61 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include <vector>
+
+#include "ns3/ptr.h"
+#include "ns3/mobility-model.h"
+#include "ns3/mobility-model-notifier.h"
+#include "ns3/random-topology.h"
+#include "ns3/default-value.h"
+#include "ns3/command-line.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/node.h"
+#include "ns3/node-list.h"
+
+using namespace ns3;
+
+static void
+CourseChange (ns3::TraceContext const&, Ptr<const MobilityModel> mobility)
+{
+ Position pos = mobility->Get ();
+ Speed vel = mobility->GetSpeed ();
+ std::cout << Simulator::Now () << ", model=" << mobility << ", POS: x=" << pos.x << ", y=" << pos.y
+ << ", z=" << pos.z << "; VEL:" << vel.dx << ", y=" << vel.dy
+ << ", z=" << vel.dz << std::endl;
+}
+
+int main (int argc, char *argv[])
+{
+ DefaultValue::Bind ("RandomWalk2dMode", "Time");
+ DefaultValue::Bind ("RandomWalk2dTime", "2s");
+ DefaultValue::Bind ("RandomWalk2dSpeed", "Constant:1.0");
+ DefaultValue::Bind ("RandomWalk2dBounds", "0:200:0:100");
+
+ DefaultValue::Bind ("RandomDiscPositionX", "100");
+ DefaultValue::Bind ("RandomDiscPositionY", "50");
+ DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
+
+ DefaultValue::Bind ("RandomTopologyPositionType", "RandomDiscPosition");
+ DefaultValue::Bind ("RandomTopologyMobilityType", "RandomWalk2dMobilityModel");
+
+ CommandLine::Parse (argc, argv);
+
+ RandomTopology topology;
+
+ for (uint32_t i = 0; i < 100; i++)
+ {
+ Ptr<Node> node = Create<Node> ();
+ node->AddInterface (Create<MobilityModelNotifier> ());
+ }
+
+ topology.Layout (NodeList::Begin (), NodeList::End ());
+ NodeList::Connect ("/nodes/*/$MobilityModelNotifier/course-change",
+ MakeCallback (&CourseChange));
+
+ Simulator::StopAt (Seconds (100.0));
+
+ Simulator::Run ();
+
+ return 0;
+}
--- a/samples/wscript Mon Oct 08 11:23:53 2007 +0100
+++ b/samples/wscript Mon Oct 08 11:24:16 2007 +0100
@@ -41,3 +41,6 @@
['core', 'simulator', 'mobility'])
obj.source = 'main-random-topology.cc'
+ obj = bld.create_ns3_program('main-random-walk',
+ ['core', 'simulator', 'mobility'])
+ obj.source = 'main-random-walk.cc'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/int-to-type.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,19 @@
+#ifndef INT_TO_TYPE_H
+#define INT_TO_TYPE_H
+
+namespace ns3 {
+
+/**
+ * This trivial template is extremely useful, as explained in
+ * "Modern C++ Design", p29, section 2.4,
+ * "Mapping Integral Constants to Types"
+ */
+template <int v>
+struct IntToType
+{
+ enum {value = v};
+};
+
+} // namespace ns3
+
+#endif /* INT_TO_TYPE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/type-traits-test.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,40 @@
+#include "type-traits.h"
+#include "test.h"
+
+#ifdef RUN_SELF_TESTS
+
+namespace ns3 {
+
+class TypeTraitsTest : public Test
+{
+public:
+ TypeTraitsTest ();
+ virtual bool RunTests (void);
+};
+
+TypeTraitsTest::TypeTraitsTest ()
+ : Test ("TypeTraits")
+{}
+bool
+TypeTraitsTest::RunTests (void)
+{
+ bool result = true;
+
+ //TypeTraits<int &>::ReferencedType ir;
+ //TypeTraits<const int>::NonConstType uci;
+ NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (void)>::IsPointerToMember, 1);
+ NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (void) const>::IsPointerToMember, 1);
+ NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (int)>::IsPointerToMember, 1);
+ NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (int) const>::IsPointerToMember, 1);
+ NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (void) const>::PointerToMemberTraits::nArgs, 0);
+ NS_TEST_ASSERT_EQUAL (TypeTraits<void (TypeTraitsTest::*) (int) const>::PointerToMemberTraits::nArgs, 1);
+
+ return result;
+}
+
+static TypeTraitsTest g_typeTraitsTest;
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
+
--- a/src/core/type-traits.h Mon Oct 08 11:23:53 2007 +0100
+++ b/src/core/type-traits.h Mon Oct 08 11:24:16 2007 +0100
@@ -2,24 +2,293 @@
#define TYPE_TRAITS_H
template <typename T>
-struct TypeTraits;
-
-template <typename T>
struct TypeTraits
{
- typedef T ReferencedType;
-};
+private:
+ struct NullType {};
+ template <typename U> struct UnConst
+ {
+ typedef U Result;
+ };
+ template <typename U> struct UnConst<const U>
+ {
+ typedef U Result;
+ };
+ template <typename U> struct ReferenceTraits
+ {
+ enum {IsReference = 0};
+ typedef U ReferencedType;
+ };
+ template <typename U> struct ReferenceTraits<U&>
+ {
+ enum {IsReference = 1};
+ typedef U ReferencedType;
+ };
+ template <typename U> struct PointerTraits
+ {
+ enum {IsPointer = 0};
+ typedef U PointeeType;
+ };
+ template <typename U> struct PointerTraits<U *>
+ {
+ enum {IsPointer = 1};
+ typedef U PointeeType;
+ };
+ template <typename U> struct FunctionPtrTraits
+ {
+ enum {IsFunctionPointer = 0};
+ };
+ template <typename U>
+ struct FunctionPtrTraits <U (*) (void)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 0};
+ typedef U ReturnType;
+ };
+ template <typename U, typename V1>
+ struct FunctionPtrTraits <U (*) (V1)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 1};
+ typedef U ReturnType;
+ typedef V1 Arg1Type;
+ };
+ template <typename U, typename V1, typename V2>
+ struct FunctionPtrTraits <U (*) (V1,V2)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 2};
+ typedef U ReturnType;
+ typedef V1 Arg1Type;
+ typedef V2 Arg2Type;
+ };
+ template <typename U, typename V1, typename V2,
+ typename V3>
+ struct FunctionPtrTraits <U (*) (V1,V2,V3)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 3};
+ typedef U ReturnType;
+ typedef V1 Arg1Type;
+ typedef V2 Arg2Type;
+ typedef V3 Arg3Type;
+ };
+ template <typename U, typename V1, typename V2,
+ typename V3, typename V4>
+ struct FunctionPtrTraits <U (*) (V1,V2,V3,V4)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 4};
+ typedef U ReturnType;
+ typedef V1 Arg1Type;
+ typedef V2 Arg2Type;
+ typedef V3 Arg3Type;
+ typedef V4 Arg4Type;
+ };
+ template <typename U, typename V1, typename V2,
+ typename V3, typename V4,
+ typename V5>
+ struct FunctionPtrTraits <U (*) (V1,V2,V3,V4,V5)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 5};
+ typedef U ReturnType;
+ typedef V1 Arg1Type;
+ typedef V2 Arg2Type;
+ typedef V3 Arg3Type;
+ typedef V4 Arg4Type;
+ typedef V5 Arg5Type;
+ };
+ template <typename U, typename V1, typename V2,
+ typename V3, typename V4,
+ typename V5, typename V6>
+ struct FunctionPtrTraits <U (*) (V1,V2,V3,V4,V5,V6)>
+ {
+ enum {IsFunctionPointer = 1};
+ enum {nArgs = 6};
+ typedef U ReturnType;
+ typedef V1 Arg1Type;
+ typedef V2 Arg2Type;
+ typedef V3 Arg3Type;
+ typedef V4 Arg4Type;
+ typedef V5 Arg5Type;
+ typedef V6 Arg6Type;
+ };
+ template <typename U> struct PtrToMemberTraits
+ {
+ enum {IsPointerToMember = 0};
+ };
+ template <typename U, typename V>
+ struct PtrToMemberTraits <U (V::*) (void)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 0};
+ typedef U ReturnType;
+ };
+ template <typename U, typename V>
+ struct PtrToMemberTraits <U (V::*) (void) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 0};
+ typedef U ReturnType;
+ };
+ template <typename U, typename V,typename W1>
+ struct PtrToMemberTraits <U (V::*) (W1)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 1};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ };
+ template <typename U, typename V,typename W1>
+ struct PtrToMemberTraits <U (V::*) (W1) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 1};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ };
+ template <typename U, typename V,typename W1, typename W2>
+ struct PtrToMemberTraits <U (V::*) (W1,W2)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 2};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ };
+ template <typename U, typename V,typename W1, typename W2>
+ struct PtrToMemberTraits <U (V::*) (W1,W2) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 2};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 3};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 3};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3, typename W4>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 4};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ typedef W4 Arg4Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3, typename W4>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 4};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ typedef W4 Arg4Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3, typename W4,
+ typename W5>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 5};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ typedef W4 Arg4Type;
+ typedef W5 Arg5Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3, typename W4,
+ typename W5>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 5};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ typedef W4 Arg4Type;
+ typedef W5 Arg5Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3, typename W4,
+ typename W5, typename W6>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5,W6)>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 6};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ typedef W4 Arg4Type;
+ typedef W5 Arg5Type;
+ typedef W6 Arg6Type;
+ };
+ template <typename U, typename V,
+ typename W1, typename W2,
+ typename W3, typename W4,
+ typename W5, typename W6>
+ struct PtrToMemberTraits <U (V::*) (W1,W2,W3,W4,W5,W6) const>
+ {
+ enum {IsPointerToMember = 1};
+ enum {nArgs = 6};
+ typedef U ReturnType;
+ typedef W1 Arg1Type;
+ typedef W2 Arg2Type;
+ typedef W3 Arg3Type;
+ typedef W4 Arg4Type;
+ typedef W5 Arg5Type;
+ typedef W6 Arg6Type;
+ };
-template <typename T>
-struct TypeTraits<const T &>
-{
- typedef T ReferencedType;
-};
-
-template <typename T>
-struct TypeTraits<T &>
-{
- typedef T ReferencedType;
+public:
+ typedef typename UnConst<T>::Result NonConstType;
+ typedef typename ReferenceTraits<T>::ReferencedType ReferencedType;
+ typedef typename PointerTraits<T>::PointeeType PointeeType;
+ enum {IsPointerToMember = PtrToMemberTraits<T>::IsPointerToMember};
+ enum {IsPointer = PointerTraits<T>::IsPointer};
+ enum {IsReference = ReferenceTraits<T>::IsReference};
+ enum {IsFunctionPointer = FunctionPtrTraits<T>::IsFunctionPointer};
+ typedef PtrToMemberTraits<T> PointerToMemberTraits;
+ typedef FunctionPtrTraits<T> FunctionPointerTraits;
};
--- a/src/core/wscript Mon Oct 08 11:23:53 2007 +0100
+++ b/src/core/wscript Mon Oct 08 11:24:16 2007 +0100
@@ -51,6 +51,7 @@
'composite-trace-resolver.cc',
'trace-doc.cc',
'trace-source.cc',
+ 'type-traits-test.cc',
]
if sys.platform == 'win32':
@@ -94,5 +95,6 @@
'composite-trace-resolver.h',
'array-trace-resolver.h',
'trace-doc.h',
+ 'int-to-type.h',
]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/ns2-mobility-file-topology.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include <fstream>
+#include <sstream>
+#include "ns3/debug.h"
+#include "ns3/simulator.h"
+#include "ns3/node-list.h"
+#include "ns3/node.h"
+#include "ns2-mobility-file-topology.h"
+#include "static-speed-mobility-model.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("Ns2MobilityFileTopology");
+
+namespace ns3 {
+
+
+Ns2MobilityFileTopology::Ns2MobilityFileTopology (std::string filename)
+ : m_filename (filename)
+{}
+
+
+Ptr<StaticSpeedMobilityModel>
+Ns2MobilityFileTopology::GetMobilityModel (std::string idString, const ObjectStore &store) const
+{
+ std::istringstream iss;
+ iss.str (idString);
+ uint32_t id;
+ iss >> id;
+ Ptr<Object> object = store.Get (id);
+ if (object == 0)
+ {
+ return 0;
+ }
+ Ptr<StaticSpeedMobilityModel> model =
+ object->QueryInterface<StaticSpeedMobilityModel> (StaticSpeedMobilityModel::iid);
+ if (model == 0)
+ {
+ model = Create<StaticSpeedMobilityModel> ();
+ object->AddInterface (model);
+ }
+ return model;
+}
+
+double
+Ns2MobilityFileTopology::ReadDouble (std::string valueString) const
+{
+ std::istringstream iss;
+ iss.str (valueString);
+ double value;
+ iss >> value;
+ return value;
+}
+
+void
+Ns2MobilityFileTopology::LayoutObjectStore (const ObjectStore &store) const
+{
+ std::ifstream file (m_filename.c_str (), std::ios::in);
+ if (file.is_open())
+ {
+ while (!file.eof() )
+ {
+ std::string line;
+ getline (file, line);
+ std::string::size_type startNodeId = line.find_first_of ("(");
+ std::string::size_type endNodeId = line.find_first_of (")");
+ if (startNodeId == std::string::npos ||
+ endNodeId == std::string::npos)
+ {
+ continue;
+ }
+ Ptr<StaticSpeedMobilityModel> model = GetMobilityModel (line.substr (startNodeId + 1,
+ endNodeId - startNodeId),
+ store);
+ if (model == 0)
+ {
+ continue;
+ }
+ if (startNodeId == 6)
+ {
+ double value = ReadDouble (line.substr (endNodeId + 9, std::string::npos));
+ std::string coordinate = line.substr (endNodeId + 6, 1);
+ Position position = model->Get ();
+ if (coordinate == "X")
+ {
+ position.x = value;
+ NS_DEBUG ("X=" << value);
+ }
+ else if (coordinate == "Y")
+ {
+ position.y = value;
+ NS_DEBUG ("Y=" << value);
+ }
+ else if (coordinate == "Z")
+ {
+ position.z = value;
+ NS_DEBUG ("Z=" << value);
+ }
+ else
+ {
+ continue;
+ }
+ model->Set (position);
+ }
+ else
+ {
+ double at = ReadDouble (line.substr (8, startNodeId - 17));
+ std::string::size_type xSpeedEnd = line.find_first_of (" ", endNodeId + 10);
+ std::string::size_type ySpeedEnd = line.find_first_of (" ", xSpeedEnd + 1);
+ double xSpeed = ReadDouble (line.substr (endNodeId + 10, xSpeedEnd - endNodeId - 10));
+ double ySpeed = ReadDouble (line.substr (xSpeedEnd + 1, ySpeedEnd - xSpeedEnd - 1));
+ double zSpeed = ReadDouble (line.substr (ySpeedEnd + 1, std::string::npos));
+ NS_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
+ Simulator::Schedule (Seconds (at), &StaticSpeedMobilityModel::SetSpeed, model,
+ Speed (xSpeed, ySpeed, zSpeed));
+ }
+ }
+ file.close();
+ }
+}
+
+void
+Ns2MobilityFileTopology::Layout (void) const
+{
+ Layout (NodeList::Begin (), NodeList::End ());
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/ns2-mobility-file-topology.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef NS2_MOBILITY_FILE_TOPOLOGY_H
+#define NS2_MOBILITY_FILE_TOPOLOGY_H
+
+#include <string>
+#include <stdint.h>
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "static-speed-mobility-model.h"
+
+namespace ns3 {
+
+/**
+ * \brief a topology object which can read ns2's movement files
+ * generated by the CMU setdest tool.
+ */
+class Ns2MobilityFileTopology
+{
+public:
+ /**
+ * \param filename filename of file which contains the
+ * ns2 movement trace.
+ */
+ Ns2MobilityFileTopology (std::string filename);
+
+ /**
+ * Read the ns2 trace file and configure the movement
+ * patterns of all nodes contained in the global ns3::NodeList
+ * whose nodeId is matches the nodeId of the nodes in the trace
+ * file.
+ */
+ void Layout (void) const;
+
+ /**
+ * \param begin an iterator which points to the start of the input
+ * object array.
+ * \param end an iterator which points to the end of the input
+ * object array.
+ *
+ * Read the ns2 trace file and configure the movement
+ * patterns of all input objects. Each input object
+ * is identified by a unique node id which reflects
+ * the index of the object in the input array.
+ */
+ template <typename T>
+ void Layout (T begin, T end) const;
+private:
+ class ObjectStore
+ {
+ public:
+ virtual ~ObjectStore () {}
+ virtual Ptr<Object> Get (uint32_t i) const = 0;
+ };
+ void LayoutObjectStore (const ObjectStore &store) const;
+ Ptr<StaticSpeedMobilityModel> GetMobilityModel (std::string idString, const ObjectStore &store) const;
+ double ReadDouble (std::string valueString) const;
+ std::string m_filename;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void
+Ns2MobilityFileTopology::Layout (T begin, T end) const
+{
+ class MyObjectStore : public ObjectStore
+ {
+ public:
+ MyObjectStore (T begin, T end)
+ : m_begin (begin),
+ m_end (end)
+ {}
+ virtual Ptr<Object> Get (uint32_t i) const {
+ T iterator = m_begin;
+ iterator += i;
+ if (iterator >= m_end)
+ {
+ return 0;
+ }
+ return *iterator;
+ }
+ private:
+ T m_begin;
+ T m_end;
+ };
+ LayoutObjectStore (MyObjectStore (begin, end));
+}
+
+
+} // namespace ns3
+
+#endif /* NS2_MOBILITY_FILE_TOPOLOGY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-direction-2d-mobility-model.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,210 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ns3/random-variable-default-value.h"
+#include "ns3/rectangle-default-value.h"
+#include "ns3/simulator.h"
+#include <algorithm>
+#include <cmath>
+#include "random-direction-2d-mobility-model.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("RandomDirection2dMobilityModel");
+
+namespace ns3 {
+
+const double RandomDirection2dMobilityModel::PI = 3.14159265358979323846;
+const ClassId RandomDirection2dMobilityModel::cid =
+ MakeClassId<RandomDirection2dMobilityModel> ("RandomDirection2dMobilityModel",
+ MobilityModel::iid);
+
+
+static RandomVariableDefaultValue
+ g_speedVariable ("RandomDirection2dSpeed",
+ "A random variable to control the speed of a RandomDirection2d mobility model.",
+ "Uniform:1:2");
+
+static RandomVariableDefaultValue
+ g_pauseVariable ("RandomDirection2dPause",
+ "A random variable to control the duration "
+ "of the pause of a RandomDiretion mobility model.",
+ "Constant:2");
+
+static RectangleDefaultValue
+ g_bounds ("RandomDirection2dArea",
+ "The bounding area for the RandomDirection2d model.",
+ -100, 100, -100, 100);
+
+
+RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters ()
+ : m_bounds (g_bounds.GetValue ()),
+ m_speedVariable (g_speedVariable.GetCopy ()),
+ m_pauseVariable (g_pauseVariable.GetCopy ())
+
+{}
+RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters
+(const Rectangle &bounds,
+ const RandomVariable &speedVariable,
+ const RandomVariable &pauseVariable)
+ : m_bounds (bounds),
+ m_speedVariable (speedVariable.Copy ()),
+ m_pauseVariable (pauseVariable.Copy ())
+{}
+
+RandomDirection2dMobilityModelParameters::~RandomDirection2dMobilityModelParameters ()
+{
+ delete m_speedVariable;
+ delete m_pauseVariable;
+ m_speedVariable = 0;
+ m_pauseVariable = 0;
+}
+
+void
+RandomDirection2dMobilityModelParameters::SetSpeed (const RandomVariable &speedVariable)
+{
+ delete m_speedVariable;
+ m_speedVariable = speedVariable.Copy ();
+}
+void
+RandomDirection2dMobilityModelParameters::SetPause (const RandomVariable &pauseVariable)
+{
+ delete m_pauseVariable;
+ m_pauseVariable = pauseVariable.Copy ();
+}
+void
+RandomDirection2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
+{
+ m_bounds = bounds;
+}
+
+Ptr<RandomDirection2dMobilityModelParameters>
+RandomDirection2dMobilityModelParameters::GetCurrent (void)
+{
+ static Ptr<RandomDirection2dMobilityModelParameters> parameters = 0;
+ if (parameters == 0 ||
+ g_bounds.IsDirty () ||
+ g_speedVariable.IsDirty () ||
+ g_pauseVariable.IsDirty ())
+ {
+ parameters = Create<RandomDirection2dMobilityModelParameters> ();
+ g_bounds.ClearDirtyFlag ();
+ g_speedVariable.ClearDirtyFlag ();
+ g_pauseVariable.ClearDirtyFlag ();
+ }
+ return parameters;
+}
+
+
+RandomDirection2dMobilityModel::RandomDirection2dMobilityModel ()
+ : m_parameters (RandomDirection2dMobilityModelParameters::GetCurrent ())
+{
+ SetInterfaceId (RandomDirection2dMobilityModel::iid);
+ m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
+}
+RandomDirection2dMobilityModel::RandomDirection2dMobilityModel
+(Ptr<RandomDirection2dMobilityModelParameters> parameters)
+ : m_parameters (parameters)
+{
+ SetInterfaceId (RandomDirection2dMobilityModel::iid);
+ m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
+}
+void
+RandomDirection2dMobilityModel::DoDispose (void)
+{
+ m_parameters = 0;
+ // chain up.
+ MobilityModel::DoDispose ();
+}
+void
+RandomDirection2dMobilityModel::Start (void)
+{
+ double direction = UniformVariable::GetSingleValue (0, 2 * PI);
+ SetDirectionAndSpeed (direction);
+}
+
+void
+RandomDirection2dMobilityModel::BeginPause (void)
+{
+ Time pause = Seconds (m_parameters->m_pauseVariable->GetValue ());
+ m_helper.Pause ();
+ m_event = Simulator::Schedule (pause, &RandomDirection2dMobilityModel::ResetDirectionAndSpeed, this);
+ NotifyCourseChange ();
+}
+
+void
+RandomDirection2dMobilityModel::SetDirectionAndSpeed (double direction)
+{
+ NS_LOG_FUNCTION;
+ double speed = m_parameters->m_speedVariable->GetValue ();
+ const Speed vector (std::cos (direction) * speed,
+ std::sin (direction) * speed,
+ 0.0);
+ Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+ m_helper.Reset (vector);
+ Position next = m_parameters->m_bounds.CalculateIntersection (position, vector);
+ Time delay = Seconds (CalculateDistance (position, next) / speed);
+ m_event = Simulator::Schedule (delay,
+ &RandomDirection2dMobilityModel::BeginPause, this);
+ NotifyCourseChange ();
+}
+void
+RandomDirection2dMobilityModel::ResetDirectionAndSpeed (void)
+{
+ double direction = UniformVariable::GetSingleValue (0, PI);
+
+ Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+ switch (m_parameters->m_bounds.GetClosestSide (position))
+ {
+ case Rectangle::RIGHT:
+ direction += PI / 2;
+ break;
+ case Rectangle::LEFT:
+ direction += - PI / 2;
+ break;
+ case Rectangle::TOP:
+ direction += PI;
+ break;
+ case Rectangle::BOTTOM:
+ direction += 0.0;
+ break;
+ }
+ SetDirectionAndSpeed (direction);
+}
+Position
+RandomDirection2dMobilityModel::DoGet (void) const
+{
+ return m_helper.GetCurrentPosition (m_parameters->m_bounds);
+}
+void
+RandomDirection2dMobilityModel::DoSet (const Position &position)
+{
+ m_helper.InitializePosition (position);
+ Simulator::Remove (m_event);
+ m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
+}
+Speed
+RandomDirection2dMobilityModel::DoGetSpeed (void) const
+{
+ return m_helper.GetSpeed ();
+}
+
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-direction-2d-mobility-model.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef RANDOM_DIRECTION_MOBILITY_MODEL_H
+#define RANDOM_DIRECTION_MOBILITY_MODEL_H
+
+#include "ns3/object.h"
+#include "ns3/ptr.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+#include "ns3/component-manager.h"
+#include "ns3/rectangle.h"
+#include "mobility-model.h"
+#include "static-speed-helper.h"
+
+namespace ns3 {
+
+class RandomVariable;
+
+/**
+ * \brief the parameters to control a RandomDirection mobility model.
+ */
+class RandomDirection2dMobilityModelParameters : public Object
+{
+ public:
+ /**
+ * Create a default parameter object from Bind default values.
+ */
+ RandomDirection2dMobilityModelParameters ();
+ /**
+ * \param bounds the 2d bounds of the mobility model
+ * \param speedVariable the random variable used to pick a random speed
+ * \param pauseVariable the random variable used to pick a random pause delay
+ */
+ RandomDirection2dMobilityModelParameters (const Rectangle &bounds,
+ const RandomVariable &speedVariable,
+ const RandomVariable &pauseVariable);
+ virtual ~RandomDirection2dMobilityModelParameters ();
+
+ /**
+ * \param speedVariable the random variable used to pick a random speed.
+ */
+ void SetSpeed (const RandomVariable &speedVariable);
+ /**
+ * \param pauseVariable the random variable used to pick a random pause delay.
+ */
+ void SetPause (const RandomVariable &pauseVariable);
+ /**
+ * \param bounds the 2d bounds of the mobility model.
+ */
+ void SetBounds (const Rectangle &bounds);
+ private:
+ friend class RandomDirection2dMobilityModel;
+
+ static Ptr<RandomDirection2dMobilityModelParameters> GetCurrent (void);
+
+ Rectangle m_bounds;
+ RandomVariable *m_speedVariable;
+ RandomVariable *m_pauseVariable;
+};
+
+/**
+ * \brief a RandomDirection mobility model
+ *
+ * The movement of objects is based on random directions: each object
+ * pauses for a specific delay, chooses a random direction and speed and
+ * then travels in the specific direction until it reaches one of
+ * the boundaries of the model. When it reaches the boundary, it pauses,
+ * selects a new direction and speed, aso.
+ */
+class RandomDirection2dMobilityModel : public MobilityModel
+{
+ public:
+ static const ClassId cid;
+
+ /**
+ * Create a RandomDirection model from the default Bind values.
+ */
+ RandomDirection2dMobilityModel ();
+ /**
+ * \param parameters the parameters which control the behavior of the model.
+ * Create a RandomDirection model using the parameters specified.
+ */
+ RandomDirection2dMobilityModel (Ptr<RandomDirection2dMobilityModelParameters> parameters);
+ private:
+ void Start (void);
+ void ResetDirectionAndSpeed (void);
+ void BeginPause (void);
+ void SetDirectionAndSpeed (double direction);
+ void InitializeDirectionAndSpeed (void);
+ virtual void DoDispose (void);
+ virtual Position DoGet (void) const;
+ virtual void DoSet (const Position &position);
+ virtual Speed DoGetSpeed (void) const;
+
+ static const double PI;
+ Ptr<RandomDirection2dMobilityModelParameters> m_parameters;
+ EventId m_event;
+ StaticSpeedHelper m_helper;
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_DIRECTION_MOBILITY_MODEL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-walk-2d-mobility-model.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "random-walk-2d-mobility-model.h"
+#include "ns3/default-value.h"
+#include "ns3/time-default-value.h"
+#include "ns3/rectangle-default-value.h"
+#include "ns3/random-variable-default-value.h"
+#include "ns3/simulator.h"
+#include "ns3/debug.h"
+#include <cmath>
+
+NS_DEBUG_COMPONENT_DEFINE ("RandomWalk2d");
+
+namespace ns3 {
+
+const ClassId RandomWalk2dMobilityModel::cid =
+ MakeClassId<RandomWalk2dMobilityModel> ("RandomWalk2dMobilityModel", RandomWalk2dMobilityModel::iid);
+
+
+static EnumDefaultValue<RandomWalk2dMobilityModelParameters::Mode>
+g_mode ("RandomWalk2dMode",
+ "The mode indicates the condition used to "
+ "change the current speed and direction",
+ RandomWalk2dMobilityModelParameters::MODE_DISTANCE, "Distance",
+ RandomWalk2dMobilityModelParameters::MODE_TIME, "Time",
+ 0, (void*)0);
+
+static NumericDefaultValue<double>
+g_modeDistance ("RandomWalk2dDistance",
+ "Change current direction and speed after moving this distance.",
+ 2.0);
+
+static TimeDefaultValue
+g_modeTime ("RandomWalk2dTime",
+ "Change current direction and speed after moving for this delay.",
+ Seconds (1.0));
+
+static RandomVariableDefaultValue
+g_speed ("RandomWalk2dSpeed",
+ "A random variable used to pick the speed.",
+ "Uniform:2:4");
+static RandomVariableDefaultValue
+g_direction ("RandomWalk2dDirection",
+ "A random variable used to pick the direction (gradients).",
+ "Uniform:0.0:6.283184");
+
+static RectangleDefaultValue
+g_rectangle ("RandomWalk2dBounds",
+ "Bounds of the area to cruise.",
+ 0.0, 0.0, 100.0, 100.0);
+
+RandomWalk2dMobilityModelParameters::RandomWalk2dMobilityModelParameters ()
+ : m_mode (g_mode.GetValue ()),
+ m_modeDistance (g_modeDistance.GetValue ()),
+ m_modeTime (g_modeTime.GetValue ()),
+ m_speed (g_speed.GetCopy ()),
+ m_direction (g_direction.GetCopy ()),
+ m_bounds (g_rectangle.GetValue ())
+{}
+
+RandomWalk2dMobilityModelParameters::~RandomWalk2dMobilityModelParameters ()
+{
+ delete m_speed;
+ delete m_direction;
+ m_speed = 0;
+ m_direction = 0;
+}
+
+void
+RandomWalk2dMobilityModelParameters::SetSpeed (const RandomVariable &speed)
+{
+ delete m_speed;
+ m_speed = speed.Copy ();
+}
+void
+RandomWalk2dMobilityModelParameters::SetDirection (const RandomVariable &direction)
+{
+ delete m_direction;
+ m_direction = direction.Copy ();
+}
+void
+RandomWalk2dMobilityModelParameters::SetModeDistance (double distance)
+{
+ m_mode = RandomWalk2dMobilityModelParameters::MODE_DISTANCE;
+ m_modeDistance = distance;
+}
+void
+RandomWalk2dMobilityModelParameters::SetModeTime (Time time)
+{
+ m_mode = RandomWalk2dMobilityModelParameters::MODE_TIME;
+ m_modeTime = time;
+}
+void
+RandomWalk2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
+{
+ m_bounds = bounds;
+}
+
+Ptr<RandomWalk2dMobilityModelParameters>
+RandomWalk2dMobilityModelParameters::GetCurrent (void)
+{
+ static Ptr<RandomWalk2dMobilityModelParameters> parameters = 0;
+ if (parameters == 0 ||
+ g_speed.IsDirty () ||
+ g_direction.IsDirty () ||
+ g_mode.IsDirty () ||
+ g_modeDistance.IsDirty () ||
+ g_modeTime.IsDirty () ||
+ g_rectangle.IsDirty ())
+ {
+ parameters = Create<RandomWalk2dMobilityModelParameters> ();
+ }
+ return parameters;
+}
+
+RandomWalk2dMobilityModel::RandomWalk2dMobilityModel ()
+ : m_parameters (RandomWalk2dMobilityModelParameters::GetCurrent ())
+{
+ SetInterfaceId (RandomWalk2dMobilityModel::iid);
+ m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
+}
+
+void
+RandomWalk2dMobilityModel::Start (void)
+{
+ double speed = m_parameters->m_speed->GetValue ();
+ double direction = m_parameters->m_direction->GetValue ();
+ Speed vector (std::cos (direction) * speed,
+ std::sin (direction) * speed,
+ 0.0);
+ m_helper.Reset (vector);
+
+ Time delayLeft;
+ if (m_parameters->m_mode == RandomWalk2dMobilityModelParameters::MODE_TIME)
+ {
+ delayLeft = m_parameters->m_modeTime;
+ }
+ else
+ {
+ delayLeft = Seconds (m_parameters->m_modeDistance / speed);
+ }
+ DoWalk (delayLeft);
+}
+
+void
+RandomWalk2dMobilityModel::DoWalk (Time delayLeft)
+{
+ Position position = m_helper.GetCurrentPosition ();
+ Speed speed = m_helper.GetSpeed ();
+ Position nextPosition = position;
+ nextPosition.x += speed.dx * delayLeft.GetSeconds ();
+ nextPosition.y += speed.dy * delayLeft.GetSeconds ();
+ if (m_parameters->m_bounds.IsInside (nextPosition))
+ {
+ m_event = Simulator::Schedule (delayLeft, &RandomWalk2dMobilityModel::Start, this);
+ }
+ else
+ {
+ nextPosition = m_parameters->m_bounds.CalculateIntersection (position, speed);
+ Time delay = Seconds ((nextPosition.x - position.x) / speed.dx);
+ m_event = Simulator::Schedule (delay, &RandomWalk2dMobilityModel::Rebound, this,
+ delayLeft - delay);
+ }
+ NotifyCourseChange ();
+}
+
+void
+RandomWalk2dMobilityModel::Rebound (Time delayLeft)
+{
+ Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+ Speed speed = m_helper.GetSpeed ();
+ switch (m_parameters->m_bounds.GetClosestSide (position))
+ {
+ case Rectangle::RIGHT:
+ case Rectangle::LEFT:
+ speed.dx = - speed.dx;
+ break;
+ case Rectangle::TOP:
+ case Rectangle::BOTTOM:
+ speed.dy = - speed.dy;
+ break;
+ }
+ m_helper.Reset (speed);
+ DoWalk (delayLeft);
+}
+
+void
+RandomWalk2dMobilityModel::DoDispose (void)
+{
+ m_parameters = 0;
+ // chain up
+ MobilityModel::DoDispose ();
+}
+Position
+RandomWalk2dMobilityModel::DoGet (void) const
+{
+ return m_helper.GetCurrentPosition (m_parameters->m_bounds);
+}
+void
+RandomWalk2dMobilityModel::DoSet (const Position &position)
+{
+ NS_ASSERT (m_parameters->m_bounds.IsInside (position));
+ m_helper.InitializePosition (position);
+ Simulator::Remove (m_event);
+ m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
+}
+Speed
+RandomWalk2dMobilityModel::DoGetSpeed (void) const
+{
+ return m_helper.GetSpeed ();
+}
+
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-walk-2d-mobility-model.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef RANDOM_WALK_2D_MOBILITY_MODEL_H
+#define RANDOM_WALK_2D_MOBILITY_MODEL_H
+
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+#include "ns3/component-manager.h"
+#include "ns3/event-id.h"
+#include "ns3/rectangle.h"
+#include "mobility-model.h"
+#include "static-speed-helper.h"
+
+namespace ns3 {
+
+class RandomVariable;
+
+/**
+ * \brief parameters to control a random walk 2d model
+ *
+ * A single parameter object can be shared by multiple random
+ * walk models.
+ */
+class RandomWalk2dMobilityModelParameters : public Object
+{
+ public:
+ /**
+ * Instantiate a set of RandomWalk parameters initialized
+ * with the Bind default values.
+ */
+ RandomWalk2dMobilityModelParameters ();
+ virtual ~RandomWalk2dMobilityModelParameters ();
+ /**
+ * \param speed the random variable used to pick a new
+ * speed when the direction is changed.
+ *
+ */
+ void SetSpeed (const RandomVariable &speed);
+ /**
+ * \param direction the random variable used to pick a new
+ * direction.
+ */
+ void SetDirection (const RandomVariable &direction);
+ /**
+ * \param distance the distance before a direction change
+ *
+ * Unit is meters.
+ * "time" mode is incompatible with "distance" mode.
+ */
+ void SetModeDistance (double distance);
+ /**
+ * \param time the delay before a direction change.
+ *
+ * "time" mode is incompatible with "distance" mode.
+ */
+ void SetModeTime (Time time);
+
+ /**
+ * \param bounds the bounds of the random walk
+ */
+ void SetBounds (const Rectangle &bounds);
+
+
+ // needed public for internal default value code.
+ enum Mode {
+ MODE_DISTANCE,
+ MODE_TIME
+ };
+ private:
+ friend class RandomWalk2dMobilityModel;
+ static Ptr<RandomWalk2dMobilityModelParameters> GetCurrent (void);
+
+ enum Mode m_mode;
+ double m_modeDistance;
+ Time m_modeTime;
+ RandomVariable *m_speed;
+ RandomVariable *m_direction;
+ Rectangle m_bounds;
+};
+
+/**
+ * \brief a 2D random walk position model
+ *
+ * Each instance moves with a speed and direction choosen at random
+ * with the user-provided random variables until
+ * either a fixed distance has been walked or until a fixed amount
+ * of time.
+ *
+ * The parameters of the model can be specified either with the ns3::Bind
+ * function and the variables "RandomWalk2dSpeed", "RandomWalk2dMode",
+ * "RandomWalk2dDistance", "RandomWalk2dTime", and, "RandomWalk2dBounds" or
+ * with an instance of the RandomWalk2dMobilityModelParameters class which
+ * must be fed to the RandomWalk2dMobilityModel constructors.
+ */
+class RandomWalk2dMobilityModel : public MobilityModel
+{
+ public:
+ static const ClassId cid;
+ /**
+ * Create a new position object located at position (0,0,0)
+ */
+ RandomWalk2dMobilityModel ();
+ /**
+ * \param parameters the parameters to use to control
+ * the movement of this mobile object.
+ *
+ * Create a new position object located at position (0,0,0) with
+ * the specified parameters.
+ */
+ RandomWalk2dMobilityModel (Ptr<RandomWalk2dMobilityModelParameters> parameters);
+
+ private:
+ void Start (void);
+ void Rebound (Time timeLeft);
+ void DoWalk (Time timeLeft);
+ virtual void DoDispose (void);
+ virtual Position DoGet (void) const;
+ virtual void DoSet (const Position &position);
+ virtual Speed DoGetSpeed (void) const;
+
+ StaticSpeedHelper m_helper;
+ EventId m_event;
+ Ptr<RandomWalk2dMobilityModelParameters> m_parameters;
+};
+
+
+} // namespace ns3
+
+#endif /* RANDOM_WALK_2D_MOBILITY_MODEL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-waypoint-mobility-model.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include <cmath>
+#include "ns3/simulator.h"
+#include "ns3/random-variable.h"
+#include "ns3/random-variable-default-value.h"
+#include "ns3/component-manager.h"
+#include "random-waypoint-mobility-model.h"
+#include "random-position.h"
+
+namespace ns3 {
+
+static RandomVariableDefaultValue
+g_speed ("RandomWaypointSpeed",
+ "A random variable used to pick the speed of a random waypoint model.",
+ "Uniform:0.3:0.7");
+
+static RandomVariableDefaultValue
+g_pause ("RandomWaypointPause",
+ "A random variable used to pick the pause of a random waypoint model.",
+ "Constant:2");
+
+static ClassIdDefaultValue
+g_position ("RandomWaypointPosition",
+ "A random position model used to pick the next waypoint position.",
+ RandomPosition::iid,
+ "RandomRectanglePosition");
+
+const ClassId RandomWaypointMobilityModel::cid =
+ MakeClassId<RandomWaypointMobilityModel> ("RandomWaypointMobilityModel", MobilityModel::iid);
+
+RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters ()
+ : m_speed (g_speed.GetCopy ()),
+ m_pause (g_pause.GetCopy ())
+{
+ m_position = ComponentManager::Create<RandomPosition> (g_position.GetValue (),
+ RandomPosition::iid);
+}
+RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
+ const RandomVariable &speed,
+ const RandomVariable &pause)
+ : m_speed (speed.Copy ()),
+ m_pause (pause.Copy ()),
+ m_position (randomPosition)
+{}
+void
+RandomWaypointMobilityModelParameters::SetWaypointPositionModel (Ptr<RandomPosition> randomPosition)
+{
+ m_position = randomPosition;
+}
+void
+RandomWaypointMobilityModelParameters::SetSpeed (const RandomVariable &speed)
+{
+ delete m_speed;
+ m_speed = speed.Copy ();
+}
+void
+RandomWaypointMobilityModelParameters::SetPause (const RandomVariable &pause)
+{
+ delete m_pause;
+ m_pause = pause.Copy ();
+}
+void
+RandomWaypointMobilityModelParameters::DoDispose (void)
+{
+ m_position = 0;
+ delete m_pause;
+ delete m_speed;
+ m_pause = 0;
+ m_speed = 0;
+}
+
+Ptr<RandomWaypointMobilityModelParameters>
+RandomWaypointMobilityModelParameters::GetCurrent (void)
+{
+ static Ptr<RandomWaypointMobilityModelParameters> parameters = 0;
+ if (parameters == 0 ||
+ g_position.IsDirty () ||
+ g_pause.IsDirty () ||
+ g_speed.IsDirty ())
+ {
+ parameters = Create<RandomWaypointMobilityModelParameters> ();
+ }
+ return parameters;
+}
+
+RandomWaypointMobilityModel::RandomWaypointMobilityModel ()
+ : m_parameters (RandomWaypointMobilityModelParameters::GetCurrent ())
+{
+ Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
+}
+
+RandomWaypointMobilityModel::RandomWaypointMobilityModel (Ptr<RandomWaypointMobilityModelParameters> parameters)
+ : m_parameters (parameters)
+{
+ Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
+ NotifyCourseChange ();
+}
+
+void
+RandomWaypointMobilityModel::BeginWalk (void)
+{
+ Position m_current = m_helper.GetCurrentPosition ();
+ Position destination = m_parameters->m_position->Get ();
+ double speed = m_parameters->m_speed->GetValue ();
+ double dx = (destination.x - m_current.x);
+ double dy = (destination.y - m_current.y);
+ double dz = (destination.z - m_current.z);
+ double k = speed / std::sqrt (dx*dx + dy*dy + dz*dz);
+
+ m_helper.Reset (Speed (k*dx, k*dy, k*dz));
+ Time travelDelay = Seconds (CalculateDistance (destination, m_current) / speed);
+ m_event = Simulator::Schedule (travelDelay,
+ &RandomWaypointMobilityModel::Start, this);
+ NotifyCourseChange ();
+}
+
+void
+RandomWaypointMobilityModel::Start (void)
+{
+ Time pause = Seconds (m_parameters->m_pause->GetValue ());
+ m_helper.Pause ();
+ NotifyCourseChange ();
+ m_event = Simulator::Schedule (pause, &RandomWaypointMobilityModel::BeginWalk, this);
+}
+
+Position
+RandomWaypointMobilityModel::DoGet (void) const
+{
+ return m_helper.GetCurrentPosition ();
+}
+void
+RandomWaypointMobilityModel::DoSet (const Position &position)
+{
+ m_helper.InitializePosition (position);
+ Simulator::Remove (m_event);
+ Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
+}
+Speed
+RandomWaypointMobilityModel::DoGetSpeed (void) const
+{
+ return m_helper.GetSpeed ();
+}
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-waypoint-mobility-model.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef RANDOM_WAYPOINT_MOBILITY_MODEL_H
+#define RANDOM_WAYPOINT_MOBILITY_MODEL_H
+
+#include "static-speed-helper.h"
+#include "mobility-model.h"
+#include "random-position.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class RandomVariable;
+
+/**
+ * \brief the parameters which control the behavior of a random waypoint
+ * mobility model.
+ */
+class RandomWaypointMobilityModelParameters : public Object
+{
+public:
+ /**
+ * Defaults parameters based on the Bind values.
+ */
+ RandomWaypointMobilityModelParameters ();
+ /**
+ * \param randomPosition a random position model to choose the position of waypoints.
+ * \param speed a random variable to choose the speed
+ * \param pause a random variable to choose the pause delay
+ */
+ RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
+ const RandomVariable &speed,
+ const RandomVariable &pause);
+ /**
+ * \param randomPosition a random position model to choose the position of waypoints.
+ */
+ void SetWaypointPositionModel (Ptr<RandomPosition> randomPosition);
+ /**
+ * \param speed a random variable to choose the speed
+ */
+ void SetSpeed (const RandomVariable &speed);
+ /**
+ * \param pause a random variable to choose the pause delay
+ */
+ void SetPause (const RandomVariable &pause);
+private:
+ friend class RandomWaypointMobilityModel;
+ static Ptr<RandomWaypointMobilityModelParameters> GetCurrent (void);
+ virtual void DoDispose (void);
+ RandomVariable *m_speed;
+ RandomVariable *m_pause;
+ Ptr<RandomPosition> m_position;
+};
+
+/**
+ * \brief a random waypoint mobility model
+ *
+ * Each object chooses a random destination "waypoint", a random speed,
+ * and a random pause time: it then pauses for the specified pause time,
+ * and starts moving towards the specified destination with the specified
+ * speed. Once the destination is reached the process starts again.
+ *
+ * The implementation of this model is not 2d-specific. i.e. if you provide
+ * a 3d random waypoint position model to this mobility model, the model
+ * will still work.
+ */
+class RandomWaypointMobilityModel : public MobilityModel
+{
+public:
+ static const ClassId cid;
+
+ /**
+ * Create a waypoint mobility model from the Bind default values.
+ */
+ RandomWaypointMobilityModel ();
+ /**
+ * \param parameters the parameters which control the behavior of this model.
+ */
+ RandomWaypointMobilityModel (Ptr<RandomWaypointMobilityModelParameters> parameters);
+private:
+ void Start (void);
+ void BeginWalk (void);
+ virtual Position DoGet (void) const;
+ virtual void DoSet (const Position &position);
+ virtual Speed DoGetSpeed (void) const;
+
+ StaticSpeedHelper m_helper;
+ Ptr<RandomWaypointMobilityModelParameters> m_parameters;
+ EventId m_event;
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_WAYPOINT_MOBILITY_MODEL_H */
--- a/src/mobility/rectangle.cc Mon Oct 08 11:23:53 2007 +0100
+++ b/src/mobility/rectangle.cc Mon Oct 08 11:24:16 2007 +0100
@@ -45,17 +45,17 @@
Rectangle::IsInside (const Position &position) const
{
return
- position.x <= xMax && position.x >= xMin &&
- position.y <= yMax && position.y >= yMin;
+ position.x <= this->xMax && position.x >= this->xMin &&
+ position.y <= this->yMax && position.y >= this->yMin;
}
Rectangle::Side
Rectangle::GetClosestSide (const Position &position) const
{
- double xMinDist = std::abs (position.x - xMin);
- double xMaxDist = std::abs (xMax - position.x);
- double yMinDist = std::abs (position.y - yMin);
- double yMaxDist = std::abs (yMax - position.y);
+ double xMinDist = std::abs (position.x - this->xMin);
+ double xMaxDist = std::abs (this->xMax - position.x);
+ double yMinDist = std::abs (position.y - this->yMin);
+ double yMaxDist = std::abs (this->yMax - position.y);
double minX = std::min (xMinDist, xMaxDist);
double minY = std::min (yMinDist, yMaxDist);
if (minX < minY)
@@ -85,29 +85,29 @@
Position
Rectangle::CalculateIntersection (const Position ¤t, const Speed &speed) const
{
- double xMaxY = current.y + (xMax - current.x) / speed.dx * speed.dy;
- double xMinY = current.y + (xMin - current.x) / speed.dx * speed.dy;
- double yMaxX = current.x + (yMax - current.y) / speed.dy * speed.dx;
- double yMinX = current.x + (yMin - current.y) / speed.dy * speed.dx;
- bool xMaxOk = xMaxY <= yMax && xMaxY >= yMin;
- bool xMinOk = xMinY <= yMax && xMinY >= yMin;
- bool yMaxOk = yMaxX <= xMax && yMaxX >= xMin;
- bool yMinOk = yMinX <= xMax && yMinX >= xMin;
- if (xMaxOk && speed.dx >= 0)
+ double xMaxY = current.y + (this->xMax - current.x) / speed.dx * speed.dy;
+ double xMinY = current.y + (this->xMin - current.x) / speed.dx * speed.dy;
+ double yMaxX = current.x + (this->yMax - current.y) / speed.dy * speed.dx;
+ double yMinX = current.x + (this->yMin - current.y) / speed.dy * speed.dx;
+ bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
+ bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
+ bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
+ bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
+ if (xMaxYOk && speed.dx >= 0)
{
- return Position (xMax, xMaxY, 0.0);
+ return Position (this->xMax, xMaxY, 0.0);
}
- else if (xMinOk && speed.dx <= 0)
+ else if (xMinYOk && speed.dx <= 0)
{
- return Position (xMin, xMinY, 0.0);
+ return Position (this->xMin, xMinY, 0.0);
}
- else if (yMaxOk && speed.dy >= 0)
+ else if (yMaxXOk && speed.dy >= 0)
{
- return Position (yMaxX, yMax, 0.0);
+ return Position (yMaxX, this->yMax, 0.0);
}
- else if (yMinOk && speed.dy <= 0)
+ else if (yMinXOk && speed.dy <= 0)
{
- return Position (yMinX, yMin, 0.0);
+ return Position (yMinX, this->yMin, 0.0);
}
else
{
--- a/src/mobility/static-speed-helper.cc Mon Oct 08 11:23:53 2007 +0100
+++ b/src/mobility/static-speed-helper.cc Mon Oct 08 11:24:16 2007 +0100
@@ -31,7 +31,8 @@
StaticSpeedHelper::StaticSpeedHelper (const Position &position,
const Speed &speed)
: m_position (position),
- m_speed (speed)
+ m_speed (speed),
+ m_paused (true)
{}
void
StaticSpeedHelper::InitializePosition (const Position &position)
@@ -41,14 +42,7 @@
m_speed.dy = 0.0;
m_speed.dz = 0.0;
m_lastUpdate = Simulator::Now ();
- m_pauseEnd = Simulator::Now ();
-}
-
-void
-StaticSpeedHelper::Reset (const Speed &speed, const Time &pauseDelay)
-{
- Reset (speed);
- m_pauseEnd = Simulator::Now () + pauseDelay;
+ m_paused = true;
}
Position
@@ -61,7 +55,7 @@
Speed
StaticSpeedHelper::GetSpeed (void) const
{
- return m_speed;
+ return m_paused? Speed (0, 0, 0) : m_speed;
}
void
StaticSpeedHelper::SetSpeed (const Speed &speed)
@@ -73,17 +67,13 @@
void
StaticSpeedHelper::Update (void) const
{
- Time now = Simulator::Now ();
- if (m_pauseEnd > now)
+ if (m_paused)
{
return;
}
- Time last = std::max (now, m_pauseEnd);
- if (m_lastUpdate >= last)
- {
- return;
- }
- Time deltaTime = now - last;
+ Time now = Simulator::Now ();
+ NS_ASSERT (m_lastUpdate <= now);
+ Time deltaTime = now - m_lastUpdate;
m_lastUpdate = now;
double deltaS = deltaTime.GetSeconds ();
m_position.x += m_speed.dx * deltaS;
@@ -96,7 +86,7 @@
{
Update ();
m_speed = speed;
- m_pauseEnd = Simulator::Now ();
+ Unpause ();
}
void
StaticSpeedHelper::UpdateFull (const Rectangle &bounds) const
@@ -115,5 +105,21 @@
return m_position;
}
+void
+StaticSpeedHelper::Pause (void)
+{
+ Update ();
+ m_paused = true;
+}
+
+void
+StaticSpeedHelper::Unpause (void)
+{
+ if (m_paused)
+ {
+ m_lastUpdate = Simulator::Now ();
+ m_paused = false;
+ }
+}
} // namespace ns3
--- a/src/mobility/static-speed-helper.h Mon Oct 08 11:23:53 2007 +0100
+++ b/src/mobility/static-speed-helper.h Mon Oct 08 11:24:16 2007 +0100
@@ -37,12 +37,13 @@
const Speed &speed);
void InitializePosition (const Position &position);
- void Reset (const Speed &speed, const Time &pauseDelay);
void Reset (const Speed &speed);
Position GetCurrentPosition (const Rectangle &bounds) const;
Position GetCurrentPosition (void) const;
Speed GetSpeed (void) const;
void SetSpeed (const Speed &speed);
+ void Pause (void);
+ void Unpause (void);
private:
void Update (void) const;
@@ -50,7 +51,7 @@
mutable Time m_lastUpdate;
mutable Position m_position;
Speed m_speed;
- Time m_pauseEnd;
+ bool m_paused;
};
} // namespace ns3
--- a/src/mobility/wscript Mon Oct 08 11:23:53 2007 +0100
+++ b/src/mobility/wscript Mon Oct 08 11:24:16 2007 +0100
@@ -16,6 +16,10 @@
'static-mobility-model.cc',
'static-speed-helper.cc',
'static-speed-mobility-model.cc',
+ 'random-waypoint-mobility-model.cc',
+ 'random-walk-2d-mobility-model.cc',
+ 'random-direction-2d-mobility-model.cc',
+ 'ns2-mobility-file-topology.cc',
]
headers = bld.create_obj('ns3header')
@@ -33,4 +37,8 @@
'static-mobility-model.h',
'static-speed-helper.h',
'static-speed-mobility-model.h',
+ 'random-waypoint-mobility-model.h',
+ 'random-walk-2d-mobility-model.h',
+ 'random-direction-2d-mobility-model.h',
+ 'ns2-mobility-file-topology.h',
]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event-garbage-collector.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,152 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ * 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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+#include "event-garbage-collector.h"
+
+#define CLEANUP_CHUNK_MIN_SIZE 8
+#define CLEANUP_CHUNK_MAX_SIZE 128
+
+
+namespace ns3 {
+
+
+EventGarbageCollector::EventGarbageCollector () :
+ m_nextCleanupSize (CLEANUP_CHUNK_MIN_SIZE)
+{}
+
+void
+EventGarbageCollector::Track (EventId event)
+{
+ m_events.push_back (event);
+ if (m_events.size () >= m_nextCleanupSize)
+ Cleanup ();
+}
+
+inline bool
+EventExpiredPredicate (const EventId &event)
+{
+ return event.IsExpired ();
+}
+
+void
+EventGarbageCollector::Grow ()
+{
+ m_nextCleanupSize += (m_nextCleanupSize < CLEANUP_CHUNK_MAX_SIZE?
+ m_nextCleanupSize : CLEANUP_CHUNK_MAX_SIZE);
+}
+
+void
+EventGarbageCollector::Shrink ()
+{
+ while (m_nextCleanupSize > m_events.size ())
+ m_nextCleanupSize >>= 1;
+ Grow ();
+}
+
+// Called when a new event was added and the cleanup limit was exceeded in consequence.
+void
+EventGarbageCollector::Cleanup ()
+{
+ m_events.remove_if (EventExpiredPredicate);
+
+ // If after cleanup we are still over the limit, increase the limit.
+ if (m_events.size () >= m_nextCleanupSize)
+ Grow ();
+ else
+ Shrink ();
+}
+
+
+EventGarbageCollector::~EventGarbageCollector ()
+{
+ for (std::list<EventId>::iterator event = m_events.begin ();
+ event != m_events.end (); event++)
+ {
+ Simulator::Cancel (*event);
+ }
+}
+
+}; // namespace ns3
+
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+
+namespace ns3 {
+
+class EventGarbageCollectorTests : public Test
+{
+ int m_counter;
+ EventGarbageCollector *m_events;
+
+ void EventGarbageCollectorCallback ();
+
+public:
+
+ EventGarbageCollectorTests ();
+ virtual ~EventGarbageCollectorTests ();
+ virtual bool RunTests (void);
+};
+
+EventGarbageCollectorTests::EventGarbageCollectorTests ()
+ : Test ("EventGarbageCollector"), m_counter (0), m_events (0)
+{}
+
+EventGarbageCollectorTests::~EventGarbageCollectorTests ()
+{}
+
+void
+EventGarbageCollectorTests::EventGarbageCollectorCallback ()
+{
+ m_counter++;
+ if (m_counter == 50)
+ {
+ // this should cause the remaining (50) events to be cancelled
+ delete m_events;
+ m_events = 0;
+ }
+}
+
+bool EventGarbageCollectorTests::RunTests (void)
+{
+ bool result = true;
+
+ m_events = new EventGarbageCollector ();
+
+ for (int n = 0; n < 100; n++)
+ {
+ m_events->Track (Simulator::Schedule
+ (Simulator::Now (),
+ &EventGarbageCollectorTests::EventGarbageCollectorCallback,
+ this));
+ }
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_events, 0);
+ NS_TEST_ASSERT_EQUAL (m_counter, 50);
+ return result;
+}
+
+static EventGarbageCollectorTests g_eventCollectorTests;
+
+};
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/event-garbage-collector.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ * 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: Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+#ifndef EVENT_GARBAGE_COLLECTOR_H
+#define EVENT_GARBAGE_COLLECTOR_H
+
+#include <list>
+#include "event-id.h"
+#include "simulator.h"
+
+namespace ns3 {
+
+/**
+ * \brief An object that tracks scheduled events and automatically
+ * cancels them when it is destroyed. It is useful in situations
+ * where multiple instances of the same type of event can
+ * simultaneously be scheduled, and when the events should be limited
+ * to the lifetime of a container object.
+ */
+class EventGarbageCollector
+{
+public:
+
+ EventGarbageCollector ();
+
+ /**
+ * \brief Tracks a new event
+ */
+ void Track (EventId event);
+
+ ~EventGarbageCollector ();
+
+private:
+
+ std::list<EventId>::size_type m_nextCleanupSize;
+ std::list<EventId> m_events;
+
+ void Cleanup ();
+ void Grow ();
+ void Shrink ();
+};
+
+}; // namespace ns3
+
+#endif /* EVENT_GARBAGE_COLLECTOR_H */
--- a/src/simulator/simulator.cc Mon Oct 08 11:23:53 2007 +0100
+++ b/src/simulator/simulator.cc Mon Oct 08 11:24:16 2007 +0100
@@ -67,9 +67,10 @@
EventId ScheduleDestroy (const Ptr<EventImpl> &event);
void Remove (const EventId &ev);
void Cancel (const EventId &ev);
- bool IsExpired (const EventId &ev);
+ bool IsExpired (const EventId &ev) const;
void Run (void);
Time Now (void) const;
+ Time GetDelayLeft (const EventId &id) const;
private:
void ProcessOneEvent (void);
@@ -251,6 +252,18 @@
{
return TimeStep (m_currentTs);
}
+Time
+SimulatorPrivate::GetDelayLeft (const EventId &id) const
+{
+ if (IsExpired (id))
+ {
+ return TimeStep (0);
+ }
+ else
+ {
+ return TimeStep (id.GetTs () - m_currentTs);
+ }
+}
void
SimulatorPrivate::Remove (const EventId &ev)
@@ -293,12 +306,12 @@
}
bool
-SimulatorPrivate::IsExpired (const EventId &ev)
+SimulatorPrivate::IsExpired (const EventId &ev) const
{
if (ev.GetUid () == 2)
{
// destroy events.
- for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
+ for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
{
if (*i == ev)
{
@@ -411,6 +424,11 @@
{
return GetPriv ()->Now ();
}
+Time
+Simulator::GetDelayLeft (const EventId &id)
+{
+ return GetPriv ()->GetDelayLeft (id);
+}
Ptr<EventImpl>
Simulator::MakeEvent (void (*f) (void))
--- a/src/simulator/simulator.h Mon Oct 08 11:23:53 2007 +0100
+++ b/src/simulator/simulator.h Mon Oct 08 11:24:16 2007 +0100
@@ -552,6 +552,13 @@
* Return the "current simulation time".
*/
static Time Now (void);
+ /**
+ * \param id the event id to analyse
+ * \returns the delay left until the input event id expires.
+ * if the event is not running, this method returns
+ * zero.
+ */
+ static Time GetDelayLeft (const EventId &id);
private:
Simulator ();
~Simulator ();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/timer.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,325 @@
+#include "timer.h"
+#include "simulator.h"
+#include "simulation-singleton.h"
+#include "event-garbage-collector.h"
+
+namespace ns3 {
+
+Timer::Timer ()
+ : m_flags (0),
+ m_delay (FemtoSeconds (0)),
+ m_event (),
+ m_impl (0)
+{}
+
+Timer::Timer (enum SchedulePolicy schedulePolicy,
+ enum DestroyPolicy destroyPolicy)
+ : m_flags (schedulePolicy | destroyPolicy),
+ m_delay (FemtoSeconds (0)),
+ m_event (),
+ m_impl (0)
+{}
+
+Timer::Timer (enum GarbageCollectPolicy policy)
+ : m_flags (GARBAGE_COLLECT),
+ m_delay (FemtoSeconds (0)),
+ m_event (),
+ m_impl (0)
+{}
+
+Timer::~Timer ()
+{
+ if (m_flags & CHECK_ON_DESTROY)
+ {
+ if (m_event.IsRunning ())
+ {
+ NS_FATAL_ERROR ("Event is still running while destroying.");
+ }
+ }
+ else if (m_flags & CANCEL_ON_DESTROY)
+ {
+ m_event.Cancel ();
+ }
+ else if (m_flags & REMOVE_ON_DESTROY)
+ {
+ Simulator::Remove (m_event);
+ }
+ delete m_impl;
+}
+
+void
+Timer::SetDelay (const Time &time)
+{
+ m_delay = time;
+}
+Time
+Timer::GetDelay (void) const
+{
+ return m_delay;
+}
+Time
+Timer::GetDelayLeft (void) const
+{
+ switch (GetState ()) {
+ case Timer::RUNNING:
+ return Simulator::GetDelayLeft (m_event);
+ break;
+ case Timer::EXPIRED:
+ return TimeStep (0);
+ break;
+ case Timer::SUSPENDED:
+ return m_delayLeft;
+ break;
+ default:
+ NS_ASSERT (false);
+ return TimeStep (0);
+ break;
+ }
+}
+
+void
+Timer::Cancel (void)
+{
+ Simulator::Cancel (m_event);
+}
+void
+Timer::Remove (void)
+{
+ Simulator::Remove (m_event);
+}
+bool
+Timer::IsExpired (void) const
+{
+ return !IsSuspended () && m_event.IsExpired ();
+}
+bool
+Timer::IsRunning (void) const
+{
+ return !IsSuspended () && m_event.IsRunning ();
+}
+bool
+Timer::IsSuspended (void) const
+{
+ return (m_flags & TIMER_SUSPENDED) == TIMER_SUSPENDED;
+}
+enum Timer::State
+Timer::GetState (void) const
+{
+ if (IsRunning ())
+ {
+ return Timer::RUNNING;
+ }
+ else if (IsExpired ())
+ {
+ return Timer::EXPIRED;
+ }
+ else
+ {
+ NS_ASSERT (IsSuspended ());
+ return Timer::SUSPENDED;
+ }
+}
+
+void
+Timer::Schedule (void)
+{
+ Schedule (m_delay);
+}
+
+void
+Timer::Schedule (Time delay)
+{
+ NS_ASSERT (m_impl != 0);
+ if (m_flags & CHECK_ON_SCHEDULE)
+ {
+ if (m_event.IsRunning ())
+ {
+ NS_FATAL_ERROR ("Event is still running while re-scheduling.");
+ }
+ }
+ else if (m_flags & CANCEL_ON_SCHEDULE)
+ {
+ m_event.Cancel ();
+ }
+ else if (m_flags & REMOVE_ON_SCHEDULE)
+ {
+ Simulator::Remove (m_event);
+ }
+ m_event = m_impl->Schedule (delay);
+ if (m_flags & GARBAGE_COLLECT)
+ {
+ SimulationSingleton<EventGarbageCollector>::Get ()->Track (m_event);
+ }
+}
+
+void
+Timer::Suspend (void)
+{
+ NS_ASSERT (IsRunning ());
+ m_delayLeft = Simulator::GetDelayLeft (m_event);
+ Simulator::Remove (m_event);
+ m_flags |= TIMER_SUSPENDED;
+}
+
+void
+Timer::Resume (void)
+{
+ NS_ASSERT (m_flags & TIMER_SUSPENDED);
+ m_event = m_impl->Schedule (m_delayLeft);
+ m_flags &= ~TIMER_SUSPENDED;
+}
+
+
+} // namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+#include "ns3/test.h"
+
+namespace {
+void bari (int)
+{}
+void bar2i (int, int)
+{}
+void bar3i (int, int, int)
+{}
+void bar4i (int, int, int, int)
+{}
+void bar5i (int, int, int, int, int)
+{}
+void bar6i (int, int, int, int, int, int)
+{}
+void barcir (const int &)
+{}
+void barir (int &)
+{}
+void barip (int *)
+{}
+void barcip (const int *)
+{}
+}
+
+namespace ns3 {
+
+class TimerTests : public Test
+{
+public:
+ TimerTests ();
+ virtual bool RunTests (void);
+ void bazi (int) {}
+ void baz2i (int, int) {}
+ void baz3i (int, int, int) {}
+ void baz4i (int, int, int, int) {}
+ void baz5i (int, int, int, int, int) {}
+ void baz6i (int, int, int, int, int, int) {}
+ void bazcir (const int&) {}
+ void bazir (int&) {}
+ void bazip (int *) {}
+ void bazcip (const int *) {}
+};
+
+TimerTests::TimerTests ()
+ : Test ("Timer")
+{}
+
+bool
+TimerTests::RunTests (void)
+{
+ bool result = true;
+
+ Timer timer;
+
+ timer.SetFunction (&bari);
+ timer.SetArguments (1);
+ timer.SetDelay (Seconds (10.0));
+ NS_TEST_ASSERT (!timer.IsRunning ());
+ NS_TEST_ASSERT (timer.IsExpired ());
+ NS_TEST_ASSERT (!timer.IsSuspended ());
+ NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::EXPIRED);
+ timer.Schedule ();
+ NS_TEST_ASSERT (timer.IsRunning ());
+ NS_TEST_ASSERT (!timer.IsExpired ());
+ NS_TEST_ASSERT (!timer.IsSuspended ());
+ NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::RUNNING);
+ timer.Suspend ();
+ NS_TEST_ASSERT (!timer.IsRunning ());
+ NS_TEST_ASSERT (!timer.IsExpired ());
+ NS_TEST_ASSERT (timer.IsSuspended ());
+ NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::SUSPENDED);
+ timer.Resume ();
+ NS_TEST_ASSERT (timer.IsRunning ());
+ NS_TEST_ASSERT (!timer.IsExpired ());
+ NS_TEST_ASSERT (!timer.IsSuspended ());
+ NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::RUNNING);
+ timer.Cancel ();
+ NS_TEST_ASSERT (!timer.IsRunning ());
+ NS_TEST_ASSERT (timer.IsExpired ());
+ NS_TEST_ASSERT (!timer.IsSuspended ());
+ NS_TEST_ASSERT_EQUAL (timer.GetState (), Timer::EXPIRED);
+
+ int a = 0;
+ int &b = a;
+ const int &c = a;
+
+ timer.SetFunction (&bari);
+ timer.SetArguments (2);
+ timer.SetArguments (a);
+ timer.SetArguments (b);
+ timer.SetArguments (c);
+ timer.SetFunction (&barir);
+ timer.SetArguments (2);
+ timer.SetArguments (a);
+ timer.SetArguments (b);
+ timer.SetArguments (c);
+ timer.SetFunction (&barcir);
+ timer.SetArguments (2);
+ timer.SetArguments (a);
+ timer.SetArguments (b);
+ timer.SetArguments (c);
+ // the following call cannot possibly work and is flagged by
+ // a runtime error.
+ //timer.SetArguments (0.0);
+ timer.SetDelay (Seconds (1.0));
+ timer.Schedule ();
+
+ timer.SetFunction (&TimerTests::bazi, this);
+ timer.SetArguments (3);
+ timer.SetFunction (&TimerTests::bazir, this);
+ timer.SetArguments (3);
+ timer.SetFunction (&TimerTests::bazcir, this);
+ timer.SetArguments (3);
+
+ timer.SetFunction (&bar2i);
+ timer.SetArguments (1, 1);
+ timer.SetFunction (&bar3i);
+ timer.SetArguments (1, 1, 1);
+ timer.SetFunction (&bar4i);
+ timer.SetArguments (1, 1, 1, 1);
+ timer.SetFunction (&bar5i);
+ timer.SetArguments (1, 1, 1, 1, 1);
+ //timer.SetFunction (&bar6i);
+ //timer.SetArguments (1, 1, 1, 1, 1, 1);
+
+ timer.SetFunction (&TimerTests::baz2i, this);
+ timer.SetArguments (1, 1);
+ timer.SetFunction (&TimerTests::baz3i, this);
+ timer.SetArguments (1, 1, 1);
+ timer.SetFunction (&TimerTests::baz4i, this);
+ timer.SetArguments (1, 1, 1, 1);
+ timer.SetFunction (&TimerTests::baz5i, this);
+ timer.SetArguments (1, 1, 1, 1, 1);
+ //timer.SetFunction (&TimerTests::baz6i, this);
+ //timer.SetArguments (1, 1, 1, 1, 1, 1);
+
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return result;
+}
+
+TimerTests g_tests;
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/timer.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,991 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "ns3/fatal-error.h"
+#include "nstime.h"
+#include "event-id.h"
+#include "ns3/int-to-type.h"
+
+namespace ns3 {
+
+class TimerImpl;
+
+/**
+ * \brief a simple Timer class
+ *
+ * A timer is used to hold together a delay, a function to invoke
+ * when the delay expires, and a set of arguments to pass to the function
+ * when the delay expires.
+ *
+ * A timer can also be used to enforce a set of predefined event lifetime
+ * management policies. These policies are specified at construction time
+ * and cannot be changed after.
+ */
+class Timer
+{
+public:
+ enum SchedulePolicy {
+ /**
+ * This policy cancels the event before scheduling a new event
+ * for each call to Timer::Schedule.
+ */
+ CANCEL_ON_SCHEDULE = (1<<0),
+ /**
+ * This policy removes the event from the simulation event list
+ * before scheduling a new event for each call to Timer::Schedule.
+ */
+ REMOVE_ON_SCHEDULE = (1<<1),
+ /**
+ * This policy enforces a check before each call to Timer::Schedule
+ * to verify that the timer has already expired.
+ */
+ CHECK_ON_SCHEDULE = (1<<2),
+ };
+ enum DestroyPolicy {
+ /**
+ * This policy cancels the event from the destructor of the Timer
+ * to verify that the event has already expired.
+ */
+ CANCEL_ON_DESTROY = (1<<3),
+ /**
+ * This policy removes the event from the simulation event list
+ * when the destructor of the Timer is invoked.
+ */
+ REMOVE_ON_DESTROY = (1<<4),
+ /**
+ * This policy enforces a check from the destructor of the Timer
+ * to verify that the timer has already expired.
+ */
+ CHECK_ON_DESTROY = (1<<5)
+ };
+ enum GarbageCollectPolicy {
+ /**
+ * Every event scheduled with this policy is kept track of by an
+ * event garbage collector which makes sure that all events
+ * of timers with a GARBAGE_COLLECT policy are cancelled at the
+ * end of the simulation.
+ */
+ GARBAGE_COLLECT = (1<<6)
+ };
+ enum State {
+ RUNNING,
+ EXPIRED,
+ SUSPENDED,
+ };
+ /**
+ * create a timer with a default event lifetime management policy:
+ * - CHECK_ON_SCHEDULE
+ * - CHECK_ON_DESTROY
+ */
+ Timer ();
+ /**
+ * \param scheduleFlags the event lifetime management policies to use for schedule events
+ * \param destroyFlags the event lifetime management policies to use for destroy events
+ */
+ Timer (enum SchedulePolicy schedulePolicy,
+ enum DestroyPolicy destroyPolicy);
+ /**
+ * \param policy the garbage collect policy. Only one
+ * value is possible.
+ */
+ Timer (enum GarbageCollectPolicy policy);
+ ~Timer ();
+
+ /**
+ * \param fn the function
+ *
+ * Store this function in this Timer for later use by Timer::Schedule.
+ */
+ template <typename FN>
+ void SetFunction (FN fn);
+
+ /**
+ * \param memPtr the member function pointer
+ * \param objPtr the pointer to object
+ *
+ * Store this function and object in this Timer for later use by Timer::Schedule.
+ */
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void SetFunction (MEM_PTR memPtr, OBJ_PTR objPtr);
+
+
+ /**
+ * \param a1 the first argument
+ *
+ * Store this argument in this Timer for later use by Timer::Schedule.
+ */
+ template <typename T1>
+ void SetArguments (T1 a1);
+ /**
+ * \param a1 the first argument
+ * \param a2 the second argument
+ *
+ * Store these arguments in this Timer for later use by Timer::Schedule.
+ */
+ template <typename T1, typename T2>
+ void SetArguments (T1 a1, T2 a2);
+ /**
+ * \param a1 the first argument
+ * \param a2 the second argument
+ * \param a3 the third argument
+ *
+ * Store these arguments in this Timer for later use by Timer::Schedule.
+ */
+ template <typename T1, typename T2, typename T3>
+ void SetArguments (T1 a1, T2 a2, T3 a3);
+ /**
+ * \param a1 the first argument
+ * \param a2 the second argument
+ * \param a3 the third argument
+ * \param a4 the fourth argument
+ *
+ * Store these arguments in this Timer for later use by Timer::Schedule.
+ */
+ template <typename T1, typename T2, typename T3, typename T4>
+ void SetArguments (T1 a1, T2 a2, T3 a3, T4 a4);
+ /**
+ * \param a1 the first argument
+ * \param a2 the second argument
+ * \param a3 the third argument
+ * \param a4 the fourth argument
+ * \param a5 the fifth argument
+ *
+ * Store these arguments in this Timer for later use by Timer::Schedule.
+ */
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ void SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+ /**
+ * \param a1 the first argument
+ * \param a2 the second argument
+ * \param a3 the third argument
+ * \param a4 the fourth argument
+ * \param a5 the fifth argument
+ * \param a6 the sixth argument
+ *
+ * Store these arguments in this Timer for later use by Timer::Schedule.
+ */
+ template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ void SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
+
+ /**
+ * \param delay the delay
+ *
+ * The next call to Schedule will schedule the timer with this delay.
+ */
+ void SetDelay (const Time &delay);
+ /**
+ * \returns the currently-configured delay for the next Schedule.
+ */
+ Time GetDelay (void) const;
+ /**
+ * \returns the amount of time left until this timer expires.
+ *
+ * This method returns zero if the timer is in EXPIRED state.
+ */
+ Time GetDelayLeft (void) const;
+ /**
+ * Cancel the currently-running event if there is one. Do nothing
+ * otherwise.
+ */
+ void Cancel (void);
+ /**
+ * Remove from the simulation event-list the currently-running event
+ * if there is one. Do nothing otherwise.
+ */
+ void Remove (void);
+ /**
+ * \return true if there is no currently-running event, false otherwise.
+ */
+ bool IsExpired (void) const;
+ /**
+ * \return true if there is a currently-running event, false otherwise.
+ */
+ bool IsRunning (void) const;
+ /**
+ * \returns true if this timer was suspended and not yet resumed, false
+ * otherwise.
+ */
+ bool IsSuspended (void) const;
+ /**
+ * \returns the current state of the timer.
+ */
+ enum Timer::State GetState (void) const;
+ /**
+ * Schedule a new event using the currently-configured delay, function,
+ * and arguments.
+ */
+ void Schedule (void);
+ /**
+ * \param delay the delay to use
+ *
+ * Schedule a new event using the specified delay (ignore the delay set by
+ * Timer::SetDelay), function, and arguments.
+ */
+ void Schedule (Time delay);
+
+ /**
+ * Cancel the timer and save the amount of time left until it was
+ * set to expire.
+ * Calling Suspend on a non-running timer is an error.
+ */
+ void Suspend (void);
+ /**
+ * Restart the timer to expire within the amount of time left saved
+ * during Suspend.
+ * Calling Resume without a prior call to Suspend is an error.
+ */
+ void Resume (void);
+
+private:
+ template <typename FN>
+ void DoSetFunction (IntToType<0>, FN fn);
+ template <typename FN>
+ void DoSetFunction (IntToType<1>, FN fn);
+ template <typename FN>
+ void DoSetFunction (IntToType<2>, FN fn);
+ template <typename FN>
+ void DoSetFunction (IntToType<3>, FN fn);
+ template <typename FN>
+ void DoSetFunction (IntToType<4>, FN fn);
+ template <typename FN>
+ void DoSetFunction (IntToType<5>, FN fn);
+ template <typename FN>
+ void DoSetFunction (IntToType<6>, FN fn);
+
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<0>, MEM_PTR memPtr, OBJ_PTR objPtr);
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<1>, MEM_PTR memPtr, OBJ_PTR objPtr);
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<2>, MEM_PTR memPtr, OBJ_PTR objPtr);
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<3>, MEM_PTR memPtr, OBJ_PTR objPtr);
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<4>, MEM_PTR memPtr, OBJ_PTR objPtr);
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<5>, MEM_PTR memPtr, OBJ_PTR objPtr);
+ template <typename MEM_PTR, typename OBJ_PTR>
+ void DoSetFunction (IntToType<6>, MEM_PTR memPtr, OBJ_PTR objPtr);
+
+ enum {
+ TIMER_SUSPENDED = (1<<7)
+ };
+
+ int m_flags;
+ Time m_delay;
+ EventId m_event;
+ TimerImpl *m_impl;
+ Time m_delayLeft;
+};
+
+} // namespace ns3
+
+
+// The actual implementation.
+#include "simulator.h"
+#include "ns3/type-traits.h"
+
+namespace ns3 {
+
+
+template <typename T>
+struct TimerTraits
+{
+ typedef typename TypeTraits<typename TypeTraits<T>::ReferencedType>::NonConstType StoredType;
+ typedef const StoredType &ParameterType;
+};
+
+class TimerImpl
+{
+public:
+ virtual ~TimerImpl () {}
+ virtual EventId Schedule (const Time &delay) = 0;
+};
+
+
+template <typename T1>
+struct TimerImplOne : public TimerImpl
+{
+ virtual void SetArguments (T1 a1) = 0;
+};
+template <typename T1, typename T2>
+struct TimerImplTwo : public TimerImpl
+{
+ virtual void SetArguments (T1 a1,T2 a2) = 0;
+};
+template <typename T1, typename T2, typename T3>
+struct TimerImplThree : public TimerImpl
+{
+ virtual void SetArguments (T1 a1,T2 a2,T3 a3) = 0;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct TimerImplFour : public TimerImpl
+{
+ virtual void SetArguments (T1 a1,T2 a2,T3 a3, T4 a4) = 0;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct TimerImplFive : public TimerImpl
+{
+ virtual void SetArguments (T1 a1,T2 a2,T3 a3, T4 a4, T5 a5) = 0;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+struct TimerImplSix : public TimerImpl
+{
+ virtual void SetArguments (T1 a1,T2 a2,T3 a3, T4 a4, T5 a5, T6 a6) = 0;
+};
+
+
+template <typename FN>
+void
+Timer::SetFunction (FN fn)
+{
+ NS_ASSERT (TypeTraits<FN>::IsFunctionPointer);
+ DoSetFunction (IntToType<TypeTraits<FN>::FunctionPointerTraits::nArgs> (), fn);
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<0>, FN fn)
+{
+ struct FnTimerImplZero : public TimerImpl
+ {
+ FnTimerImplZero (FN fn)
+ : m_fn (fn) {}
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn);
+ }
+ FN m_fn;
+ } *function = new FnTimerImplZero (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<1>, FN fn)
+{
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+
+ struct FnTimerImplOne : public TimerImplOne<T1Parameter>
+ {
+ FnTimerImplOne (FN fn)
+ : m_fn (fn) {}
+ virtual void SetArguments (T1Parameter a1) {
+ m_a1 = a1;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn, m_a1);
+ }
+ FN m_fn;
+ T1Stored m_a1;
+ } *function = new FnTimerImplOne (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<2>, FN fn)
+{
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+
+ struct FnTimerImplTwo : public TimerImplTwo<T1Parameter,T2Parameter>
+ {
+ FnTimerImplTwo (FN fn)
+ : m_fn (fn) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2) {
+ m_a1 = a1;
+ m_a2 = a2;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn, m_a1, m_a2);
+ }
+ FN m_fn;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ } *function = new FnTimerImplTwo (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<3>, FN fn)
+{
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+
+ struct FnTimerImplThree : public TimerImplThree<T1Parameter,T2Parameter,T3Parameter>
+ {
+ FnTimerImplThree (FN fn)
+ : m_fn (fn) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3);
+ }
+ FN m_fn;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ } *function = new FnTimerImplThree (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<4>, FN fn)
+{
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg4Type T4;
+ typedef typename TimerTraits<T4>::ParameterType T4Parameter;
+ typedef typename TimerTraits<T4>::StoredType T4Stored;
+
+ struct FnTimerImplFour : public TimerImplFour<T1Parameter,T2Parameter,T3Parameter,T4Parameter>
+ {
+ FnTimerImplFour (FN fn)
+ : m_fn (fn) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ m_a4 = a4;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3, m_a4);
+ }
+ FN m_fn;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ T4Stored m_a4;
+ } *function = new FnTimerImplFour (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<5>, FN fn)
+{
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg4Type T4;
+ typedef typename TimerTraits<T4>::ParameterType T4Parameter;
+ typedef typename TimerTraits<T4>::StoredType T4Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg5Type T5;
+ typedef typename TimerTraits<T5>::ParameterType T5Parameter;
+ typedef typename TimerTraits<T5>::StoredType T5Stored;
+
+ struct FnTimerImplFive : public TimerImplFive<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter>
+ {
+ FnTimerImplFive (FN fn)
+ : m_fn (fn) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4, T5Parameter a5) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ m_a4 = a4;
+ m_a5 = a5;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3, m_a4, m_a5);
+ }
+ FN m_fn;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ T4Stored m_a4;
+ T5Stored m_a5;
+ } *function = new FnTimerImplFive (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename FN>
+void
+Timer::DoSetFunction (IntToType<6>, FN fn)
+{
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg4Type T4;
+ typedef typename TimerTraits<T4>::ParameterType T4Parameter;
+ typedef typename TimerTraits<T4>::StoredType T4Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg5Type T5;
+ typedef typename TimerTraits<T5>::ParameterType T5Parameter;
+ typedef typename TimerTraits<T5>::StoredType T5Stored;
+ typedef typename TypeTraits<FN>::FunctionPointerTraits::Arg6Type T6;
+ typedef typename TimerTraits<T6>::ParameterType T6Parameter;
+ typedef typename TimerTraits<T6>::StoredType T6Stored;
+
+ struct FnTimerImplSix : public TimerImplSix<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter,T6Parameter>
+ {
+ FnTimerImplSix (FN fn)
+ : m_fn (fn) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4, T5Parameter a5, T6Parameter a6) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ m_a4 = a4;
+ m_a5 = a5;
+ m_a6 = a6;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_fn, m_a1, m_a2, m_a3, m_a4, m_a5, m_a6);
+ }
+ FN m_fn;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ T4Stored m_a4;
+ T5Stored m_a5;
+ T6Stored m_a6;
+ } *function = new FnTimerImplSix (fn);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::SetFunction (MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ NS_ASSERT (TypeTraits<MEM_PTR>::IsPointerToMember);
+ DoSetFunction (IntToType<TypeTraits<MEM_PTR>::PointerToMemberTraits::nArgs> () , memPtr, objPtr);
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<0>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ struct MemFnTimerImplZero : public TimerImpl
+ {
+ MemFnTimerImplZero (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ } *function = new MemFnTimerImplZero (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<1>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+
+ struct MemFnTimerImplOne : public TimerImplOne<T1Parameter>
+ {
+ MemFnTimerImplOne (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual void SetArguments (T1Parameter a1) {
+ m_a1 = a1;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ T1Stored m_a1;
+ } *function = new MemFnTimerImplOne (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<2>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+
+ struct MemFnTimerImplTwo : public TimerImplTwo<T1Parameter,T2Parameter>
+ {
+ MemFnTimerImplTwo (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2) {
+ m_a1 = a1;
+ m_a2 = a2;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ } *function = new MemFnTimerImplTwo (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<3>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+
+ struct MemFnTimerImplThree : public TimerImplThree<T1Parameter,T2Parameter,T3Parameter>
+ {
+ MemFnTimerImplThree (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ } *function = new MemFnTimerImplThree (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<4>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg4Type T4;
+ typedef typename TimerTraits<T4>::ParameterType T4Parameter;
+ typedef typename TimerTraits<T4>::StoredType T4Stored;
+
+ struct MemFnTimerImplFour : public TimerImplFour<T1Parameter,T2Parameter,T3Parameter,T4Parameter>
+ {
+ MemFnTimerImplFour (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ m_a4 = a4;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ T4Stored m_a4;
+ } *function = new MemFnTimerImplFour (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<5>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg4Type T4;
+ typedef typename TimerTraits<T4>::ParameterType T4Parameter;
+ typedef typename TimerTraits<T4>::StoredType T4Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg5Type T5;
+ typedef typename TimerTraits<T5>::ParameterType T5Parameter;
+ typedef typename TimerTraits<T5>::StoredType T5Stored;
+
+ struct MemFnTimerImplFive : public TimerImplFive<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter>
+ {
+ MemFnTimerImplFive (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4,T5Parameter a5) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ m_a4 = a4;
+ m_a5 = a5;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4, m_a5);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ T4Stored m_a4;
+ T5Stored m_a5;
+ } *function = new MemFnTimerImplFive (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+template <typename MEM_PTR, typename OBJ_PTR>
+void
+Timer::DoSetFunction (IntToType<6>, MEM_PTR memPtr, OBJ_PTR objPtr)
+{
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg1Type T1;
+ typedef typename TimerTraits<T1>::ParameterType T1Parameter;
+ typedef typename TimerTraits<T1>::StoredType T1Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg2Type T2;
+ typedef typename TimerTraits<T2>::ParameterType T2Parameter;
+ typedef typename TimerTraits<T2>::StoredType T2Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg3Type T3;
+ typedef typename TimerTraits<T3>::ParameterType T3Parameter;
+ typedef typename TimerTraits<T3>::StoredType T3Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg4Type T4;
+ typedef typename TimerTraits<T4>::ParameterType T4Parameter;
+ typedef typename TimerTraits<T4>::StoredType T4Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg5Type T5;
+ typedef typename TimerTraits<T5>::ParameterType T5Parameter;
+ typedef typename TimerTraits<T5>::StoredType T5Stored;
+ typedef typename TypeTraits<MEM_PTR>::PointerToMemberTraits::Arg6Type T6;
+ typedef typename TimerTraits<T6>::ParameterType T6Parameter;
+ typedef typename TimerTraits<T6>::StoredType T6Stored;
+
+ struct MemFnTimerImplSix : public TimerImplSix<T1Parameter,T2Parameter,T3Parameter,T4Parameter,T5Parameter,T6Parameter>
+ {
+ MemFnTimerImplSix (MEM_PTR memPtr, OBJ_PTR objPtr)
+ : m_memPtr (memPtr), m_objPtr (objPtr) {}
+ virtual void SetArguments (T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4,T5Parameter a5,T6Parameter a6) {
+ m_a1 = a1;
+ m_a2 = a2;
+ m_a3 = a3;
+ m_a4 = a4;
+ m_a5 = a5;
+ m_a6 = a6;
+ }
+ virtual EventId Schedule (const Time &delay) {
+ return Simulator::Schedule (delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4, m_a5, m_a6);
+ }
+ MEM_PTR m_memPtr;
+ OBJ_PTR m_objPtr;
+ T1Stored m_a1;
+ T2Stored m_a2;
+ T3Stored m_a3;
+ T4Stored m_a4;
+ T5Stored m_a5;
+ T6Stored m_a6;
+ } *function = new MemFnTimerImplSix (memPtr, objPtr);
+ delete m_impl;
+ m_impl = function;
+}
+
+
+template <typename T1>
+void
+Timer::SetArguments (T1 a1)
+{
+ if (m_impl == 0)
+ {
+ NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
+ return;
+ }
+ typedef struct TimerImplOne<
+ typename TimerTraits<T1>::ParameterType
+ > TimerImplBase;
+ TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
+ if (impl == 0)
+ {
+ NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
+ return;
+ }
+ impl->SetArguments (a1);
+}
+
+template <typename T1, typename T2>
+void
+Timer::SetArguments (T1 a1, T2 a2)
+{
+ if (m_impl == 0)
+ {
+ NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
+ return;
+ }
+ typedef struct TimerImplTwo<
+ typename TimerTraits<T1>::ParameterType,
+ typename TimerTraits<T2>::ParameterType
+ > TimerImplBase;
+ TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
+ if (impl == 0)
+ {
+ NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
+ return;
+ }
+ impl->SetArguments (a1, a2);
+}
+
+template <typename T1, typename T2, typename T3>
+void
+Timer::SetArguments (T1 a1, T2 a2, T3 a3)
+{
+ if (m_impl == 0)
+ {
+ NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
+ return;
+ }
+ typedef struct TimerImplThree<
+ typename TimerTraits<T1>::ParameterType,
+ typename TimerTraits<T2>::ParameterType,
+ typename TimerTraits<T3>::ParameterType
+ > TimerImplBase;
+ TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
+ if (impl == 0)
+ {
+ NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
+ return;
+ }
+ impl->SetArguments (a1, a2, a3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void
+Timer::SetArguments (T1 a1, T2 a2, T3 a3, T4 a4)
+{
+ if (m_impl == 0)
+ {
+ NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
+ return;
+ }
+ typedef struct TimerImplFour<
+ typename TimerTraits<T1>::ParameterType,
+ typename TimerTraits<T2>::ParameterType,
+ typename TimerTraits<T3>::ParameterType,
+ typename TimerTraits<T4>::ParameterType
+ > TimerImplBase;
+ TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
+ if (impl == 0)
+ {
+ NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
+ return;
+ }
+ impl->SetArguments (a1, a2, a3, a4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void
+Timer::SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+{
+ if (m_impl == 0)
+ {
+ NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
+ return;
+ }
+ typedef struct TimerImplFive<
+ typename TimerTraits<T1>::ParameterType,
+ typename TimerTraits<T2>::ParameterType,
+ typename TimerTraits<T3>::ParameterType,
+ typename TimerTraits<T4>::ParameterType,
+ typename TimerTraits<T5>::ParameterType
+ > TimerImplBase;
+ TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
+ if (impl == 0)
+ {
+ NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
+ return;
+ }
+ impl->SetArguments (a1, a2, a3, a4, a5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+void
+Timer::SetArguments (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
+{
+ if (m_impl == 0)
+ {
+ NS_FATAL_ERROR ("You cannot set the arguments of a Timer before setting its function.");
+ return;
+ }
+ typedef struct TimerImplSix<
+ typename TimerTraits<T1>::ParameterType,
+ typename TimerTraits<T2>::ParameterType,
+ typename TimerTraits<T3>::ParameterType,
+ typename TimerTraits<T4>::ParameterType,
+ typename TimerTraits<T5>::ParameterType,
+ typename TimerTraits<T6>::ParameterType
+ > TimerImplBase;
+ TimerImplBase *impl = dynamic_cast<TimerImplBase *> (m_impl);
+ if (impl == 0)
+ {
+ NS_FATAL_ERROR ("You tried to set Timer arguments incompatible with its function.");
+ return;
+ }
+ impl->SetArguments (a1, a2, a3, a4, a5, a6);
+}
+
+
+
+} // namespace ns3
+
+#endif /* TIMER_H */
--- a/src/simulator/wscript Mon Oct 08 11:23:53 2007 +0100
+++ b/src/simulator/wscript Mon Oct 08 11:24:16 2007 +0100
@@ -60,6 +60,8 @@
'event-impl.cc',
'simulator.cc',
'time-default-value.cc',
+ 'timer.cc',
+ 'event-garbage-collector.cc',
]
headers = bld.create_obj('ns3header')
@@ -73,6 +75,7 @@
'scheduler-factory.h',
'simulation-singleton.h',
'time-default-value.h',
+ 'timer.h'
]
env = bld.env_of_name('default')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/mobility-generator.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/ns2-mobility-file-topology.h"
+#include "ns3/object.h"
+#include "ns3/simulator.h"
+#include "ns3/mobility-model-notifier.h"
+#include <iostream>
+
+using namespace ns3;
+
+static void
+CourseChange (Ptr<const MobilityModel> position)
+{
+ Position pos = position->Get ();
+ std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
+ << ", z=" << pos.z << std::endl;
+}
+
+int main (int argc, char *argv[])
+{
+ std::vector<Ptr<Object> > objects;
+ while (argc > 0)
+ {
+ if (strncmp (*argv, "--n=", strlen ("--n=")) == 0)
+ {
+ uint32_t n = atoi (*argv + strlen ("--n="));
+ for (uint32_t i = 0; i < n; i++)
+ {
+ Ptr<MobilityModelNotifier> notifier = Create<MobilityModelNotifier> ();
+ notifier->RegisterListener (MakeCallback (&CourseChange));
+ objects.push_back (notifier);
+ }
+ }
+ else if (strncmp (*argv, "--ns2-topology=",
+ strlen ("--ns2-topology=")) == 0)
+ {
+ const char *filename = *argv + strlen ("--ns2-topology=");
+ Ns2MobilityFileTopology topology (filename);
+ topology.Layout (objects.begin (), objects.end ());
+ }
+ argc--;
+ argv++;
+ }
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/mobility-visualizer-model.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include <vector>
+
+#include "ns3/ptr.h"
+#include "ns3/mobility-model.h"
+#include "ns3/mobility-model-notifier.h"
+#include "ns3/random-topology.h"
+#include "ns3/default-value.h"
+#include "ns3/command-line.h"
+#include "ns3/command-line.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/node.h"
+#include "ns3/node-list.h"
+#include "ns3/rectangle-default-value.h"
+
+#include "mobility-visualizer.h"
+
+using namespace ns3;
+
+static Time g_sampleInterval = Seconds (SAMPLE_INTERVAL);
+static uint32_t g_numNodes = 10;
+
+template <typename T>
+static const T* DefaultValueListGet (const std::string &name)
+{
+ for (DefaultValueList::Iterator iter = DefaultValueList::Begin ();
+ iter != DefaultValueList::End (); iter++)
+ {
+ const DefaultValueBase *value = *iter;
+ if (value->GetName () == name)
+ {
+ return dynamic_cast<const T*> (value);
+ }
+ }
+ return NULL;
+}
+
+
+
+static void
+Sample ()
+{
+
+ ViewUpdateData *data = new ViewUpdateData;
+ for (NodeList::Iterator nodeIter = NodeList::Begin (); nodeIter != NodeList::End (); nodeIter++)
+ {
+ Ptr<Node> node = *nodeIter;
+ Ptr<MobilityModel> mobility = node->QueryInterface<MobilityModel> (MobilityModel::iid);
+ Position pos = mobility->Get ();
+ Speed vel = mobility->GetSpeed ();
+
+ NodeUpdate update;
+ update.node = PeekPointer<Node> (node);
+ update.x = pos.x;
+ update.y = pos.y;
+ update.vx = vel.dx;
+ update.vy = vel.dy;
+ data->updateList.push_back (update);
+ }
+ data->time = Simulator::Now ().GetSeconds ();
+ view_update (data);
+ Simulator::Schedule (g_sampleInterval, Sample);
+}
+
+
+
+int model_init (int argc, char *argv[], double *x1, double *y1, double *x2, double *y2)
+{
+ DefaultValue::Bind ("RandomWalk2dMode", "Time");
+ DefaultValue::Bind ("RandomWalk2dTime", "5s");
+ DefaultValue::Bind ("RandomWalk2dSpeed", "Constant:20.0");
+ DefaultValue::Bind ("RandomDirection2dSpeed", "Uniform:10.0:20.0");
+ DefaultValue::Bind ("RandomWalk2dBounds", "0:400:0:300");
+ DefaultValue::Bind ("RandomDirection2dArea", "0:400:0:300");
+ DefaultValue::Bind ("RandomWaypointSpeed", "Uniform:10:30");
+
+// DefaultValue::Bind ("RandomDiscPositionX", "100");
+// DefaultValue::Bind ("RandomDiscPositionY", "50");
+// DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
+
+ DefaultValue::Bind ("RandomTopologyPositionType", "RandomRectanglePosition");
+ DefaultValue::Bind ("RandomTopologyMobilityType", "RandomWalk2dMobilityModel");
+
+// CommandLine::AddArgValue ("sample-interval","sample interval", g_sampleInterval);
+// CommandLine::AddArgValue ("num-nodes","number of nodes", g_numNodes);
+
+ CommandLine::Parse (argc, argv);
+
+ RandomTopology topology;
+
+ for (uint32_t i = 0; i < g_numNodes; i++)
+ {
+ Ptr<Node> node = Create<Node> ();
+ node->AddInterface (Create<MobilityModelNotifier> ());
+ }
+
+ topology.Layout (NodeList::Begin (), NodeList::End ());
+
+ Simulator::Schedule (g_sampleInterval, Sample);
+
+ ClassId mobType = DefaultValueListGet<ClassIdDefaultValue> ("RandomTopologyMobilityType")->GetValue ();
+ if (mobType.GetName () == "RandomWalk2dMobilityModel")
+ {
+ Rectangle bounds = DefaultValueListGet<RectangleDefaultValue> ("RandomWalk2dBounds")->GetValue ();
+ *x1 = bounds.xMin;
+ *y1 = bounds.yMin;
+ *x2 = bounds.xMax;
+ *y2 = bounds.yMax;
+ std::cout << "RECT " << bounds.xMin << " " << bounds.xMax << " "
+ << bounds.yMin << " " << bounds.yMax << std::endl;
+ }
+ else if (mobType.GetName () == "RandomDirection2dMobilityModel")
+ {
+ Rectangle bounds = DefaultValueListGet<RectangleDefaultValue> ("RandomDirection2dArea")->GetValue ();
+ *x1 = bounds.xMin;
+ *y1 = bounds.yMin;
+ *x2 = bounds.xMax;
+ *y2 = bounds.yMax;
+ std::cout << "RECT " << bounds.xMin << " " << bounds.xMax << " "
+ << bounds.yMin << " " << bounds.yMax << std::endl;
+ }
+ else if (mobType.GetName () == "RandomWaypointMobilityModel")
+ {
+ std::cerr << "bounds for RandomWaypointMobilityModel not implemented" << std::endl;
+ //ClassId posType = DefaultValueList::Get<ClassIdDefaultValue> ("RandomWaypointPosition")->GetValue ();
+ std::cout << "?" << std::endl; // too hard to represent an abstract/probabilistic model graphically
+ }
+ else
+ {
+ NS_FATAL_ERROR ("mobility type " << mobType.GetName () << " not supported");
+ }
+
+ std::cerr << g_sampleInterval << std::endl;
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/mobility-visualizer-view.cc Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,218 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include <map>
+
+#include <goocanvas.h>
+#include <glib/gthread.h>
+
+#include "mobility-visualizer.h"
+#include <map>
+#include "ns3/simulator.h"
+
+#define MAX_QUEUE_LENGTH 100
+#define MAX_EVENTS 20
+#define LOOKAHEAD_SECONDS 10
+
+GtkWidget *g_canvas;
+
+int model_init (int argc, char *argv[]);
+
+struct Node
+{
+ GooCanvasItem *m_item;
+ GooCanvasItem *m_vector;
+ void create ()
+ {
+ GooCanvasItem *root = goo_canvas_get_root_item (GOO_CANVAS (g_canvas));
+ m_item = goo_canvas_ellipse_new (root, 0, 0, 2.0, 2.0,
+ "line_width", 0.5,
+ "stroke_color", "black",
+ "fill_color", "red",
+ NULL);
+
+ m_vector = goo_canvas_polyline_new (root, FALSE, 0,
+ "line_width", 0.3,
+ "stroke_color", "black",
+ "end-arrow", TRUE,
+ "arrow-length", 10.0,
+ "arrow-width", 10.0,
+ NULL);
+
+ }
+
+
+ void update (double x, double y, double vx, double vy)
+ {
+ g_object_set (m_item, "center_x", x, "center_y", y, NULL);
+
+ if (vx == 0 && vy == 0)
+ {
+ GooCanvasPoints *points = goo_canvas_points_new (0);
+ g_object_set (m_vector, "points", points, NULL);
+ goo_canvas_points_unref (points);
+ }
+ else
+ {
+ GooCanvasPoints *points = goo_canvas_points_new (2);
+
+ points->coords[0] = x;
+ points->coords[1] = y;
+ points->coords[2] = x + vx;
+ points->coords[3] = y + vy;
+
+ g_object_set (m_vector, "points", points, NULL);
+ goo_canvas_points_unref (points);
+ }
+ }
+};
+
+std::map<void*, Node> g_nodes;
+
+GTimeVal initialTime = {-1, -1};
+gboolean firstTime = TRUE;
+double g_lookaheadTime = 0;
+GStaticMutex g_lookaheadTimeMux = G_STATIC_MUTEX_INIT;
+ViewUpdateData *g_nextData = NULL;
+
+
+GAsyncQueue *queue;
+
+#define TIME_SCALE 1
+
+double get_current_time ()
+{
+ GTimeVal currTime;
+ g_get_current_time (&currTime);
+ GTimeVal relativeTime;
+ relativeTime.tv_sec = currTime.tv_sec - initialTime.tv_sec + LOOKAHEAD_SECONDS;
+ relativeTime.tv_usec = currTime.tv_usec;
+ g_time_val_add (&relativeTime, -initialTime.tv_usec);
+ return (relativeTime.tv_sec + 1.0e-6*relativeTime.tv_usec)*TIME_SCALE;
+}
+
+// called from the simulation thread
+void view_update (ViewUpdateData *updateData)
+{
+ while ((g_static_mutex_lock (&g_lookaheadTimeMux), g_lookaheadTime) != 0 and updateData->time >= g_lookaheadTime)
+ {
+ g_static_mutex_unlock (&g_lookaheadTimeMux);
+ g_usleep ((gulong) 10e3);
+ }
+ g_static_mutex_unlock (&g_lookaheadTimeMux);
+ g_async_queue_push (queue, updateData);
+}
+
+void view_update_process (ViewUpdateData *updateData)
+{
+ for (std::vector<NodeUpdate>::const_iterator update
+ = updateData->updateList.begin ();
+ update != updateData->updateList.end ();
+ update++)
+ {
+ if (g_nodes.find (update->node) == g_nodes.end ())
+ {
+ g_nodes[update->node].create ();
+ }
+ g_nodes[update->node].update (update->x, update->y, update->vx, update->vy);
+ }
+ delete updateData;
+}
+
+gboolean view_update_consumer ()
+{
+ if (firstTime)
+ {
+ firstTime = FALSE;
+ g_get_current_time (&initialTime);
+ }
+
+ double now = get_current_time ();
+ g_static_mutex_lock (&g_lookaheadTimeMux);
+ g_lookaheadTime = now + LOOKAHEAD_SECONDS;
+ g_static_mutex_unlock (&g_lookaheadTimeMux);
+
+ if (!g_nextData)
+ g_nextData = (ViewUpdateData *) g_async_queue_try_pop (queue);
+
+ if (!g_nextData)
+ return TRUE;
+
+ if (g_nextData->time > now)
+ return TRUE;
+
+ do
+ {
+ view_update_process (g_nextData);
+ g_nextData = (ViewUpdateData *) g_async_queue_try_pop (queue);
+ }
+ while (g_nextData && g_nextData->time <= now);
+
+ return TRUE;
+}
+
+void zoom_changed (GtkAdjustment *adj)
+{
+ goo_canvas_set_scale (GOO_CANVAS (g_canvas), gtk_adjustment_get_value (adj));
+}
+
+int main (int argc, char *argv[])
+{
+ g_thread_init (NULL);
+ gtk_init (&argc, &argv);
+ double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+
+ model_init (argc, argv, &x1, &y1, &x2, &y2);
+
+ GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
+ gtk_widget_show (window);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ GtkWidget *scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
+ gtk_widget_show (scrolled_win);
+
+ GtkWidget *vbox = gtk_vbox_new (FALSE, 4);
+ gtk_widget_show (vbox);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, 1, 1, 4);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 4);
+ gtk_widget_show (hbox);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, false, false, 4);
+
+ GtkObject *zoom = gtk_adjustment_new (3.0, 0.1, 10.0, 0.2, 1.0, 1.0);
+ gtk_box_pack_start(GTK_BOX (hbox),
+ GTK_WIDGET (g_object_new (GTK_TYPE_SPIN_BUTTON, "adjustment", zoom,
+ "visible", true, "digits", 2, NULL)),
+ false, false, 4);
+
+ g_canvas = goo_canvas_new ();
+ gtk_widget_set_size_request (GTK_WIDGET (g_canvas), 600, 450);
+ goo_canvas_set_bounds (GOO_CANVAS (g_canvas), -500, -500, 500, 500);
+ g_signal_connect (zoom, "value-changed", G_CALLBACK (zoom_changed), NULL);
+ gtk_adjustment_value_changed (GTK_ADJUSTMENT (zoom));
+ gtk_widget_show (g_canvas);
+ gtk_container_add (GTK_CONTAINER (scrolled_win), g_canvas);
+
+ goo_canvas_scroll_to (GOO_CANVAS (g_canvas), 0, 0);
+
+ // create the bounds rectangle
+ if (x1 != x2)
+ {
+ GooCanvasItem *item =
+ goo_canvas_rect_new (goo_canvas_get_root_item (GOO_CANVAS (g_canvas)),
+ x1, y1, x2-x1, y2-y1, NULL);
+ g_object_set (item, "line-width", 1.0, "stroke-color", "grey", NULL);
+ }
+
+ queue = g_async_queue_new ();
+
+ g_timeout_add ((guint) (SAMPLE_INTERVAL*1000), (GSourceFunc) view_update_consumer, NULL);
+
+ g_thread_create (GThreadFunc (ns3::Simulator::Run), NULL, FALSE, NULL);
+
+ gtk_main ();
+
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/mobility-visualizer.h Mon Oct 08 11:24:16 2007 +0100
@@ -0,0 +1,23 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+#include <vector>
+
+int model_init (int argc, char *argv[], double *x1, double *y1, double *x2, double *y2);
+
+struct NodeUpdate
+{
+ void *node;
+ double x;
+ double y;
+ double vx;
+ double vy;
+};
+
+struct ViewUpdateData
+{
+ std::vector<NodeUpdate> updateList;
+ double time;
+};
+
+void view_update (ViewUpdateData *updateData);
+
+#define SAMPLE_INTERVAL (1.0/30)
--- a/utils/wscript Mon Oct 08 11:23:53 2007 +0100
+++ b/utils/wscript Mon Oct 08 11:24:16 2007 +0100
@@ -1,5 +1,13 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import os.path
+def configure(conf):
+ check = conf.create_pkgconfig_configurator()
+ check.name = 'goocanvas gthread-2.0'
+ check.uselib = 'MOBILITY_VISUALIZER'
+ check.mandatory = False
+ conf.env['ENABLE_MOBILITY_VISUALIZER'] = check.run()
+
def build(bld):
env = bld.env_of_name('default')
@@ -23,3 +31,12 @@
obj = bld.create_ns3_program('print-trace-sources',
['internet-node', 'csma-cd', 'point-to-point'])
obj.source = 'print-trace-sources.cc'
+
+ if env['ENABLE_MOBILITY_VISUALIZER']:
+ obj = bld.create_ns3_program('mobility-visualizer',
+ ['internet-node', 'mobility'])
+ obj.source = ['mobility-visualizer-model.cc', 'mobility-visualizer-view.cc']
+ obj.uselib = 'MOBILITY_VISUALIZER'
+ if os.path.basename(obj.env['CXX']).startswith("g++"):
+ obj.env.append_value('CXXFLAGS', '-fno-strict-aliasing')
+
--- a/wscript Mon Oct 08 11:23:53 2007 +0100
+++ b/wscript Mon Oct 08 11:24:16 2007 +0100
@@ -143,6 +143,7 @@
variant_env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
conf.sub_config('src')
+ conf.sub_config('utils')
def create_ns3_program(bld, name, dependencies=('simulator',)):