merge with HEAD

This commit is contained in:
Mathieu Lacage
2007-05-04 14:03:12 +02:00
22 changed files with 1774 additions and 49 deletions

View File

@@ -27,6 +27,9 @@ core.add_sources([
'rng-stream.cc',
'ns-unknown.cc',
'iid-manager.cc',
'default-value.cc',
'command-line.cc',
'type-name.cc',
])
env = Environment()
if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
@@ -52,6 +55,9 @@ core.add_inst_headers([
'rng-stream.h',
'ns-unknown.h',
'iid-manager.h',
'default-value.h',
'command-line.h',
'type-name.h',
])
def config_core (env, config):
@@ -377,6 +383,18 @@ ns3.add(sample_simple)
sample_simple.add_deps(['core', 'simulator', 'node'])
sample_simple.add_source('main-simple.cc')
sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples')
sample_sp2p.set_executable()
#n3.add(sample_sp2p)
sample_sp2p.add_deps(['core', 'simulator', 'node', 'p2p'])
sample_sp2p.add_source('main-simple-p2p.cc')
sample_default_value = build.Ns3Module('sample-default-value', 'samples')
sample_default_value.set_executable()
ns3.add(sample_default_value)
sample_default_value.add_deps(['core', 'simulator', 'node', 'p2p'])
sample_default_value.add_source('main-default-value.cc')
# examples
example_simple_p2p = build.Ns3Module('simple-p2p', 'examples')
example_simple_p2p.set_executable()

View File

@@ -43,6 +43,8 @@
#include <cassert>
#include "ns3/debug.h"
#include "ns3/command-line.h"
#include "ns3/default-value.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
@@ -70,6 +72,7 @@ using namespace ns3;
int main (int argc, char *argv[])
{
CommandLine::Parse (argc, argv);
#if 0
DebugComponentEnable("Object");
DebugComponentEnable("Queue");
@@ -84,7 +87,7 @@ int main (int argc, char *argv[])
// be a DropTail queue, with a limit of 30 packets.
// Specify DropTail for default queue type (note. this is actually
// the default, but included here as an example).
Queue::Default(DropTailQueue());
Bind ("queue", "DropTail"); //Queue::Default(DropTailQueue());
// Specify limit of 30 in units of packets (not implemented).
// Queue::Default().SetLimitPackets(30);

View File

@@ -0,0 +1,85 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include <string>
#include "ns3/default-value.h"
#include "ns3/command-line.h"
#include "ns3/debug.h"
using namespace ns3;
//
// This sample file demonstrates how to take some simple member
// variables and hook them into the default variable system
// Typically, you will establish a static variable to maintain the current
// value of the default parameter. Then as other code require the values of
// the defaults, they query them with GetValue() to get the present value.
static BooleanDefaultValue defaultTestBool1 ("testBool1", "helpBool", true);
static IntegerDefaultValue<int> defaultTestInt1 ("testInt1", "helpInt1", 33);
static IntegerDefaultValue<uint32_t> defaultTestInt2 ("testInt2", "helpInt2", 47);
//
// This test class demonstrates the declaration of variables that
// may be overridden by the default-value system
//
// You will see in the core ns-3 modules that many member variables
// can be overridden in this manner
//
class TestClass {
public:
TestClass();
virtual ~TestClass () {}
bool m_testBool1;
int m_testInt1;
uint32_t m_testInt2;
};
//
// In the constructor, you can assign default values in the initializer
// list such as below; note that the instance of the created TestClass
// will have the values as dictated by the current value of the default.
// This means that the behavior of this class can be changed on the fly with
// calls to bind.
//
TestClass::TestClass () :
m_testBool1(defaultTestBool1.GetValue()),
m_testInt1(defaultTestInt1.GetValue()),
m_testInt2(defaultTestInt2.GetValue())
{
}
using std::cout;
int main (int argc, char* argv[])
{
//The following allows the default values established so far to be hooked
//into the command line argument processing unit. Essentially, the command
//line processor is aware of the DefaultValues that have been registered, and
//will accept command line overrides of these. The call automatically
//provides a --help option in addition to allowing overrides of defaults.
uint32_t loops = 0;
CommandLine::AddArgValue("loops","a test of the command line",loops);
CommandLine::Parse(argc,argv);
//utilize the loops variable to show that it can be read from the command line
if(loops>0)
{
cout<<"You requested "<<loops<<" iterations of a loop";
for(uint32_t i=0;i<loops;++i)
cout<<"iteration "<<i;
}
// Before objects are instantiated in your simulation script, you have
// the opportunity to overwrite any default value in the system.
// The Bind () method allows you to specify the name (string) of the
// global variable and value (string) to overwrite the default.
// Here, the default value of 33 for testInt1 is overwritten with 57
//
Bind("testInt1", "57");
TestClass* testclass = new TestClass ();
NS_DEBUG_UNCOND("TestBool1 default value (" << testclass->m_testBool1 << ")");
NS_DEBUG_UNCOND("TestInt1 default value (" << testclass->m_testInt1 << ")");
NS_DEBUG_UNCOND("TestInt2 default value (" << testclass->m_testInt2 << ")");
delete testclass;
return 0;
}

131
src/core/command-line.cc Normal file
View File

@@ -0,0 +1,131 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "command-line.h"
#include <unistd.h>
namespace ns3 {
CommandDefaultValue CommandLine::g_help ("help",
"Print Help text for all commands",
MakeCallback (&CommandLine::PrintHelp));
void
CommandLine::AddArgCommand (const std::string &name,
const std::string &help,
Callback<void> cb)
{
DefaultValueBase *base =
new CommandDefaultValue (name, help, cb);
GetUserList ()->push_back (base);
}
CommandLine::List *
CommandLine::GetUserList (void)
{
static List list;
return &list;
}
void
CommandLine::PrintHelp (void)
{
for (List::iterator i = GetUserList ()->begin ();
i != GetUserList ()->end (); i++)
{
DefaultValueBase *item = *i;
if (item->GetType () == "" &&
item->GetDefaultValue () == "")
{
std::cout << "--" << item->GetName () << "\t" << item->GetHelp () << std::endl;
}
else
{
std::cout << "--" << item->GetName () << "=[" << item->GetType () << ":"
<< item->GetDefaultValue () << "]\t" << item->GetHelp () << std::endl;
}
}
for (List::iterator i = DefaultValueList::Begin ();
i != DefaultValueList::End (); i++)
{
DefaultValueBase *item = *i;
if (item->GetType () == "" &&
item->GetDefaultValue () == "")
{
std::cout << "--" << item->GetName () << "\t" << item->GetHelp () << std::endl;
}
else
{
std::cout << "--" << item->GetName () << "=[" << item->GetType () << ":"
<< item->GetDefaultValue () << "]\t" << item->GetHelp () << std::endl;
}
}
// XXX on win32, do the right thing here.
exit (0);
}
void
CommandLine::Parse (int argc, char *argv[])
{
argc--;
argv++;
while (argc > 0)
{
// remove "--" or "-" heading.
std::string param = *argv;
std::string::size_type cur = param.find ("--");
if (cur == std::string::npos)
{
cur = param.find ("-");
if (cur == std::string::npos)
{
// invalid argument. ignore it.
continue;
}
}
if (cur != 0)
{
// invalid argument. ignore it.
continue;
}
param = std::string (param, 2, param.size ());
cur = param.find ("=");
std::string name, value;
if (cur == std::string::npos)
{
name = param;
value = "";
}
else
{
name = std::string (param, 0, cur);
value = std::string (param, cur + 1, std::string::npos);
}
// try to find this argument in the user args.
for (List::iterator i = GetUserList ()->begin ();
i != GetUserList ()->end (); i++)
{
DefaultValueBase *item = *i;
if (item->GetName () == name)
{
item->ParseValue (value);
continue;
}
}
// try to find this argument in the default args.
for (List::iterator i = DefaultValueList::Begin ();
i != DefaultValueList::End (); i++)
{
DefaultValueBase *item = *i;
if (item->GetName () == name)
{
item->ParseValue (value);
continue;
}
}
argc--;
argv++;
}
}
}//namespace ns3

93
src/core/command-line.h Normal file
View File

@@ -0,0 +1,93 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef COMMAND_LINE_H
#define COMMAND_LINE_H
#include <list>
#include <string>
#include "default-value.h"
namespace ns3 {
class CommandLine
{
public:
template <typename T>
static void AddArgValue (const std::string &name,
const std::string &help,
T &value);
static void AddArgCommand (const std::string &name,
const std::string &help,
Callback<void> cb);
static void Parse (int argc, char *argv[]);
private:
template <typename T>
class UserDefaultValue : public DefaultValueBase
{
public:
UserDefaultValue (const std::string &name,
const std::string &help,
T &value);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
T *m_valuePtr;
};
static void PrintHelp (void);
typedef std::list<DefaultValueBase *> List;
static List *GetUserList (void);
static CommandDefaultValue g_help;
};
}//namespace ns3
namespace ns3 {
template <typename T>
void
CommandLine::AddArgValue (const std::string &name,
const std::string &help,
T &value)
{
DefaultValueBase *base =
new UserDefaultValue<T> (name, help, value);
GetUserList ()->push_back (base);
}
template <typename T>
CommandLine::UserDefaultValue<T>::UserDefaultValue (const std::string &name,
const std::string &help,
T &value)
: DefaultValueBase (name, help),
m_valuePtr (&value)
{
// we do not register in the DefaultValueList class on purpose.
}
template <typename T>
bool
CommandLine::UserDefaultValue<T>::DoParseValue (const std::string &value)
{
std::istringstream iss;
iss.str (value);
T v;
iss >> v;
*m_valuePtr = v;
return !iss.bad () && !iss.fail ();
}
template <typename T>
std::string
CommandLine::UserDefaultValue<T>::DoGetType (void) const
{
return "";
}
template <typename T>
std::string
CommandLine::UserDefaultValue<T>::DoGetDefaultValue (void) const
{
return "";
}
}//namespace ns3
#endif /* COMMAND_LINE_H */

447
src/core/default-value.cc Normal file
View File

@@ -0,0 +1,447 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "default-value.h"
#include "fatal-error.h"
namespace ns3 {
DefaultValueBase::DefaultValueBase (const std::string &name,
const std::string &help)
: m_name (name),
m_help (help)
{}
DefaultValueBase::~DefaultValueBase ()
{}
std::string
DefaultValueBase::GetName (void) const
{
return m_name;
}
std::string
DefaultValueBase::GetHelp (void) const
{
return m_help;
}
bool
DefaultValueBase::ParseValue (const std::string &value)
{
return DoParseValue (value);
}
std::string
DefaultValueBase::GetType (void) const
{
return DoGetType ();
}
std::string
DefaultValueBase::GetDefaultValue (void) const
{
return DoGetDefaultValue ();
}
DefaultValueList::Iterator
DefaultValueList::Begin (void)
{
return GetList ()->begin ();
}
DefaultValueList::Iterator
DefaultValueList::End (void)
{
return GetList ()->end ();
}
void
DefaultValueList::Remove (const std::string &name)
{
DefaultValueList::List *list = GetList ();
for (List::iterator i = list->begin (); i != list->end (); /* nothing */)
{
if ((*i)->GetName () == name)
{
i = list->erase (i);
}
else
{
i++;
}
}
}
void
DefaultValueList::Add (DefaultValueBase *defaultValue)
{
GetList ()->push_back (defaultValue);
}
DefaultValueList::List *
DefaultValueList::GetList (void)
{
static List list;
return &list;
}
enum BindStatus {
OK,
INVALID_VALUE,
NOT_FOUND
};
static
enum BindStatus
BindSafe (std::string name, std::string value)
{
for (DefaultValueList::Iterator i = DefaultValueList::Begin ();
i != DefaultValueList::End (); i++)
{
DefaultValueBase *cur = *i;
if (cur->GetName () == name)
{
if (!cur->ParseValue (value))
{
return INVALID_VALUE;
}
return OK;
}
}
return NOT_FOUND;
}
void
Bind (std::string name, std::string value)
{
switch (BindSafe (name, value)) {
case INVALID_VALUE:
NS_FATAL_ERROR ("Invalid value: "<<name<<"="<<value);
break;
case NOT_FOUND:
NS_FATAL_ERROR ("No registered DefaultValue=\"" << name << "\"");
break;
case OK:
break;
}
}
BooleanDefaultValue::BooleanDefaultValue (std::string name,
std::string help,
bool defaultValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_value (defaultValue)
{
DefaultValueList::Add (this);
}
bool
BooleanDefaultValue::GetValue (void) const
{
return m_value;
}
bool
BooleanDefaultValue::DoParseValue (const std::string &value)
{
if (value.compare ("0") == 0 ||
value.compare ("f") == 0 ||
value.compare ("false") == 0 ||
value.compare ("FALSE") == 0)
{
m_value = false;
return true;
}
else if (value.compare ("1") == 0 ||
value.compare ("t") == 0 ||
value.compare ("true") == 0 ||
value.compare ("TRUE") == 0)
{
m_value = true;
return true;
}
else
{
return false;
}
}
std::string
BooleanDefaultValue::DoGetType (void) const
{
return "bool";
}
std::string
BooleanDefaultValue::DoGetDefaultValue (void) const
{
return m_defaultValue?"true":"false";
}
StringEnumDefaultValue::StringEnumDefaultValue (const std::string &name,
const std::string &help)
: DefaultValueBase (name, help),
m_oneDefault (false)
{
DefaultValueList::Add (this);
}
void
StringEnumDefaultValue::AddDefaultValue (const std::string &value)
{
if (m_oneDefault)
{
NS_FATAL_ERROR ("More than one default value registered: " << value);
}
m_oneDefault = true;
for (std::list<std::string>::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == *i)
{
NS_FATAL_ERROR ("Value already exists: " << value);
}
}
m_possibleValues.push_back (value);
m_value = value;
m_defaultValue = value;
}
void
StringEnumDefaultValue::AddPossibleValue (const std::string &value)
{
for (std::list<std::string>::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == *i)
{
NS_FATAL_ERROR ("Value already exists: " << value);
}
}
m_possibleValues.push_back (value);
}
std::string
StringEnumDefaultValue::GetValue (void) const
{
return m_value;
}
bool
StringEnumDefaultValue::DoParseValue (const std::string &value)
{
for (std::list<std::string>::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == *i)
{
m_value = value;
return true;
}
}
return false;
}
std::string
StringEnumDefaultValue::DoGetType (void) const
{
std::string retval;
retval += "(";
for (std::list<std::string>::const_iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (i != m_possibleValues.begin ())
{
retval += "|";
}
retval += *i;
}
retval += ")";
return retval;
}
std::string
StringEnumDefaultValue::DoGetDefaultValue (void) const
{
return m_defaultValue;
}
CommandDefaultValue::CommandDefaultValue (const std::string &name,
const std::string &help,
Callback<void> cb)
: DefaultValueBase (name, help),
m_cb (cb)
{
DefaultValueList::Add (this);
}
bool
CommandDefaultValue::DoParseValue (const std::string &value)
{
m_cb ();
return true;
}
std::string
CommandDefaultValue::DoGetType (void) const
{
return "";
}
std::string
CommandDefaultValue::DoGetDefaultValue (void) const
{
return "";
}
}//namespace ns3
#ifdef RUN_SELF_TESTS
#include "test.h"
namespace ns3 {
enum MyEnum {
MY_ENUM_A,
MY_ENUM_B,
MY_ENUM_C,
MY_ENUM_D,
};
class DefaultValueTest : public Test
{
public:
DefaultValueTest ();
virtual bool RunTests (void);
};
DefaultValueTest::DefaultValueTest ()
: Test ("DefaultValue")
{}
bool
DefaultValueTest::RunTests (void)
{
bool ok = true;
BooleanDefaultValue a ("bool-a", "help a", true);
if (!a.GetValue ())
{
ok = false;
}
Bind ("bool-a", "false");
if (a.GetValue ())
{
ok = false;
}
BooleanDefaultValue b ("bool-b", "help b", false);
Bind ("bool-b", "true");
if (!b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "0");
if (b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "1");
if (!b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "f");
if (b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "t");
if (!b.GetValue ())
{
ok = false;
}
Bind ("bool-b", "false");
if (b.GetValue ())
{
ok = false;
}
if (BindSafe ("bool-b", "tr") != INVALID_VALUE)
{
ok = false;
}
IntegerDefaultValue<int> i ("test-i", "help-i", -1);
if (i.GetValue () != -1)
{
ok = false;
}
Bind ("test-i", "-2");
if (i.GetValue () != -2)
{
ok = false;
}
Bind ("test-i", "+2");
if (i.GetValue () != 2)
{
ok = false;
}
if (i.GetType () != "int32_t(-2147483648:2147483647)")
{
ok = false;
}
IntegerDefaultValue<uint32_t> ui32 ("test-ui32", "help-ui32", 10);
if (ui32.GetType () != "uint32_t(0:4294967295)")
{
ok = false;
}
IntegerDefaultValue<char> c ("test-c", "help-c", 10);
if (c.GetValue () != 10)
{
ok = false;
}
Bind ("test-c", "257");
EnumDefaultValue<enum MyEnum> e ("test-e", "help-e",
MY_ENUM_C, "C",
MY_ENUM_A, "A",
MY_ENUM_B, "B",
0, (void*)0);
if (e.GetValue () != MY_ENUM_C)
{
ok = false;
}
Bind ("test-e", "B");
if (e.GetValue () != MY_ENUM_B)
{
ok = false;
}
if (BindSafe ("test-e", "D") != INVALID_VALUE)
{
ok = false;
}
class MyEnumSubclass : public EnumDefaultValue<enum MyEnum>
{
public:
MyEnumSubclass ()
: EnumDefaultValue<enum MyEnum> ("test-e1", "help-e1",
MY_ENUM_B, "B",
MY_ENUM_A, "A",
0, (void*)0)
{
AddPossibleValue (MY_ENUM_C, "C");
AddPossibleValue (MY_ENUM_D, "D");
}
} e1 ;
if (e1.GetValue () != MY_ENUM_B)
{
ok = false;
}
Bind ("test-e1", "D");
if (e1.GetValue () != MY_ENUM_D)
{
ok = false;
}
DefaultValueList::Remove ("test-e1");
DefaultValueList::Remove ("test-e");
DefaultValueList::Remove ("bool-b");
DefaultValueList::Remove ("bool-a");
DefaultValueList::Remove ("test-i");
DefaultValueList::Remove ("test-c");
DefaultValueList::Remove ("test-ui32");
return ok;
}
static DefaultValueTest g_default_value_tests;
}//namespace ns3
#endif /* RUN_SELF_TESTS */

423
src/core/default-value.h Normal file
View File

@@ -0,0 +1,423 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef DEFAULT_VALUE_H
#define DEFAULT_VALUE_H
#include <string>
#include <list>
#include "callback.h"
namespace ns3 {
class DefaultValueBase
{
public:
virtual ~DefaultValueBase ();
std::string GetName (void) const;
std::string GetHelp (void) const;
// parse a matching parameter
// return true in case of success, false otherwise.
bool ParseValue (const std::string &value);
std::string GetType (void) const;
std::string GetDefaultValue (void) const;
protected:
DefaultValueBase (const std::string &name,
const std::string &help);
private:
virtual bool DoParseValue (const std::string &value) = 0;
virtual std::string DoGetType (void) const = 0;
virtual std::string DoGetDefaultValue (void) const = 0;
std::string m_name;
std::string m_help;
};
class DefaultValueList
{
public:
typedef std::list<DefaultValueBase *>::iterator Iterator;
static Iterator Begin (void);
static Iterator End (void);
static void Remove (const std::string &name);
static void Add (DefaultValueBase *defaultValue);
private:
typedef std::list<DefaultValueBase *> List;
static List *GetList (void);
};
/**
* \param name name of variable to bind
* \param value value to bind to the specified variable
*
* If the variable name does not match any existing
* variable or if the value is not compatible with
* the variable type, this function will abort
* at runtime and print an error message detailing
* which variable or value triggered the problem.
*/
void Bind (std::string name, std::string value);
/**
* \brief A Boolean variable for ns3::Bind
*
* Every instance of this type is automatically
* registered in the variable pool which is used
* by ns3::Bind.
*/
class BooleanDefaultValue : public DefaultValueBase
{
public:
/**
* \param name name of variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value to assign
* to this variable.
*
* Unless the user invokes ns3::Bind with the right arguments,
* the GetValue method will return the default value. Otherwise,
* it will return the user-specified value.
*/
BooleanDefaultValue (std::string name,
std::string help,
bool defaultValue);
/**
* \returns the default value for this variable or a
* user-provided overriden variable.
*/
bool GetValue (void) const;
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
bool m_defaultValue;
bool m_value;
};
/**
* \brief An Integer variable for ns3::Bind
*
* Every instance of this type is automatically
* registered in the variable pool which is used
* by ns3::Bind.
*/
template <typename T>
class IntegerDefaultValue : public DefaultValueBase
{
public:
/**
* \param name the name of the variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned
* to this variable
*
* By default, the set of allowed values is the entire range
* of values which can be stored and retrieved from the underlying
* type.
*/
IntegerDefaultValue (std::string name,
std::string help,
T defaultValue);
/**
* \param name the name of the variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned to this
* variable
* \param minValue the minimum value which can be set
* in this variable
* \param maxValue the maximum value which can be set in this
* variable.
*/
IntegerDefaultValue (std::string name,
std::string help,
T defaultValue,
T minValue,
T maxValue);
T GetValue (void) const;
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
T m_defaultValue;
T m_minValue;
T m_maxValue;
T m_value;
};
class StringEnumDefaultValue : public DefaultValueBase
{
public:
StringEnumDefaultValue (const std::string &name,
const std::string &help);
void AddDefaultValue (const std::string &value);
void AddPossibleValue (const std::string &value);
std::string GetValue (void) const;
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
bool m_oneDefault;
std::list<std::string> m_possibleValues;
std::string m_defaultValue;
std::string m_value;
};
/**
* \brief An enum variable for ns3::Bind
*
* Every instance of this type is automatically
* registered in the variable pool which is used
* by ns3::Bind.
*/
template <typename T>
class EnumDefaultValue : public DefaultValueBase
{
public:
/**
* \param name the name of this variable
* \param help help text which explains the purpose
* and the semantics of this variable
* \param defaultValue the default value assigned to this
* variable unless it is overriden with ns3::Bind
* \param defaultValueString the string which represents
* the default value which should be used by ns3::Bind
*
* This method takes a variable number of arguments. The list of
* arguments is terminated by the pair of values 0 and (void *)0.
* Each pair of extra argument is assumed to be of the form
* (enum value, string representing enum value). If ns3::Bind
* is invoked on this variable, it will check that the user-provided
* values are within the set of values specified in this constructor.
*
* Typical useage of this method will look like this:
* \code
* enum MyEnum {
* MY_ENUM_A,
* MY_ENUM_B,
* MY_ENUM_C,
* };
* // set default value to be "B".
* static EnumDefaultValue<enum MyEnum>
* g_myDefaultValue ("my", "my help",
* MY_ENUM_B, "B",
* MY_ENUM_A, "A",
* MY_ENUM_C, "C",);
* 0, (void*)0);
* \endcode
* Note that to ensure portability to 64 bit systems, make sure that
* the last element in the variable list of arguments is (void *)0.
*/
EnumDefaultValue (const std::string &name, const std::string &help,
T defaultValue, const char *defaultValueString,
...);
void AddPossibleValue (T value, const std::string &valueString);
/**
* \returns the default value or any other value specified by the
* user with ns3::Bind
*/
T GetValue (void);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
typedef std::list<std::pair<T,std::string> > PossibleValues;
T m_defaultValue;
PossibleValues m_possibleValues;
T m_value;
};
class CommandDefaultValue : public DefaultValueBase
{
public:
CommandDefaultValue (const std::string &name,
const std::string &help,
Callback<void> cb);
private:
virtual bool DoParseValue (const std::string &value);
virtual std::string DoGetType (void) const;
virtual std::string DoGetDefaultValue (void) const;
Callback<void> m_cb;
};
}//namespace ns3
#include "type-name.h"
#include "assert.h"
#include <sstream>
#include <stdarg.h>
#include <limits>
namespace ns3 {
/**************************************************************
**************************************************************/
template <typename T>
IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
std::string help,
T defaultValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_minValue (std::numeric_limits<T>::min ()),
m_maxValue (std::numeric_limits<T>::max ()),
m_value (defaultValue)
{
DefaultValueList::Add (this);
}
template <typename T>
IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
std::string help,
T defaultValue,
T minValue,
T maxValue)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_minValue (minValue),
m_maxValue (maxValue),
m_value (defaultValue)
{
DefaultValueList::Add (this);
NS_ASSERT (m_defaultValue <= m_maxValue &&
m_defaultValue >= m_minValue);
}
template <typename T>
T
IntegerDefaultValue<T>::GetValue (void) const
{
return m_value;
}
template <typename T>
bool
IntegerDefaultValue<T>::DoParseValue (const std::string &value)
{
std::istringstream iss;
iss.str (value);
iss >> m_value;
if (m_value > m_maxValue ||
m_value < m_minValue)
{
return false;
}
return !iss.bad () && !iss.fail ();
}
template <typename T>
std::string
IntegerDefaultValue<T>::DoGetType (void) const
{
std::ostringstream oss;
oss << TypeNameGet<T> () << "("
<< m_minValue << ":"
<< m_maxValue << ")";
return oss.str ();
}
template <typename T>
std::string
IntegerDefaultValue<T>::DoGetDefaultValue (void) const
{
std::ostringstream oss;
oss << m_defaultValue;
return oss.str ();
}
/**************************************************************
**************************************************************/
template <typename T>
EnumDefaultValue<T>::EnumDefaultValue (const std::string &name, const std::string &help,
T defaultValue, const char *defaultValueString,
...)
: DefaultValueBase (name, help),
m_defaultValue (defaultValue),
m_value (defaultValue)
{
AddPossibleValue (defaultValue, defaultValueString);
va_list list;
va_start (list, defaultValueString);
while (true)
{
T v = (T) va_arg (list, int);
const char *str = va_arg (list, const char *);
if (v == 0 && str == 0)
{
break;
}
AddPossibleValue (v, str);
}
DefaultValueList::Add (this);
}
template <typename T>
void
EnumDefaultValue<T>::AddPossibleValue (T value, const std::string &valueString)
{
m_possibleValues.push_back (std::make_pair (value, valueString));
}
template <typename T>
T
EnumDefaultValue<T>::GetValue (void)
{
return m_value;
}
template <typename T>
bool
EnumDefaultValue<T>::DoParseValue (const std::string &value)
{
for (typename PossibleValues::iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (value == i->second)
{
m_value = i->first;
return true;
}
}
return false;
}
template <typename T>
std::string
EnumDefaultValue<T>::DoGetType (void) const
{
std::string retval;
retval += "(";
for (typename PossibleValues::const_iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (i != m_possibleValues.begin ())
{
retval += "|";
}
retval += i->second;
}
retval += ")";
return retval;
}
template <typename T>
std::string
EnumDefaultValue<T>::DoGetDefaultValue (void) const
{
for (typename PossibleValues::const_iterator i = m_possibleValues.begin ();
i != m_possibleValues.end (); i++)
{
if (i->first == m_defaultValue)
{
return i->second;
}
}
// cannot happen theoretically.
NS_ASSERT (false);
return ""; // quiet compiler
}
}//namespace ns3
#endif /* DEFAULT_VALUE_H */

View File

@@ -44,16 +44,33 @@ namespace ns3{
uint32_t RandomVariable::runNumber = 0;
bool RandomVariable::initialized = false; // True if RngStream seed set
bool RandomVariable::useDevRandom = false; // True if use /dev/random desired
bool RandomVariable::useDevRandom = false; // True if use /dev/random
bool RandomVariable::globalSeedSet = false; // True if GlobalSeed called
int RandomVariable::devRandom = -1;
uint32_t RandomVariable::globalSeed[6];
uint32_t RandomVariable::globalSeed[6];
unsigned long RandomVariable::heuristic_sequence;
RngStream* RandomVariable::m_static_generator = 0;
//the static object random_variable_initializer initializes the static members
//of RandomVariable
static class RandomVariableInitializer
{
public:
RandomVariableInitializer()
{
RandomVariable::Initialize(); // sets the static package seed
RandomVariable::m_static_generator = new RngStream();
RandomVariable::m_static_generator->InitializeStream();
}
~RandomVariableInitializer()
{
delete RandomVariable::m_static_generator;
}
} random_variable_initializer;
RandomVariable::RandomVariable()
{
m_generator = new RngStream();
RandomVariable::Initialize(); // sets the seed for the static object
m_generator->InitializeStream();
m_generator->ResetNthSubstream(RandomVariable::runNumber);
}
@@ -173,7 +190,7 @@ void RandomVariable::SetRunNumber(uint32_t n)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// UniformVariable methods
// UniformVariable
UniformVariable::UniformVariable()
: m_min(0), m_max(1.0) { }
@@ -192,6 +209,12 @@ RandomVariable* UniformVariable::Copy() const
{
return new UniformVariable(*this);
}
double UniformVariable::GetSingleValue(double s, double l)
{
return s + m_static_generator->RandU01() * (l - s);;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ConstantVariable methods
@@ -291,6 +314,12 @@ RandomVariable* ExponentialVariable::Copy() const
{
return new ExponentialVariable(*this);
}
double ExponentialVariable::GetSingleValue(double m, double b/*=0*/)
{
double r = -m*log(m_static_generator->RandU01());
if (b != 0 && r > b) return b;
return r;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ParetoVariable methods
@@ -322,6 +351,14 @@ RandomVariable* ParetoVariable::Copy() const
{
return new ParetoVariable(*this);
}
double ParetoVariable::GetSingleValue(double m, double s, double b/*=0*/)
{
double scale = m * ( s - 1.0) / s;
double r = (scale * ( 1.0 / pow(m_static_generator->RandU01(), 1.0 / s)));
if (b != 0 && r > b) return b;
return r;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// WeibullVariable methods
@@ -348,14 +385,25 @@ RandomVariable* WeibullVariable::Copy() const
{
return new WeibullVariable(*this);
}
double WeibullVariable::GetSingleValue(double m, double s, double b/*=0*/)
{
double exponent = 1.0 / s;
double r = m * pow( -log(m_static_generator->RandU01()), exponent);
if (b != 0 && r > b) return b;
return r;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// NormalVariable methods
bool NormalVariable::m_static_nextValid = false;
double NormalVariable::m_static_next;
const double NormalVariable::INFINITE_VALUE = 1e307;
NormalVariable::NormalVariable()
: m_mean(0.0), m_variance(1.0), m_bound(INFINITE_VALUE), m_nextValid(false){}
NormalVariable::NormalVariable(double m, double v, double b)
NormalVariable::NormalVariable(double m, double v, double b/*=INFINITE_VALUE*/)
: m_mean(m), m_variance(v), m_bound(b), m_nextValid(false) { }
NormalVariable::NormalVariable(const NormalVariable& c)
@@ -395,6 +443,34 @@ RandomVariable* NormalVariable::Copy() const
return new NormalVariable(*this);
}
double NormalVariable::GetSingleValue(double m, double v, double b)
{
if (m_static_nextValid)
{ // use previously generated
m_static_nextValid = false;
return m_static_next;
}
while(1)
{ // See Simulation Modeling and Analysis p. 466 (Averill Law)
// for algorithm
double u1 = m_static_generator->RandU01();
double u2 = m_static_generator->RandU01();;
double v1 = 2 * u1 - 1;
double v2 = 2 * u2 - 1;
double w = v1 * v1 + v2 * v2;
if (w <= 1.0)
{ // Got good pair
double y = sqrt((-2 * log(w))/w);
m_static_next = m + v2 * y * sqrt(v);
if (fabs(m_static_next) > b) m_static_next = b * (m_static_next)/fabs(m_static_next);
m_static_nextValid = true;
double x1 = m + v1 * y * sqrt(v);
if (fabs(x1) > b) x1 = b * (x1)/fabs(x1);
return x1;
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ValueCDF methods
@@ -522,5 +598,91 @@ RandomVariable* DeterministicVariable::Copy() const
return new DeterministicVariable(*this);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LogNormalVariable
RandomVariable* LogNormalVariable::Copy () const
{
return new LogNormalVariable (m_mu, m_sigma);
}
LogNormalVariable::LogNormalVariable (double mu, double sigma)
:m_mu(mu), m_sigma(sigma)
{
}
// The code from this function was adapted from the GNU Scientific
// Library 1.8:
/* randist/lognormal.c
*
* Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* The lognormal distribution has the form
p(x) dx = 1/(x * sqrt(2 pi sigma^2)) exp(-(ln(x) - zeta)^2/2 sigma^2) dx
for x > 0. Lognormal random numbers are the exponentials of
gaussian random numbers */
double
LogNormalVariable::GetValue ()
{
double u, v, r2, normal, z;
do
{
/* choose x,y in uniform square (-1,-1) to (+1,+1) */
u = -1 + 2 * m_generator->RandU01 ();
v = -1 + 2 * m_generator->RandU01 ();
/* see if it is in the unit circle */
r2 = u * u + v * v;
}
while (r2 > 1.0 || r2 == 0);
normal = u * sqrt (-2.0 * log (r2) / r2);
z = exp (m_sigma * normal + m_mu);
return z;
}
double LogNormalVariable::GetSingleValue(double sigma,double mu)
{
double u, v, r2, normal, z;
do
{
/* choose x,y in uniform square (-1,-1) to (+1,+1) */
u = -1 + 2 * m_static_generator->RandU01 ();
v = -1 + 2 * m_static_generator->RandU01 ();
/* see if it is in the unit circle */
r2 = u * u + v * v;
}
while (r2 > 1.0 || r2 == 0);
normal = u * sqrt (-2.0 * log (r2) / r2);
z = exp (sigma * normal + mu);
return z;
}
}//namespace ns3

View File

@@ -182,8 +182,10 @@ private:
static int devRandom; // File handle for /dev/random
static uint32_t globalSeed[6]; // The global seed to use
static uint32_t runNumber;
friend class RandomVariableInitializer;
protected:
static unsigned long heuristic_sequence;
static RngStream* m_static_generator;
RngStream* m_generator; //underlying generator being wrapped
};
@@ -191,6 +193,13 @@ protected:
/**
* \brief The uniform distribution RNG for NS-3.
* \ingroup randomvariable
* This class supports the creation of objects that return random numbers
* from a fixed uniform distribution. It also supports the generation of
* single random numbers from various uniform distributions.
* \code
* UniformVariable x(0,10);
* x.GetValue(); //will always return numbers [0,10]
* UniformVariable::GetSingleValue(100,1000); //returns a value [100,1000]
*/
class UniformVariable : public RandomVariable {
public:
@@ -214,6 +223,13 @@ public:
*/
virtual double GetValue();
virtual RandomVariable* Copy() const;
public:
/**
* \param s Low end of the range
* \param l High end of the range
* \return A uniformly distributed random number between s and l
*/
static double GetSingleValue(double s, double l);
private:
double m_min;
double m_max;
@@ -317,8 +333,16 @@ private:
/**
* \brief Exponentially Distributed random var
* \ingroup randomvariable
* This class supports the creation of objects that return random numbers
* from a fixed exponential distribution. It also supports the generation of
* single random numbers from various exponential distributions.
* \code
* ExponentialVariable x(3.14);
* x.GetValue(); //will always return with mean 3.14
* ExponentialVariable::GetSingleValue(20.1); //returns with mean 20.1
* ExponentialVariable::GetSingleValue(108); //returns with mean 108
* \endcode
*
* ExponentialVariable defines a random variable with an exponential distribution
*/
class ExponentialVariable : public RandomVariable {
public:
@@ -354,6 +378,13 @@ public:
*/
virtual double GetValue();
virtual RandomVariable* Copy() const;
public:
/**
* \param m The mean of the distribution from which the return value is drawn
* \param b The upper bound value desired, beyond which values get clipped
* \return A random number from an exponential distribution with mean m
*/
static double GetSingleValue(double m, double b=0);
private:
double m_mean; // Mean value of RV
double m_bound; // Upper bound on value (if non-zero)
@@ -362,8 +393,17 @@ private:
/**
* \brief ParetoVariable distributed random var
* \ingroup randomvariable
* This class supports the creation of objects that return random numbers
* from a fixed pareto distribution. It also supports the generation of
* single random numbers from various pareto distributions.
* \code
* ParetoVariable x(3.14);
* x.GetValue(); //will always return with mean 3.14
* ParetoVariable::GetSingleValue(20.1); //returns with mean 20.1
* ParetoVariable::GetSingleValue(108); //returns with mean 108
* \endcode
*/
class ParetoVariable : public RandomVariable { //
class ParetoVariable : public RandomVariable {
public:
/**
* Constructs a pareto random variable with a mean of 1 and a shape
@@ -389,6 +429,7 @@ public:
/**
* \brief Constructs a pareto random variable with the specified mean
* \brief value, shape (alpha), and upper bound.
*
* Since pareto distributions can theoretically return unbounded values,
* it is sometimes useful to specify a fixed upper limit. Note however
* when the upper limit is specified, the true mean of the distribution
@@ -406,6 +447,17 @@ public:
*/
virtual double GetValue();
virtual RandomVariable* Copy() const;
public:
/**
* \param m The mean value of the distribution from which the return value
* is drawn.
* \param s The shape parameter of the distribution from which the return
* value is drawn.
* \param b The upper bound to which to restrict return values
* \return A random number from a Pareto distribution with mean m and shape
* parameter s.
*/
static double GetSingleValue(double m, double s, double b=0);
private:
double m_mean; // Mean value of RV
double m_shape; // Shape parameter
@@ -415,6 +467,9 @@ private:
/**
* \brief WeibullVariable distributed random var
* \ingroup randomvariable
* This class supports the creation of objects that return random numbers
* from a fixed weibull distribution. It also supports the generation of
* single random numbers from various weibull distributions.
*/
class WeibullVariable : public RandomVariable {
public:
@@ -460,6 +515,14 @@ public:
*/
virtual double GetValue();
virtual RandomVariable* Copy() const;
public:
/**
* \param m Mean value for the distribution.
* \param s Shape (alpha) parameter for the distribution.
* \param b Upper limit on returned values
* \return Random number from a distribution specified by m,s, and b
*/
static double GetSingleValue(double m, double s, double b=0);
private:
double m_mean; // Mean value of RV
double m_alpha; // Shape parameter
@@ -469,6 +532,10 @@ private:
/**
* \brief Class NormalVariable defines a random variable with a
* normal (Gaussian) distribution.
*
* This class supports the creation of objects that return random numbers
* from a fixed normal distribution. It also supports the generation of
* single random numbers from various normal distributions.
* \ingroup randomvariable
*/
class NormalVariable : public RandomVariable { // Normally Distributed random var
@@ -481,7 +548,6 @@ public:
*/
NormalVariable();
/**
* \brief Construct a normal random variable with specified mean and variance
* \param m Mean value
@@ -497,12 +563,22 @@ public:
*/
virtual double GetValue();
virtual RandomVariable* Copy() const;
public:
/**
* \param m Mean value
* \param v Variance
* \param b Bound. The NormalVariable is bounded within +-bound.
* \return A random number from a distribution specified by m,v, and b.
*/
static double GetSingleValue(double m, double v, double b = INFINITE_VALUE);
private:
double m_mean; // Mean value of RV
double m_variance; // Mean value of RV
double m_bound; // Bound on value (absolute value)
bool m_nextValid; // True if next valid
bool m_nextValid; // True if next valid
double m_next; // The algorithm produces two values at a time
static bool m_static_nextValid;
static double m_static_next;
};
/**
@@ -612,5 +688,54 @@ private:
double* data;
};
/**
* \brief Log-normal Distributed random var
* \ingroup randomvariable
* LogNormalVariable defines a random variable with log-normal
* distribution. If one takes the natural logarithm of random
* variable following the log-normal distribution, the obtained values
* follow a normal distribution.
* This class supports the creation of objects that return random numbers
* from a fixed lognormal distribution. It also supports the generation of
* single random numbers from various lognormal distributions.
*/
class LogNormalVariable : public RandomVariable {
public:
/**
* \param mu Mean value of the underlying normal distribution.
* \param sigma Standard deviation of the underlying normal distribution.
*
* Notice: the parameters mu and sigma are _not_ the mean and standard
* deviation of the log-normal distribution. To obtain the
* parameters mu and sigma for a given mean and standard deviation
* of the log-normal distribution the following convertion can be
* used:
* \code
* double tmp = log (1 + pow (stddev/mean, 2));
* double sigma = sqrt (tmp);
* double mu = log (mean) - 0.5*tmp;
* \endcode
*/
LogNormalVariable (double mu, double sigma);
/**
* \return A random value from this distribution
*/
virtual double GetValue ();
virtual RandomVariable* Copy() const;
public:
/**
* \param mu Mean value of the underlying normal distribution.
* \param sigma Standard deviation of the underlying normal distribution.
* \return A random number from the distribution specified by mu and sigma
*/
static double GetSingleValue(double mu, double sigma);
private:
double m_mu;
double m_sigma;
};
}//namespace ns3
#endif

24
src/core/type-name.cc Normal file
View File

@@ -0,0 +1,24 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "type-name.h"
namespace ns3 {
#define DEF_TYPE(x) \
template <> \
std::string TypeNameGet<x> (void) \
{ \
return #x; \
}
DEF_TYPE (uint8_t);
DEF_TYPE (uint16_t);
DEF_TYPE (uint32_t);
DEF_TYPE (uint64_t);
DEF_TYPE (int8_t);
DEF_TYPE (int16_t);
DEF_TYPE (int32_t);
DEF_TYPE (int64_t);
}//namespace ns3

34
src/core/type-name.h Normal file
View File

@@ -0,0 +1,34 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef TYPE_NAME_H
#define TYPE_NAME_H
#include <stdint.h>
#include <string>
namespace ns3 {
template <typename T>
std::string TypeNameGet (void)
{
return "unknown";
}
#define DEF_TYPE(x) \
template <> \
std::string TypeNameGet<x> (void)
DEF_TYPE (uint8_t);
DEF_TYPE (uint16_t);
DEF_TYPE (uint32_t);
DEF_TYPE (uint64_t);
DEF_TYPE (int8_t);
DEF_TYPE (int16_t);
DEF_TYPE (int32_t);
DEF_TYPE (int64_t);
#undef DEF_TYPE
}//namespace ns3
#endif /* TYPE_NAME_H */

View File

@@ -28,6 +28,8 @@ static class QueueStackInitializationClass {
public:
QueueStackInitializationClass () {
Queue::Default (DropTailQueue ());
static DropTailQueue queue;
Queue::AddDefault (queue, "DropTail");
}
} queue_stack_initialization_class;

View File

@@ -20,6 +20,7 @@
#include "ns3/debug.h"
#include "ns3/composite-trace-resolver.h"
#include "queue.h"
#include "ns3/default-value.h"
NS_DEBUG_COMPONENT_DEFINE ("Queue");
@@ -209,4 +210,47 @@ Queue& Queue::Default()
return *defaultQueue;
}
Queue *
Queue::CreateDefault (void)
{
std::string defaultValue = GetDefault ()->GetValue ();
for (List::iterator i = GetList ()->begin ();
i != GetList ()->end (); i++)
{
if (i->second == defaultValue)
{
return i->first->Copy ();
}
}
NS_ASSERT (false);
// quiet compiler
return 0;
}
void
Queue::Add (Queue &queue, const std::string &name)
{
GetDefault ()->AddPossibleValue (name);
GetList ()->push_back (std::make_pair (&queue, name));
}
void
Queue::AddDefault (Queue &queue, const std::string &name)
{
GetDefault ()->AddDefaultValue (name);
GetList ()->push_back (std::make_pair (&queue, name));
}
StringEnumDefaultValue *
Queue::GetDefault (void)
{
static StringEnumDefaultValue value ("queue", "Packet Queue");
return &value;
}
Queue::List *
Queue::GetList (void)
{
static List list;
return &list;
}
}; // namespace ns3

View File

@@ -26,12 +26,15 @@
#define QUEUE_H
#include <string>
#include <list>
#include "ns3/packet.h"
#include "ns3/callback-trace-source.h"
#include "ns3/trace-resolver.h"
namespace ns3 {
class StringEnumDefaultValue;
class Queue
{
public:
@@ -108,6 +111,15 @@ private:
uint32_t m_nTotalDroppedBytes;
uint32_t m_nTotalDroppedPackets;
public:
static Queue *CreateDefault (void);
static void Add (Queue &queue, const std::string &name);
static void AddDefault (Queue &queue, const std::string &name);
private:
typedef std::list<std::pair<Queue *,std::string> > List;
static StringEnumDefaultValue *GetDefault (void);
static List *GetList (void);
public:
// Static methods to manage queue default
// Set desired queue default

View File

@@ -19,6 +19,9 @@
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "scheduler-factory.h"
#include "ns3/assert.h"
#include "ns3/fatal-error.h"
#include "ns3/default-value.h"
namespace ns3 {
@@ -28,7 +31,73 @@ SchedulerFactory::~SchedulerFactory ()
Scheduler *
SchedulerFactory::Create (void) const
{
return RealCreate ();
return DoCreate ();
}
Scheduler *
SchedulerFactory::CreateDefault (void)
{
NS_ASSERT_MSG (!GetList ()->empty (), "No Scheduler factory registered");
std::string defaultValue = GetDefault ()->GetValue ();
for (List::const_iterator i = GetList ()->begin ();
i != GetList ()->end (); i++)
{
if (i->second == defaultValue)
{
return i->first->Create ();
}
}
NS_ASSERT (false);
// quiet compiler
return 0;
}
Scheduler *
SchedulerFactory::Create (const std::string &name)
{
for (List::iterator i = GetList ()->begin ();
i != GetList ()->end (); i++)
{
if (i->second == name)
{
return i->first->Create ();
}
}
NS_ASSERT_MSG (false, "Tried to create non-existant scheduler: " << name);
// quiet compiler.
return 0;
}
void
SchedulerFactory::AddDefault (const SchedulerFactory *factory,
const std::string &name)
{
GetDefault ()->AddDefaultValue (name);
GetList ()->push_back (std::make_pair (factory, name));
}
void
SchedulerFactory::Add (const SchedulerFactory *factory,
const std::string &name)
{
GetDefault ()->AddPossibleValue (name);
GetList ()->push_back (std::make_pair (factory, name));
}
StringEnumDefaultValue *
SchedulerFactory::GetDefault (void)
{
static StringEnumDefaultValue value ("scheduler", "Event Scheduler algorithm");
return &value;
}
SchedulerFactory::List *
SchedulerFactory::GetList (void)
{
static SchedulerFactory::List list;
return &list;
}
}; // namespace ns3

View File

@@ -21,9 +21,12 @@
#ifndef SCHEDULER_FACTORY_H
#define SCHEDULER_FACTORY_H
#include <list>
namespace ns3 {
class Scheduler;
class StringEnumDefaultValue;
/**
* \brief a base class to create event schedulers
@@ -36,13 +39,39 @@ class Scheduler;
class SchedulerFactory {
public:
virtual ~SchedulerFactory ();
/**
* \returns a newly-created scheduler.
*/
Scheduler *Create (void) const;
/**
* \returns a newly-created scheduler.
*
* Return a "default" scheduler.
*/
static Scheduler *CreateDefault (void);
/**
* \param name of scheduler to create.
* \returns a newly-created scheduler.
*
* Create a scheduler registered under the specified name.
*/
static Scheduler *Create (const std::string &name);
protected:
static void Add (const SchedulerFactory *factory,
const std::string &name);
static void AddDefault (const SchedulerFactory *factory,
const std::string &name);
private:
typedef std::list<std::pair<const SchedulerFactory *, std::string> > List;
static SchedulerFactory::List *GetList (void);
static StringEnumDefaultValue *GetDefault (void);
/**
* \returns a newly-created scheduler. The caller takes
* ownership of the returned pointer.
*
* This method must be implemented by subclasses.
*/
virtual Scheduler *RealCreate (void) const = 0;
virtual Scheduler *DoCreate (void) const = 0;
};
}; // namespace ns3

View File

@@ -33,6 +33,7 @@
*/
#include "scheduler-heap.h"
#include "scheduler-factory.h"
#include "event-impl.h"
#include "ns3/assert.h"
@@ -51,6 +52,21 @@ std::cout << "HEAP TRACE " << x << std::endl;
namespace ns3 {
static class SchedulerHeapFactory : public SchedulerFactory
{
public:
SchedulerHeapFactory ()
{
SchedulerFactory::Add (this, "BinaryHeap");
}
private:
virtual Scheduler *DoCreate (void) const
{
return new SchedulerHeap ();
}
} g_schedulerHeapFactory;
SchedulerHeap::SchedulerHeap ()
{
// we purposedly waste an item at the start of

View File

@@ -20,12 +20,28 @@
*/
#include "scheduler-list.h"
#include "scheduler-factory.h"
#include "event-impl.h"
#include <utility>
#include "ns3/assert.h"
namespace ns3 {
static class SchedulerListFactory : public SchedulerFactory
{
public:
SchedulerListFactory ()
{
SchedulerFactory::AddDefault (this, "list");
}
private:
virtual Scheduler *DoCreate (void) const
{
return new SchedulerList ();
}
} g_schedulerListFactory;
SchedulerList::SchedulerList ()
{}
SchedulerList::~SchedulerList ()

View File

@@ -21,6 +21,7 @@
*/
#include "scheduler-map.h"
#include "scheduler-factory.h"
#include "event-impl.h"
#include "ns3/assert.h"
@@ -37,6 +38,20 @@ std::cout << "MAP TRACE " << x << std::endl;
namespace ns3 {
static class SchedulerMapFactory : public SchedulerFactory
{
public:
SchedulerMapFactory ()
{
SchedulerFactory::Add (this, "map");
}
private:
virtual Scheduler *DoCreate (void) const
{
return new SchedulerMap ();
}
} g_schedulerMapFactory;
SchedulerMap::SchedulerMap ()
{}

View File

@@ -23,8 +23,11 @@
#include "scheduler.h"
#include "event-impl.h"
#include <math.h>
#include "ns3/assert.h"
#include "ns3/default-value.h"
#include <math.h>
#include <fstream>
#include <list>
#include <vector>
@@ -293,27 +296,23 @@ SimulatorPrivate::IsExpired (EventId ev)
namespace ns3 {
SimulatorPrivate *Simulator::m_priv = 0;
Simulator::ListType Simulator::m_listType = LINKED_LIST;
SchedulerFactory const*Simulator::m_schedFactory = 0;
void Simulator::SetLinkedList (void)
{
m_listType = LINKED_LIST;
Bind ("scheduler", "list");
}
void Simulator::SetBinaryHeap (void)
{
m_listType = BINARY_HEAP;
Bind ("scheduler", "BinaryHeap");
}
void Simulator::SetStdMap (void)
{
m_listType = STD_MAP;
Bind ("scheduler", "map");
}
void
Simulator::SetExternal (SchedulerFactory const*factory)
Simulator::SetExternal (const std::string &external)
{
NS_ASSERT (factory != 0);
m_schedFactory = factory;
m_listType = EXTERNAL;
Bind ("scheduler", external);
}
void Simulator::EnableLogTo (char const *filename)
{
@@ -326,24 +325,7 @@ Simulator::GetPriv (void)
{
if (m_priv == 0)
{
Scheduler *events;
switch (m_listType) {
case LINKED_LIST:
events = new SchedulerList ();
break;
case BINARY_HEAP:
events = new SchedulerHeap ();
break;
case STD_MAP:
events = new SchedulerMap ();
break;
case EXTERNAL:
events = m_schedFactory->Create ();
default: // not reached
events = 0;
NS_ASSERT (false);
break;
}
Scheduler *events = SchedulerFactory::CreateDefault ();
m_priv = new SimulatorPrivate (events);
}
TRACE_S ("priv " << m_priv);

View File

@@ -85,7 +85,7 @@ public:
* This method must be invoked before any other method exported
* by the Simulator class.
*/
static void SetExternal (SchedulerFactory const*factory);
static void SetExternal (const std::string &name);
/**
* Enable logging to the file identified by filename. If the file
@@ -557,13 +557,6 @@ private:
static void ScheduleDestroy (EventImpl *event);
static void ScheduleNow (EventImpl *event);
static SimulatorPrivate *m_priv;
static SchedulerFactory const*m_schedFactory;
static enum ListType {
LINKED_LIST,
BINARY_HEAP,
STD_MAP,
EXTERNAL
} m_listType;
};
}; // namespace ns3

View File

@@ -25,7 +25,9 @@ int main (int argc, char *argv[])
{
#ifdef RUN_SELF_TESTS
ns3::TestManager::EnableVerbose ();
ns3::TestManager::RunTests ();
bool success = ns3::TestManager::RunTests ();
if (!success)
return 1;
#endif /* RUN_SELF_TESTS */
return 0;