first cut at george's ideas on api

This commit is contained in:
Mathieu Lacage
2006-09-03 12:24:04 +02:00
parent fd43aa8bdf
commit 02fa792b81
24 changed files with 591 additions and 1094 deletions

View File

@@ -511,13 +511,13 @@ simu = Ns3Module ('simulator', 'src/simulator')
ns3.add (simu)
simu.add_dep ('core')
simu.add_sources ([
'time.cc',
'event-id.cc',
'scheduler.cc',
'scheduler-list.cc',
'scheduler-heap.cc',
'scheduler-map.cc',
'scheduler-heap.cc',
'scheduler-map.cc',
'event-impl.cc',
'event-tcc.cc',
'event-tcc-test.cc',
'simulator.cc',
])
simu.add_headers ([
@@ -527,10 +527,10 @@ simu.add_headers ([
'scheduler-list.h'
])
simu.add_inst_headers ([
'event.h',
'time.h',
'event-id.h',
'event-impl.h',
'simulator.h',
'event.tcc'
])
#
@@ -625,12 +625,6 @@ ns3.add (main_callback)
main_callback.add_dep ('core')
main_callback.add_source ('main-callback.cc')
main_event = Ns3Module ('main-event', 'samples')
main_event.set_executable ()
ns3.add (main_event)
main_event.add_dep ('simulator')
main_event.add_source ('main-event.cc')
main_trace = Ns3Module ('main-trace', 'samples')
ns3.add (main_trace)
main_trace.add_dep ('common')

View File

@@ -1,42 +0,0 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
#include "ns3/event.h"
#include "ns3/event.tcc"
#include <iostream>
using namespace ns3;
class MyModel {
public:
void deal_with_event (double event_value);
};
void
MyModel::deal_with_event (double value)
{
std::cout << "Member method received event." << std::endl;
}
static void
random_function (void)
{
std::cout << "Function received event." << std::endl;
}
int main (int argc, char *argv[])
{
Event ev;
// create event to forward to random_function
ev = make_event (&random_function);
// set cancel bit to on
ev.cancel ();
// try to invoke the random_function through the event.
// This does nothing since cancel bit is on.
ev ();
MyModel model;
// create event to forward to MyModel::deal_with_event
// on the class instance "model".
ev = make_event (&MyModel::deal_with_event, &model, 10.0);
// invoke member method through the event.
ev ();
}

View File

@@ -1,7 +1,6 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
#include "ns3/event.h"
#include "ns3/event.tcc"
#include "ns3/simulator.h"
#include "ns3/time.h"
#include <iostream>
using namespace ns3;
@@ -10,25 +9,26 @@ class MyModel {
public:
void start (void);
private:
void deal_with_event (double event_value);
void deal_with_event (void);
};
void
MyModel::start (void)
{
Simulator::schedule_rel_s (10.0, make_event (&MyModel::deal_with_event,
this, Simulator::now_s ()));
Simulator::schedule (RelTimeS (10.0),
&MyModel::deal_with_event,
this);
}
void
MyModel::deal_with_event (double value)
MyModel::deal_with_event (void)
{
std::cout << "Member method received event at " << Simulator::now_s () << " started at " << value << std::endl;
std::cout << "Member method received event at " << Simulator::now ().s () << " started at " << std::endl;
}
static void
random_function (MyModel *model)
{
std::cout << "random function received event at " << Simulator::now_s () << std::endl;
std::cout << "random function received event at " << Simulator::now ().s () << std::endl;
model->start ();
}
@@ -37,8 +37,7 @@ int main (int argc, char *argv[])
{
MyModel model;
Simulator::schedule_rel_s (10.0, make_event (&random_function,
&model));
Simulator::schedule (AbsTimeS (10.0), &random_function, &model);
Simulator::run ();

View File

@@ -69,7 +69,7 @@ void
PcapWriter::write_packet (Packet const packet)
{
if (m_writer != 0) {
uint64_t current = Simulator::now_us ();
uint64_t current = Simulator::now ().us ();
uint64_t s = current / 1000000;
uint64_t us = current % 1000000;
write_32 (s & 0xffffffff);

View File

@@ -54,7 +54,7 @@ StaticSpeedPosition::set_delta (double dx, double dy, double dz)
void
StaticSpeedPosition::real_get (double &x, double &y, double &z) const
{
uint64_t now_us = Simulator::now_us ();
uint64_t now_us = Simulator::now ().us ();
uint64_t delta_us = now_us - m_prev_us;
m_x += m_dx * delta_us;
m_y += m_dy * delta_us;

64
src/simulator/event-id.cc Normal file
View File

@@ -0,0 +1,64 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "event-id.h"
#include "simulator.h"
namespace ns3 {
EventId::EventId ()
: m_event_impl (0),
m_time (0),
m_uid (0)
{}
EventId::EventId (EventImpl *impl, uint64_t time, uint32_t uid)
: m_event_impl (impl),
m_time (time),
m_uid (uid)
{}
void
EventId::cancel (void)
{
Simulator::cancel (*this);
}
bool
EventId::is_expired (void)
{
return Simulator::is_expired (*this);
}
EventImpl *
EventId::get_event_impl (void) const
{
return m_event_impl;
}
uint64_t
EventId::get_time (void) const
{
return m_time;
}
uint32_t
EventId::get_uid (void) const
{
return m_uid;
}
}; // namespace ns3

View File

@@ -18,30 +18,35 @@
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "event-impl.h"
#include "event.h"
#ifndef EVENT_ID_H
#define EVENT_ID_H
#include <stdint.h>
namespace ns3 {
class EventFunctionImpl0 : public EventImpl {
public:
typedef void (*F)(void);
class EventImpl;
EventFunctionImpl0 (F function)
: m_function (function)
{}
virtual ~EventFunctionImpl0 () {}
class EventId {
public:
EventId ();
EventId (EventImpl *impl, uint64_t time, uint32_t uid);
void cancel (void);
bool is_expired (void);
public:
/* The following methods are semi-private
* they are supposed to be invoked only by
* subclasses of the Scheduler base class.
*/
EventImpl *get_event_impl (void) const;
uint64_t get_time (void) const;
uint32_t get_uid (void) const;
private:
virtual void notify (void) {
(*m_function) ();
}
private:
F m_function;
EventImpl *m_event_impl;
uint64_t m_time;
uint32_t m_uid;
};
Event make_event(void (*f) (void))
{
return Event (new EventFunctionImpl0 (f));
}
}; // namespace ns3
#endif /* EVENT_ID_H */

View File

@@ -29,39 +29,30 @@ EventImpl::~EventImpl ()
{}
EventImpl::EventImpl ()
: m_id (0),
m_count (1),
m_cancel (0),
m_running (1)
: m_internal_iterator (0),
m_cancel (false)
{}
void
EventImpl::invoke (void)
{
if (m_cancel == 0) {
if (!m_cancel) {
notify ();
}
m_running = 0;
}
void
EventImpl::set_tag (void *tag)
EventImpl::set_internal_iterator (void *tag)
{
m_id = tag;
m_internal_iterator = tag;
}
void *
EventImpl::get_tag (void) const
EventImpl::get_internal_iterator (void) const
{
return m_id;
return m_internal_iterator;
}
void
EventImpl::cancel (void)
{
m_cancel = 1;
m_running = 0;
}
bool
EventImpl::is_running (void)
{
return (m_running == 1);
m_cancel = true;
}
}; // namespace ns3

View File

@@ -30,18 +30,15 @@ public:
EventImpl ();
virtual ~EventImpl () = 0;
void invoke (void);
void set_tag (void *tag);
void *get_tag (void) const;
void cancel (void);
bool is_running (void);
void set_internal_iterator (void *iterator);
void *get_internal_iterator (void) const;
protected:
virtual void notify (void) = 0;
private:
friend class Event;
void *m_id;
uint32_t m_count;
uint32_t m_cancel : 1;
uint32_t m_running : 1;
void *m_internal_iterator;
bool m_cancel;
};
}; // namespace ns3

View File

@@ -1,110 +0,0 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "event.tcc"
#include "ns3/test.h"
#ifdef RUN_SELF_TESTS
#define ENSURE(got,expected) \
if (got != expected) { \
g_error = true; \
}
namespace {
bool g_error = false;
void null_cb (void)
{}
void one_cb (int a)
{
ENSURE (a, 1);
}
void two_cb (int a,int b)
{
ENSURE (a, 1);
ENSURE (b, 2);
}
void three_cb (int a,int b,int c)
{
ENSURE (a, 1);
ENSURE (b, 2);
ENSURE (c, 3);
}
void four_cb (int a,int b,int c,int d)
{
ENSURE (a, 1);
ENSURE (b, 2);
ENSURE (c, 3);
ENSURE (d, 4);
}
void five_cb (int a,int b,int c,int d,int e)
{
ENSURE (a, 1);
ENSURE (b, 2);
ENSURE (c, 3);
ENSURE (d, 4);
ENSURE (e, 5);
}
};
namespace ns3 {
class EventTest : public Test {
public:
EventTest ();
virtual bool run_tests (void);
};
EventTest::EventTest ()
: Test ("Event")
{}
bool
EventTest::run_tests (void)
{
Event ev;
ev = ns3::make_event (&null_cb);
ev ();
ev = ns3::make_event (&one_cb, 1);
ev ();
ev = ns3::make_event (&two_cb, 1, 2);
ev ();
ev = ns3::make_event (&three_cb, 1, 2, 3);
ev ();
ev = ns3::make_event (&four_cb, 1, 2, 3, 4);
ev ();
ev = ns3::make_event (&five_cb, 1, 2, 3, 4, 5);
ev ();
if (g_error) {
return false;
}
return true;
}
static EventTest g_test;
};
#endif /* RUN_SELF_TESTS */

View File

@@ -1,140 +0,0 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EVENT_H
#define EVENT_H
#include <algorithm>
#include "event-impl.h"
namespace ns3 {
class EventImpl;
/**
* \brief Simulation events.
*
* The Event class has POD semantics: it can and should
* be passed around by value. The Event class is a mere
* wrapper around the EventImpl class and performs
* memory management of EventImpl object instances.
*
* While users could create Events by instanciating
* subclasses of the EventImpl class and storing them
* in an Event instance, they are advised to use the
* template functions \ref make_event instead.
*/
class Event {
public:
Event ()
: m_impl (0)
{}
Event (EventImpl *impl)
: m_impl (impl)
{}
Event (Event const &o)
: m_impl (o.m_impl)
{
if (m_impl != 0) {
m_impl->m_count++;
}
}
~Event ()
{
if (m_impl != 0) {
m_impl->m_count--;
if (m_impl->m_count == 0) {
delete m_impl;
}
}
m_impl = 0;
}
Event &operator = (Event const&o)
{
if (m_impl != 0) {
m_impl->m_count--;
if (m_impl->m_count == 0) {
delete m_impl;
}
}
m_impl = o.m_impl;
if (m_impl != 0) {
m_impl->m_count++;
}
return *this;
}
void operator () (void)
{
m_impl->invoke ();
}
/**
* Cancel an event. This operation has O(1)
* complexity since it merely sets a "cancel" bit
* to on and does not remove the Event from the
* scheduler's event list. When the event expires,
* the scheduler checks this cancel bit and, if set,
* does not execute the event.
*/
void cancel (void)
{
if (m_impl != 0) {
m_impl->cancel ();
}
}
/**
* Return true if the event is in RUNNING state.
* Return false otherwise.
*
* An Event is created in RUNNING state and switches
* to NON_RUNNING state upon one of:
* - cancel bit is set to on
* - Event execution is completed.
* It is important to note that an event is in RUNNING
* state while being executed.
*/
bool is_running (void)
{
if (m_impl != 0 && m_impl->is_running ()) {
return true;
} else {
return false;
}
}
private:
friend class SchedulerHeap;
friend class SchedulerList;
friend class SchedulerMap;
void set_tag (void *tag)
{
return m_impl->set_tag (tag);
}
void *get_tag (void) const
{
return m_impl->get_tag ();
}
EventImpl *m_impl;
};
}; // namespace ns3
#endif /* EVENT_H */

View File

@@ -1,454 +0,0 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef EVENT_TCC
#define EVENT_TCC
#include "event.h"
#include "event-impl.h"
/**
* ns3 namespace
*/
namespace ns3 {
/**
* \defgroup make_event make_event
*
* Every make_event template function returns a newly-created Event
* which holds a pointer to a special subclass of the EventImpl
* base class. Each of these subclasses holds information about which
* function or method to call and which parameters must be forwarded
* to this function or method.
*
* Sample code is shown below:
* \include samples/main-event.cc
*/
template<typename T>
class EventMemberImpl0 : public EventImpl {
public:
typedef void (T::*F)(void);
EventMemberImpl0 (T *obj, F function)
: m_obj (obj),
m_function (function)
{}
virtual ~EventMemberImpl0 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) ();
}
T* m_obj;
F m_function;
};
template<typename T, typename T1>
class EventMemberImpl1 : public EventImpl {
public:
typedef void (T::*F)(T1);
EventMemberImpl1 (T *obj, F function, T1 a1)
: m_obj (obj),
m_function (function),
m_a1 (a1)
{ }
virtual ~EventMemberImpl1 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1);
}
T* m_obj;
F m_function;
T1 m_a1;
};
template<typename T, typename T1, typename T2>
class EventMemberImpl2 : public EventImpl {
public:
typedef void (T::*F)(T1, T2);
EventMemberImpl2 (T *obj, F function, T1 a1, T2 a2)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2)
{ }
virtual ~EventMemberImpl2 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
};
template<typename T, typename T1, typename T2, typename T3>
class EventMemberImpl3 : public EventImpl {
public:
typedef void (T::*F)(T1, T2, T3);
EventMemberImpl3 (T *obj, F function, T1 a1, T2 a2, T3 a3)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3)
{ }
virtual ~EventMemberImpl3 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2, m_a3);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
};
template<typename T, typename T1, typename T2, typename T3, typename T4>
class EventMemberImpl4 : public EventImpl {
public:
typedef void (T::*F)(T1, T2, T3, T4);
EventMemberImpl4 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4)
{ }
virtual ~EventMemberImpl4 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
};
template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
class EventMemberImpl5 : public EventImpl {
public:
typedef void (T::*F)(T1, T2, T3, T4, T5);
EventMemberImpl5 (T *obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
: m_obj (obj),
m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4),
m_a5 (a5)
{ }
virtual ~EventMemberImpl5 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
}
T* m_obj;
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
T5 m_a5;
};
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \return a wrapper Event
* Build Events for class method members which take no arguments.
*/
template<typename T>
Event make_event(void (T::*f) (void), T* t) {
return Event (new EventMemberImpl0<T>(t, f));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take only one argument
*/
template<typename T, typename T1>
Event make_event(void (T::*f) (T1), T* t, T1 a1) {
return Event (new EventMemberImpl1<T, T1>(t, f, a1));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take two arguments
*/
template<typename T, typename T1, typename T2>
Event make_event(void (T::*f) (T1, T2), T* t, T1 a1, T2 a2) {
return Event (new EventMemberImpl2<T, T1, T2>(t, f, a1, a2));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \param a3 third argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take three arguments
*/
template<typename T, typename T1, typename T2, typename T3>
Event make_event(void (T::*f) (T1, T2, T3), T* t, T1 a1, T2 a2, T3 a3) {
return Event (new EventMemberImpl3<T, T1, T2, T3>(t, f, a1, a2, a3));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \param a3 third argument to pass to the target method when the event expires
* \param a4 fourth argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take four arguments
*/
template<typename T, typename T1, typename T2, typename T3, typename T4>
Event make_event(void (T::*f) (T1, T2, T3, T4), T* t, T1 a1, T2 a2, T3 a3, T4 a4) {
return Event (new EventMemberImpl4<T, T1, T2, T3, T4>(t, f, a1, a2, a3, a4));
}
/**
* \ingroup make_event
* \param f class method member pointer
* \param t class instance
* \param a1 first argument to pass to the target method when the event expires
* \param a2 second argument to pass to the target method when the event expires
* \param a3 third argument to pass to the target method when the event expires
* \param a4 fourth argument to pass to the target method when the event expires
* \param a5 fifth argument to pass to the target method when the event expires
* \return a wrapper Event
* Build Events for class method members which take five arguments.
*/
template<typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
Event make_event(void (T::*f) (T1, T2, T3, T4, T5), T* t, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
return Event (new EventMemberImpl5<T, T1, T2, T3, T4, T5>(t, f, a1, a2, a3, a4, a5));
}
template<typename T1>
class EventFunctionImpl1 : public EventImpl {
public:
typedef void (*F)(T1);
EventFunctionImpl1 (F function, T1 a1)
: m_function (function),
m_a1 (a1)
{ }
virtual ~EventFunctionImpl1 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1);
}
F m_function;
T1 m_a1;
};
template<typename T1, typename T2>
class EventFunctionImpl2 : public EventImpl {
public:
typedef void (*F)(T1, T2);
EventFunctionImpl2 (F function, T1 a1, T2 a2)
: m_function (function),
m_a1 (a1),
m_a2 (a2)
{ }
virtual ~EventFunctionImpl2 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2);
}
F m_function;
T1 m_a1;
T2 m_a2;
};
template<typename T1, typename T2, typename T3>
class EventFunctionImpl3 : public EventImpl {
public:
typedef void (*F)(T1, T2, T3);
EventFunctionImpl3 (F function, T1 a1, T2 a2, T3 a3)
: m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3)
{ }
virtual ~EventFunctionImpl3 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2, m_a3);
}
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
};
template<typename T1, typename T2, typename T3, typename T4>
class EventFunctionImpl4 : public EventImpl {
public:
typedef void (*F)(T1, T2, T3, T4);
EventFunctionImpl4 (F function, T1 a1, T2 a2, T3 a3, T4 a4)
: m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4)
{ }
virtual ~EventFunctionImpl4 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2, m_a3, m_a4);
}
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
class EventFunctionImpl5 : public EventImpl {
public:
typedef void (*F)(T1, T2, T3, T4, T5);
EventFunctionImpl5 (F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
: m_function (function),
m_a1 (a1),
m_a2 (a2),
m_a3 (a3),
m_a4 (a4),
m_a5 (a5)
{ }
virtual ~EventFunctionImpl5 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
}
F m_function;
T1 m_a1;
T2 m_a2;
T3 m_a3;
T4 m_a4;
T5 m_a5;
};
/**
* \ingroup make_event
* \param f function pointer
* \return a wrapper Event
* Build Events for function pointers which take no arguments
*/
Event make_event(void (*f) (void));
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take one argument
*/
template<typename T1>
Event make_event(void (*f) (T1), T1 a1) {
return Event (new EventFunctionImpl1<T1>(f, a1));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take two argument
*/
template<typename T1, typename T2>
Event make_event(void (*f) (T1, T2), T1 a1, T2 a2) {
return Event (new EventFunctionImpl2<T1, T2>(f, a1, a2));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \param a3 third argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take three argument
*/
template<typename T1, typename T2, typename T3>
Event make_event(void (*f) (T1, T2, T3), T1 a1, T2 a2, T3 a3) {
return Event (new EventFunctionImpl3<T1, T2, T3>(f, a1, a2, a3));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \param a3 third argument to pass to the target function when the event expires
* \param a4 fourth argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take four argument
*/
template<typename T1, typename T2, typename T3, typename T4>
Event make_event(void (*f) (T1, T2, T3, T4), T1 a1, T2 a2, T3 a3, T4 a4) {
return Event (new EventFunctionImpl4<T1, T2, T3, T4>(f, a1, a2, a3, a4));
}
/**
* \ingroup make_event
* \param f function pointer
* \param a1 first argument to pass to the target function when the event expires
* \param a2 second argument to pass to the target function when the event expires
* \param a3 third argument to pass to the target function when the event expires
* \param a4 fourth argument to pass to the target function when the event expires
* \param a5 fifth argument to pass to the target function when the event expires
* \return a wrapper Event
* Build Events for function pointers which take five argument
*/
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Event make_event(void (*f) (T1, T2, T3, T4, T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
return Event (new EventFunctionImpl5<T1, T2, T3, T4, T5>(f, a1, a2, a3, a4, a5));
}
}; // namespace ns3
#endif /* EVENT_TCC */

View File

@@ -33,7 +33,7 @@
*/
#include "scheduler-heap.h"
#include "event.h"
#include "event-impl.h"
#include <cassert>
#define noTRACE_HEAP 1
@@ -57,25 +57,22 @@ SchedulerHeap::SchedulerHeap ()
// the array to make sure the indexes in the
// array start at one.
Scheduler::EventKey empty_key = {0,0};
m_heap.push_back (std::make_pair ((Event )0, empty_key));
m_heap.push_back (std::make_pair (static_cast<EventImpl *>(0), empty_key));
}
SchedulerHeap::~SchedulerHeap ()
{}
void
SchedulerHeap::store_in_event (Event ev, uint32_t index) const
void
SchedulerHeap::store_in_event (EventImpl *ev, uint32_t index) const
{
ev.set_tag ((void *)index);
ev->set_internal_iterator ((void *)index);
}
uint32_t
SchedulerHeap::get_from_event (Event const ev) const
uint32_t
SchedulerHeap::get_from_event (EventImpl *ev) const
{
return (uint32_t)ev.get_tag ();
return (uint32_t)ev->get_internal_iterator ();
}
uint32_t
SchedulerHeap::parent (uint32_t id) const
{
@@ -127,14 +124,9 @@ SchedulerHeap::exch (uint32_t a, uint32_t b)
{
assert (b < m_heap.size () && a < m_heap.size ());
TRACE ("exch " << a << ", " << b);
#if 1
std::swap (m_heap[a].second, m_heap[b].second);
std::swap (m_heap[a].first.m_impl, m_heap[b].first.m_impl);
#else
std::pair<Event , Scheduler::EventKey> tmp (m_heap[a]);
std::pair<EventImpl*, Scheduler::EventKey> tmp (m_heap[a]);
m_heap[a] = m_heap[b];
m_heap[b] = tmp;
#endif
store_in_event (m_heap[a].first, a);
store_in_event (m_heap[b].first, b);
}
@@ -199,16 +191,16 @@ SchedulerHeap::top_down (void)
}
Event
SchedulerHeap::insert (Event event, Scheduler::EventKey key)
EventId
SchedulerHeap::insert (EventImpl *event, Scheduler::EventKey key)
{
m_heap.push_back (std::make_pair (event, key));
store_in_event (event, last ());
bottom_up ();
return event;
store_in_event (event, last ());
return EventId (event, key.m_time, key.m_uid);
}
Event
EventImpl *
SchedulerHeap::peek_next (void) const
{
assert (!is_empty ());
@@ -229,15 +221,26 @@ SchedulerHeap::remove_next (void)
top_down ();
}
Scheduler::EventKey
SchedulerHeap::remove (Event const ev)
EventImpl *
SchedulerHeap::remove (EventId id, Scheduler::EventKey *key)
{
EventImpl *ev = id.get_event_impl ();
uint32_t i = get_from_event (ev);
EventKey key = m_heap[i].second;
*key = m_heap[i].second;
exch (i, last ());
m_heap.pop_back ();
top_down ();
return key;
return ev;
}
bool
SchedulerHeap::is_valid (EventId id)
{
EventImpl *ev = id.get_event_impl ();
uint32_t i = get_from_event (ev);
Scheduler::EventKey key = m_heap[i].second;
return (key.m_time == id.get_time () &&
key.m_uid == id.get_uid ());
}
}; // namespace ns3

View File

@@ -28,7 +28,6 @@
namespace ns3 {
class Event;
class EventHolder;
class SchedulerHeap : public Scheduler {
@@ -36,16 +35,17 @@ public:
SchedulerHeap ();
virtual ~SchedulerHeap ();
virtual Event insert (Event event, Scheduler::EventKey key);
virtual EventId insert (EventImpl *event, Scheduler::EventKey key);
virtual bool is_empty (void) const;
virtual Event peek_next (void) const;
virtual EventImpl *peek_next (void) const;
virtual Scheduler::EventKey peek_next_key (void) const;
virtual void remove_next (void);
virtual Scheduler::EventKey remove (Event const ev);
virtual EventImpl *remove (EventId ev, Scheduler::EventKey *key);
virtual bool is_valid (EventId id);
private:
typedef std::vector<std::pair<Event, Scheduler::EventKey> > BinaryHeap;
inline void store_in_event (Event ev, uint32_t index) const;
uint32_t get_from_event (Event const ev) const;
typedef std::vector<std::pair<EventImpl *, Scheduler::EventKey> > BinaryHeap;
inline void store_in_event (EventImpl *ev, uint32_t index) const;
uint32_t get_from_event (EventImpl *ev) const;
inline uint32_t parent (uint32_t id) const;
uint32_t sibling (uint32_t id) const;

View File

@@ -20,7 +20,7 @@
*/
#include "scheduler-list.h"
#include "event.h"
#include "event-impl.h"
#include <utility>
#include <cassert>
@@ -37,46 +37,47 @@ SchedulerList::~SchedulerList ()
* it relies on the fact that a std::list<>::iterator has a single
* member variable, a pointer.
*/
void
SchedulerList::store_in_event (Event ev, EventsI i)
EventId
SchedulerList::get_event_id (Scheduler::EventKey key, EventsI i)
{
assert (sizeof (i) <= sizeof (Event));
void *tag;
strncpy ((char *)&(tag), (char *)&i, sizeof (void *));
ev.set_tag (tag);
assert (sizeof (i) <= sizeof (void *));
void *internal_iterator;
memcpy ((char *)&(internal_iterator), (char *)&i, sizeof (void *));
EventImpl *ev = i->first;
ev->set_internal_iterator (internal_iterator);
return EventId (ev, key.m_time, key.m_uid);
}
SchedulerList::EventsI
SchedulerList::get_from_event (Event const ev)
SchedulerList::get_iterator (EventId id)
{
SchedulerList::EventsI i;
assert (sizeof (i) <= sizeof (Event));
void *tag = ev.get_tag ();
strncpy ((char *)&i, (char *)&(tag), sizeof (void *));
assert (sizeof (i) <= sizeof (void *));
EventImpl *ev = id.get_event_impl ();
void *internal_iterator = ev->get_internal_iterator ();
memcpy ((char *)&i, (char *)&(internal_iterator), sizeof (void *));
return i;
}
Event
SchedulerList::insert (Event event, Scheduler::EventKey key)
EventId
SchedulerList::insert (EventImpl *event, Scheduler::EventKey key)
{
Scheduler::EventKeyCompare compare;
for (EventsI i = m_events.begin (); i != m_events.end (); i++) {
if (compare (key, i->second)) {
m_events.insert (i, std::make_pair (event, key));
store_in_event (event, i);
return event;
return get_event_id (key, i);
}
}
m_events.push_back (std::make_pair (event, key));
store_in_event (event, --(m_events.end ()));
return event;
return get_event_id (key, --(m_events.end ()));
}
bool
SchedulerList::is_empty (void) const
{
return m_events.empty ();
}
Event
EventImpl *
SchedulerList::peek_next (void) const
{
assert (!is_empty ());
@@ -95,13 +96,26 @@ SchedulerList::remove_next (void)
m_events.pop_front ();
}
Scheduler::EventKey
SchedulerList::remove (Event const ev)
EventImpl *
SchedulerList::remove (EventId id, Scheduler::EventKey *key)
{
EventsI i = get_from_event (ev);
EventKey key = (*i).second;
m_events.erase (get_from_event (ev));
return key;
EventsI i = get_iterator (id);
*key = i->second;
assert (key->m_time == id.get_time () &&
key->m_uid == id.get_uid ());
EventImpl *ev = i->first;
m_events.erase (i);
return ev;
}
bool
SchedulerList::is_valid (EventId id)
{
EventsI i = get_iterator (id);
Scheduler::EventKey key = i->second;
return (key.m_time == id.get_time () &&
key.m_uid == id.get_uid ());
}
}; // namespace ns3

View File

@@ -23,31 +23,32 @@
#define SCHEDULER_LIST_H
#include "scheduler.h"
#include "event-id.h"
#include <list>
#include <utility>
#include <stdint.h>
namespace ns3 {
class Event;
class EventImpl;
class SchedulerList : public Scheduler {
public:
SchedulerList ();
virtual ~SchedulerList ();
virtual Event insert (Event event, EventKey key);
virtual EventId insert (EventImpl *event, EventKey key);
virtual bool is_empty (void) const;
virtual Event peek_next (void) const;
virtual EventImpl *peek_next (void) const;
virtual Scheduler::EventKey peek_next_key (void) const;
virtual void remove_next (void);
virtual Scheduler::EventKey remove (Event const ev);
virtual EventImpl *remove (EventId ev, Scheduler::EventKey *key);
virtual bool is_valid (EventId id);
private:
typedef std::list<std::pair<Event, EventKey> > Events;
typedef std::list<std::pair<Event, EventKey> >::iterator EventsI;
void store_in_event (Event ev, EventsI i);
EventsI get_from_event (Event const ev);
typedef std::list<std::pair<EventImpl*, EventKey> > Events;
typedef std::list<std::pair<EventImpl*, EventKey> >::iterator EventsI;
EventId get_event_id (Scheduler::EventKey key, EventsI i);
EventsI get_iterator (EventId id);
Events m_events;
};

View File

@@ -21,7 +21,7 @@
*/
#include "scheduler-map.h"
#include "event.h"
#include "event-impl.h"
#include <cassert>
#define noTRACE_MAP 1
@@ -45,28 +45,28 @@ SchedulerMap::~SchedulerMap ()
void
SchedulerMap::store_in_event (Event ev, EventMapI i) const
SchedulerMap::store_in_event (EventImpl *ev, EventMapI i) const
{
void *tag;
memcpy (&(tag), &i, sizeof (tag));
ev.set_tag (tag);
ev->set_internal_iterator (tag);
}
SchedulerMap::EventMapI
SchedulerMap::get_from_event (Event const ev) const
SchedulerMap::get_from_event (EventImpl *ev) const
{
EventMapI i;
void *tag = ev.get_tag ();
void *tag = ev->get_internal_iterator ();
memcpy (&i, &(tag), sizeof (i));
return i;
}
Event
SchedulerMap::insert (Event event, Scheduler::EventKey key)
EventId
SchedulerMap::insert (EventImpl *event, Scheduler::EventKey key)
{
std::pair<EventMapI,bool> result = m_list.insert (std::make_pair (key, event));
assert (result.second);
store_in_event (event, result.first);
return event;
return EventId (event, key.m_time, key.m_uid);
}
bool
@@ -75,7 +75,7 @@ SchedulerMap::is_empty (void) const
return m_list.empty ();
}
Event
EventImpl *
SchedulerMap::peek_next (void) const
{
assert (!is_empty ());
@@ -98,14 +98,23 @@ SchedulerMap::remove_next (void)
m_list.erase (m_list.begin ());
}
Scheduler::EventKey
SchedulerMap::remove (Event const ev)
EventImpl *
SchedulerMap::remove (EventId id, Scheduler::EventKey *key)
{
assert (!is_empty ());
EventMapI i = get_from_event (ev);
EventKey key = (*i).first;
EventMapI i = get_from_event (id.get_event_impl ());
*key = i->first;
m_list.erase (i);
return key;
return i->second;
}
bool
SchedulerMap::is_valid (EventId id)
{
EventMapI i = get_from_event (id.get_event_impl ());
Scheduler::EventKey key = i->first;
return (key.m_time == id.get_time () &&
key.m_uid == id.get_uid ());
}

View File

@@ -29,25 +29,27 @@
namespace ns3 {
class EventImpl;
class SchedulerMap : public Scheduler {
public:
SchedulerMap ();
virtual ~SchedulerMap ();
virtual Event insert (Event event, Scheduler::EventKey key);
virtual EventId insert (EventImpl *event, Scheduler::EventKey key);
virtual bool is_empty (void) const;
virtual Event peek_next (void) const;
virtual EventImpl *peek_next (void) const;
virtual Scheduler::EventKey peek_next_key (void) const;
virtual void remove_next (void);
virtual Scheduler::EventKey remove (Event const ev);
virtual EventImpl *remove (EventId ev, Scheduler::EventKey *key);
virtual bool is_valid (EventId id);
private:
typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare> EventMap;
typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare>::iterator EventMapI;
typedef std::map<Scheduler::EventKey, Event, Scheduler::EventKeyCompare>::const_iterator EventMapCI;
void store_in_event (Event ev, EventMapI i) const;
EventMapI get_from_event (Event const ev) const;
typedef std::map<Scheduler::EventKey, EventImpl*, Scheduler::EventKeyCompare> EventMap;
typedef std::map<Scheduler::EventKey, EventImpl*, Scheduler::EventKeyCompare>::iterator EventMapI;
typedef std::map<Scheduler::EventKey, EventImpl*, Scheduler::EventKeyCompare>::const_iterator EventMapCI;
void store_in_event (EventImpl *ev, EventMapI i) const;
SchedulerMap::EventMapI get_from_event (EventImpl *ev) const;
EventMap m_list;
uint32_t m_uid;

View File

@@ -23,10 +23,12 @@
#define SCHEDULER_H
#include <stdint.h>
#include "event.h"
#include "event-id.h"
namespace ns3 {
class EventImpl;
class Scheduler {
public:
struct EventKey {
@@ -39,12 +41,13 @@ class Scheduler {
};
virtual ~Scheduler () = 0;
virtual Event insert (Event event, EventKey key) = 0;
virtual EventId insert (EventImpl *event, EventKey key) = 0;
virtual bool is_empty (void) const = 0;
virtual Event peek_next (void) const = 0;
virtual EventImpl *peek_next (void) const = 0;
virtual EventKey peek_next_key (void) const = 0;
virtual void remove_next (void) = 0;
virtual EventKey remove (Event const ev) = 0;
virtual EventImpl *remove (EventId id, EventKey *key) = 0;
virtual bool is_valid (EventId id) = 0;
};

View File

@@ -21,9 +21,7 @@
#include "simulator.h"
#include "scheduler.h"
#include "event.h"
#include "event.tcc"
#include "ns3/system-semaphore.h"
#include "event-impl.h"
#include <math.h>
#include <cassert>
@@ -57,24 +55,20 @@ public:
void enable_log_to (char const *filename);
bool is_finished (void) const;
uint64_t next_us (void) const;
Time next (void) const;
void stop (void);
void stop_at_us (uint64_t at);
Event schedule_rel_us (Event event, uint64_t delta);
Event schedule_rel_s (Event event, double delta);
Event schedule_abs_us (Event event, uint64_t time);
Event schedule_abs_s (Event event, double time);
Event remove (Event const ev);
void stop_at (Time time);
EventId schedule (Time time, EventImpl *event);
void remove (EventId ev);
void cancel (EventId ev);
bool is_expired (EventId ev);
void run (void);
uint64_t now_us (void);
double now_s (void);
void schedule_now (Event event);
void schedule_destroy (Event event);
Time now (void) const;
private:
void process_one_event (void);
typedef std::list<std::pair<Event,uint32_t> > Events;
typedef std::list<std::pair<EventImpl *,uint32_t> > Events;
Events m_destroy;
uint64_t m_stop_at;
bool m_stop;
@@ -103,10 +97,11 @@ SimulatorPrivate::SimulatorPrivate (Scheduler *events)
SimulatorPrivate::~SimulatorPrivate ()
{
while (!m_destroy.empty ()) {
Event ev = m_destroy.front ().first;
EventImpl *ev = m_destroy.front ().first;
m_destroy.pop_front ();
TRACE ("handle destroy " << ev);
ev ();
ev->invoke ();
delete ev;
}
delete m_events;
m_events = (Scheduler *)0xdeadbeaf;
@@ -123,7 +118,7 @@ SimulatorPrivate::enable_log_to (char const *filename)
void
SimulatorPrivate::process_one_event (void)
{
Event next_ev = m_events->peek_next ();
EventImpl *next_ev = m_events->peek_next ();
Scheduler::EventKey next_key = m_events->peek_next_key ();
m_events->remove_next ();
TRACE ("handle " << next_ev);
@@ -132,7 +127,8 @@ SimulatorPrivate::process_one_event (void)
if (m_log_enable) {
m_log << "e "<<next_key.m_uid << " " << next_key.m_time << std::endl;
}
next_ev ();
next_ev->invoke ();
delete next_ev;
}
bool
@@ -140,12 +136,12 @@ SimulatorPrivate::is_finished (void) const
{
return m_events->is_empty ();
}
uint64_t
SimulatorPrivate::next_us (void) const
Time
SimulatorPrivate::next (void) const
{
assert (!m_events->is_empty ());
Scheduler::EventKey next_key = m_events->peek_next_key ();
return next_key.m_time;
return AbsTimeUs (next_key.m_time);
}
@@ -153,7 +149,7 @@ void
SimulatorPrivate::run (void)
{
while (!m_events->is_empty () && !m_stop &&
(m_stop_at == 0 || m_stop_at > next_us ())) {
(m_stop_at == 0 || m_stop_at > next ().us ())) {
process_one_event ();
}
m_log.close ();
@@ -166,79 +162,67 @@ SimulatorPrivate::stop (void)
m_stop = true;
}
void
SimulatorPrivate::stop_at_us (uint64_t at)
SimulatorPrivate::stop_at (Time at)
{
m_stop_at = at;
m_stop_at = at.us ();
}
Event
SimulatorPrivate::schedule_rel_us (Event event, uint64_t delta)
EventId
SimulatorPrivate::schedule (Time time, EventImpl *event)
{
uint64_t current = now_us ();
return schedule_abs_us (event, current+delta);
}
Event
SimulatorPrivate::schedule_abs_us (Event event, uint64_t time)
{
assert (time >= now_us ());
Scheduler::EventKey key = {time, m_uid};
if (time.is_destroy ()) {
m_destroy.push_back (std::make_pair (event, m_uid));
if (m_log_enable) {
m_log << "id " << m_current_uid << " " << now ().us () << " "
<< m_uid << std::endl;
}
m_uid++;
//XXX
return EventId ();
}
assert (time.us () >= now ().us ());
Scheduler::EventKey key = {time.us (), m_uid};
if (m_log_enable) {
m_log << "i "<<m_current_uid<<" "<<now_us ()<<" "
<<m_uid<<" "<<time << std::endl;
m_log << "i "<<m_current_uid<<" "<<now ().us ()<<" "
<<m_uid<<" "<<time.us () << std::endl;
}
m_uid++;
return m_events->insert (event, key);
}
uint64_t
SimulatorPrivate::now_us (void)
Time
SimulatorPrivate::now (void) const
{
return m_current_us;
}
Event
SimulatorPrivate::schedule_rel_s (Event event, double delta)
{
int64_t delta_us = (int64_t)(delta * 1000000.0);
uint64_t us = now_us () + delta_us;
return schedule_abs_us (event, us);
}
Event
SimulatorPrivate::schedule_abs_s (Event event, double time)
{
int64_t us = (int64_t)(time * 1000000.0);
assert (us >= 0);
return schedule_abs_us (event, (uint64_t)us);
}
double
SimulatorPrivate::now_s (void)
{
double us = m_current_us;
us /= 1000000;
return us;
}
void
SimulatorPrivate::schedule_now (Event event)
{
schedule_abs_us (event, now_us ());
}
void
SimulatorPrivate::schedule_destroy (Event event)
{
m_destroy.push_back (std::make_pair (event, m_uid));
if (m_log_enable) {
m_log << "id " << m_current_uid << " " << now_us () << " "
<< m_uid << std::endl;
}
m_uid++;
return AbsTimeUs (m_current_us);
}
Event
SimulatorPrivate::remove (Event const ev)
void
SimulatorPrivate::remove (EventId ev)
{
Scheduler::EventKey key = m_events->remove (ev);
Scheduler::EventKey key;
EventImpl *impl = m_events->remove (ev, &key);
delete impl;
if (m_log_enable) {
m_log << "r " << m_current_uid << " " << now_us () << " "
m_log << "r " << m_current_uid << " " << now ().us () << " "
<< key.m_uid << " " << key.m_time << std::endl;
}
return Event (ev);
}
void
SimulatorPrivate::cancel (EventId id)
{
assert (m_events->is_valid (id));
EventImpl *ev = id.get_event_impl ();
ev->cancel ();
}
bool
SimulatorPrivate::is_expired (EventId ev)
{
if (ev.get_event_impl () != 0 &&
ev.get_time () <= now ().us () &&
ev.get_uid () < m_current_uid) {
return false;
}
return true;
}
@@ -312,10 +296,10 @@ Simulator::is_finished (void)
{
return get_priv ()->is_finished ();
}
uint64_t
Simulator::next_us (void)
Time
Simulator::next (void)
{
return get_priv ()->next_us ();
return get_priv ()->next ();
}
@@ -331,63 +315,39 @@ Simulator::stop (void)
get_priv ()->stop ();
}
void
Simulator::stop_at_us (uint64_t at)
Simulator::stop_at (Time at)
{
get_priv ()->stop_at_us (at);
get_priv ()->stop_at (at);
}
Event
Simulator::schedule_rel_us (uint64_t delta, Event event)
Time
Simulator::now (void)
{
TRACE ("insert " << event << " in " << delta << "us");
return get_priv ()->schedule_rel_us (event, delta);
}
Event
Simulator::schedule_abs_us (uint64_t time, Event event)
{
TRACE ("insert " << event << " at " << time << "us");
return get_priv ()->schedule_abs_us (event, time);
}
uint64_t
Simulator::now_us (void)
{
return get_priv ()->now_us ();
}
Event
Simulator::schedule_rel_s (double delta, Event event)
{
TRACE ("insert " << event << " in " << delta << "s");
return get_priv ()->schedule_rel_s (event, delta);
}
Event
Simulator::schedule_abs_s (double time, Event event)
{
TRACE ("insert " << event << " at " << time << "s");
return get_priv ()->schedule_abs_s (event, time);
}
double
Simulator::now_s (void)
{
return get_priv ()->now_s ();
}
void
Simulator::schedule_now (Event event)
{
TRACE ("insert later " << event);
return get_priv ()->schedule_now (event);
}
void
Simulator::schedule_destroy (Event event)
{
TRACE ("insert at destroy " << event);
return get_priv ()->schedule_destroy (event);
return get_priv ()->now ();
}
Event
Simulator::remove (Event const ev)
EventId
Simulator::schedule (Time time, EventImpl *ev)
{
return get_priv ()->schedule (time, ev);
}
void
Simulator::remove (EventId ev)
{
return get_priv ()->remove (ev);
}
void
Simulator::cancel (EventId ev)
{
return get_priv ()->cancel (ev);
}
bool
Simulator::is_expired (EventId id)
{
return get_priv ()->is_expired (id);
}
}; // namespace ns3

View File

@@ -23,10 +23,13 @@
#define SIMULATOR_H
#include <stdint.h>
#include "event.h"
#include "event-id.h"
#include "event-impl.h"
#include "time.h"
namespace ns3 {
class SimulatorPrivate;
/**
@@ -104,7 +107,7 @@ public:
* method is undefined. Otherwise, it returns the microsecond-based
* time of the next event expected to be scheduled.
*/
static uint64_t next_us (void);
static Time next (void);
/**
* Run the simulation until one of:
@@ -127,75 +130,100 @@ public:
* is greater than or equal to the stop time.
* @param at the stop time.
*/
static void stop_at_us (uint64_t at);
static void stop_at (Time time);
/**
* Schedule an event to expire at delta, relative to the
* current time.
* @param delta the expiration time relative to the current
* time. Expressed in microsecond units.
* Schedule an event to expire at time.
*
* @param delta the expiration time of the event.
* @param event the event to schedule.
* @returns an id for the scheduled event.
*/
static Event schedule_rel_us (uint64_t delta, Event event);
/**
* Schedule an event to expire at delta, relative to the
* current time.
* @param delta the expiration time, relative to the current
* time. Expressed in second units.
* @param event the event to schedule.
*/
static Event schedule_rel_s (double delta, Event event);
/**
* Schedule an event to expire at an absolute time.
* @param time the expiration time. Expressed in
* microsecond units.
* @param event the event to schedule.
*/
static Event schedule_abs_us (uint64_t time, Event event);
/**
* Schedule an event to expire at an absolute time.
* @param time the expiration time. Expressed in
* second units.
* @param event the event to schedule.
*/
static Event schedule_abs_s (double time, Event event);
template <typename T>
static EventId schedule (Time time, void (T::*mem_ptr) (void), T *obj) {
class EventMemberImpl0 : public EventImpl {
public:
typedef void (T::*F)(void);
EventMemberImpl0 (T *obj, F function)
: m_obj (obj),
m_function (function)
{}
virtual ~EventMemberImpl0 () {}
private:
virtual void notify (void) {
(m_obj->*m_function) ();
}
T* m_obj;
F m_function;
} *ev = new EventMemberImpl0 (obj, mem_ptr);
return schedule (time, ev);
}
static EventId schedule (Time time, void (*f) (void)) {
class EventFunctionImpl0 : public EventImpl {
public:
typedef void (*F)(void);
EventFunctionImpl0 (F function)
: m_function (function)
{}
protected:
virtual void notify (void) {
(*m_function) ();
}
private:
virtual ~EventFunctionImpl0 () {}
F m_function;
} *ev = new EventFunctionImpl0 (f);
return schedule (time, ev);
}
template <typename T1>
static EventId schedule (Time time, void (*f) (T1), T1 a1) {
class EventFunctionImpl1 : public EventImpl {
public:
typedef void (*F)(T1);
EventFunctionImpl1 (F function, T1 a1)
: m_function (function),
m_a1 (a1)
{ }
protected:
virtual ~EventFunctionImpl1 () {}
private:
virtual void notify (void) {
(*m_function) (m_a1);
}
F m_function;
T1 m_a1;
} *ev = new EventFunctionImpl1(f, a1);
return schedule (time, ev);
}
/**
* Unschedule the event. i.e.: the removed event never expires.
* @param id the event to remove from the list of scheduled events.
*/
static Event remove (Event const id);
/**
* Return the "current time" in microsecond units.
static void remove (EventId id);
/*
XXX
*/
static uint64_t now_us (void);
/**
* Return the "current time" in second units.
static void cancel (EventId id);
/*
XXX
*/
static double now_s (void);
static bool is_expired (EventId id);
/**
* Schedule an event to expire right now. i.e., it will
* expire after the currently-executing event is executed.
* If multiple events are scheduled with this method,
* they are executed in FIFO order: the events scheduled first
* are executed first.
* @param event the event to schedule now.
* Return the "current time".
*/
static void schedule_now (Event event);
/**
* Schedule an event to expire when the Simulator::destroy method
* is invoked. Events are executed in FIFO order: the events
* scheduled first are executed first.
* @param event the event to schedule.
*/
static void schedule_destroy (Event event);
static Time now (void);
private:
Simulator ();
~Simulator ();
static SimulatorPrivate *get_priv (void);
static EventId schedule (Time time, EventImpl *event);
static SimulatorPrivate *m_priv;
static enum ListType {
LINKED_LIST,
BINARY_HEAP,
STD_MAP
} m_list_type;
};

99
src/simulator/time.cc Normal file
View File

@@ -0,0 +1,99 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "time.h"
#include "simulator.h"
namespace ns3 {
Time::Time ()
: m_us (0),
m_is_destroy (true)
{}
Time::Time (Time const &o)
: m_us (o.m_us),
m_is_destroy (o.m_is_destroy)
{}
Time &
Time::operator = (Time const &o)
{
m_us = o.m_us;
m_is_destroy = o.m_is_destroy;
return *this;
}
Time::Time (uint64_t us)
: m_us (us),
m_is_destroy (false)
{}
double
Time::s (void) const
{
double us = m_us;
us /= 1000000;
return us;
}
uint64_t
Time::us (void) const
{
return m_us;
}
bool
Time::is_destroy (void) const
{
return m_is_destroy;
}
Time
operator + (Time const &lhs, uint64_t delta_us)
{
return AbsTimeUs (lhs.us () + delta_us);
}
Time
operator + (Time const &lhs, double delta_s)
{
uint64_t delta_us = (uint64_t)(int64_t)(delta_s * 1000000.0);
return AbsTimeUs (lhs.us () + delta_us);
}
AbsTimeS::AbsTimeS (double s)
: Time ((uint64_t)(int64_t)(s * 1000000.0))
{}
AbsTimeUs::AbsTimeUs (uint64_t us)
: Time (us)
{}
RelTimeS::RelTimeS (double s)
: Time (Simulator::now () + s)
{}
RelTimeUs::RelTimeUs (uint64_t us)
: Time (Simulator::now () + us)
{}
NowTime::NowTime ()
: Time (Simulator::now ().us ())
{}
DestroyTime::DestroyTime ()
: Time ()
{}
}; // namespace ns3

76
src/simulator/time.h Normal file
View File

@@ -0,0 +1,76 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TIME_H
#define TIME_H
#include <stdint.h>
namespace ns3 {
class Time {
public:
Time (Time const &o);
Time &operator = (Time const &o);
double s (void) const;
uint64_t us (void) const;
bool is_destroy (void) const;
protected:
Time (uint64_t us);
Time ();
private:
uint64_t m_us;
bool m_is_destroy;
};
Time operator + (Time const &lhs, uint64_t delta);
Time operator + (Time const &lhs, double delta);
class AbsTimeS : public Time {
public:
AbsTimeS (double s);
};
class AbsTimeUs : public Time {
public:
AbsTimeUs (uint64_t us);
};
class RelTimeS : public Time {
public:
RelTimeS (double s);
};
class RelTimeUs : public Time {
public:
RelTimeUs (uint64_t us);
};
class NowTime : public Time {
public:
NowTime ();
};
class DestroyTime : public Time {
public:
DestroyTime ();
};
}; // namespace ns3
#endif /* TIME_H */

View File

@@ -20,8 +20,6 @@
*/
#include "ns3/simulator.h"
#include "ns3/event.h"
#include "ns3/event.tcc"
#include "ns3/wall-clock-ms.h"
#include <iostream>
#include <fstream>
@@ -75,7 +73,7 @@ Bench::bench (void)
time.start ();
for (std::vector<uint64_t>::const_iterator i = m_distribution.begin ();
i != m_distribution.end (); i++) {
Simulator::schedule_rel_us (*i, make_event (&Bench::cb, this));
Simulator::schedule (AbsTimeUs (*i), &Bench::cb, this);
}
init = time.end ();
@@ -105,9 +103,9 @@ Bench::cb (void)
m_current = m_distribution.begin ();
}
if (g_debug) {
std::cerr << "event at " << Simulator::now_s () << std::endl;
std::cerr << "event at " << Simulator::now ().s () << std::endl;
}
Simulator::schedule_rel_us (*m_current, make_event (&Bench::cb, this));
Simulator::schedule (AbsTimeUs (*m_current), &Bench::cb, this);
m_current++;
m_n++;
}