merge with HEAD
This commit is contained in:
18
SConstruct
18
SConstruct
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
85
samples/main-default-value.cc
Normal file
85
samples/main-default-value.cc
Normal 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
131
src/core/command-line.cc
Normal 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
93
src/core/command-line.h
Normal 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
447
src/core/default-value.cc
Normal 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
423
src/core/default-value.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
24
src/core/type-name.cc
Normal 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
34
src/core/type-name.h
Normal 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 */
|
||||
@@ -28,6 +28,8 @@ static class QueueStackInitializationClass {
|
||||
public:
|
||||
QueueStackInitializationClass () {
|
||||
Queue::Default (DropTailQueue ());
|
||||
static DropTailQueue queue;
|
||||
Queue::AddDefault (queue, "DropTail");
|
||||
}
|
||||
} queue_stack_initialization_class;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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 ()
|
||||
{}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user