From 02fa792b81711f294f87fb7d5fc42f930a7da883 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sun, 3 Sep 2006 12:24:04 +0200 Subject: [PATCH] first cut at george's ideas on api --- SConstruct | 18 +- samples/main-event.cc | 42 -- samples/main-simulator.cc | 19 +- src/common/pcap-writer.cc | 2 +- src/common/static-speed-position.cc | 2 +- src/simulator/event-id.cc | 64 +++ src/simulator/{event-tcc.cc => event-id.h} | 43 +- src/simulator/event-impl.cc | 25 +- src/simulator/event-impl.h | 11 +- src/simulator/event-tcc-test.cc | 110 ----- src/simulator/event.h | 140 ------- src/simulator/event.tcc | 454 --------------------- src/simulator/scheduler-heap.cc | 55 +-- src/simulator/scheduler-heap.h | 14 +- src/simulator/scheduler-list.cc | 62 +-- src/simulator/scheduler-list.h | 19 +- src/simulator/scheduler-map.cc | 37 +- src/simulator/scheduler-map.h | 20 +- src/simulator/scheduler.h | 11 +- src/simulator/simulator.cc | 224 +++++----- src/simulator/simulator.h | 130 +++--- src/simulator/time.cc | 99 +++++ src/simulator/time.h | 76 ++++ utils/bench-simulator.cc | 8 +- 24 files changed, 591 insertions(+), 1094 deletions(-) delete mode 100644 samples/main-event.cc create mode 100644 src/simulator/event-id.cc rename src/simulator/{event-tcc.cc => event-id.h} (61%) delete mode 100644 src/simulator/event-tcc-test.cc delete mode 100644 src/simulator/event.h delete mode 100644 src/simulator/event.tcc create mode 100644 src/simulator/time.cc create mode 100644 src/simulator/time.h diff --git a/SConstruct b/SConstruct index 32a04de7d..ce14e2fc9 100644 --- a/SConstruct +++ b/SConstruct @@ -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') diff --git a/samples/main-event.cc b/samples/main-event.cc deleted file mode 100644 index 02b5da4e5..000000000 --- a/samples/main-event.cc +++ /dev/null @@ -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 - -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 (); -} diff --git a/samples/main-simulator.cc b/samples/main-simulator.cc index 720484aa5..09747ce02 100644 --- a/samples/main-simulator.cc +++ b/samples/main-simulator.cc @@ -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 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 (); diff --git a/src/common/pcap-writer.cc b/src/common/pcap-writer.cc index 5333ce7fd..0babe1c3c 100644 --- a/src/common/pcap-writer.cc +++ b/src/common/pcap-writer.cc @@ -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); diff --git a/src/common/static-speed-position.cc b/src/common/static-speed-position.cc index d4db5e07b..c1c16123c 100644 --- a/src/common/static-speed-position.cc +++ b/src/common/static-speed-position.cc @@ -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; diff --git a/src/simulator/event-id.cc b/src/simulator/event-id.cc new file mode 100644 index 000000000..45a5e182a --- /dev/null +++ b/src/simulator/event-id.cc @@ -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 + */ +#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 diff --git a/src/simulator/event-tcc.cc b/src/simulator/event-id.h similarity index 61% rename from src/simulator/event-tcc.cc rename to src/simulator/event-id.h index 4be0c6b46..aa689d133 100644 --- a/src/simulator/event-tcc.cc +++ b/src/simulator/event-id.h @@ -18,30 +18,35 @@ * * Author: Mathieu Lacage */ -#include "event-impl.h" -#include "event.h" +#ifndef EVENT_ID_H +#define EVENT_ID_H + +#include 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 */ diff --git a/src/simulator/event-impl.cc b/src/simulator/event-impl.cc index e390ce151..241b1692d 100644 --- a/src/simulator/event-impl.cc +++ b/src/simulator/event-impl.cc @@ -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 diff --git a/src/simulator/event-impl.h b/src/simulator/event-impl.h index af2e9196a..c2f75bc2f 100644 --- a/src/simulator/event-impl.h +++ b/src/simulator/event-impl.h @@ -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 diff --git a/src/simulator/event-tcc-test.cc b/src/simulator/event-tcc-test.cc deleted file mode 100644 index 9a13a0cd6..000000000 --- a/src/simulator/event-tcc-test.cc +++ /dev/null @@ -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 - */ -#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 */ diff --git a/src/simulator/event.h b/src/simulator/event.h deleted file mode 100644 index ab0639257..000000000 --- a/src/simulator/event.h +++ /dev/null @@ -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 - */ - -#ifndef EVENT_H -#define EVENT_H - -#include -#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 */ diff --git a/src/simulator/event.tcc b/src/simulator/event.tcc deleted file mode 100644 index 2f8a30261..000000000 --- a/src/simulator/event.tcc +++ /dev/null @@ -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 - */ - -#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 -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 -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 -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 -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 -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 -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 -Event make_event(void (T::*f) (void), T* t) { - return Event (new EventMemberImpl0(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 -Event make_event(void (T::*f) (T1), T* t, T1 a1) { - return Event (new EventMemberImpl1(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 -Event make_event(void (T::*f) (T1, T2), T* t, T1 a1, T2 a2) { - return Event (new EventMemberImpl2(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 -Event make_event(void (T::*f) (T1, T2, T3), T* t, T1 a1, T2 a2, T3 a3) { - return Event (new EventMemberImpl3(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 -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, 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 -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, f, a1, a2, a3, a4, a5)); -} - -template -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 -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 -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 -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 -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 -Event make_event(void (*f) (T1), T1 a1) { - return Event (new EventFunctionImpl1(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 -Event make_event(void (*f) (T1, T2), T1 a1, T2 a2) { - return Event (new EventFunctionImpl2(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 -Event make_event(void (*f) (T1, T2, T3), T1 a1, T2 a2, T3 a3) { - return Event (new EventFunctionImpl3(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 -Event make_event(void (*f) (T1, T2, T3, T4), T1 a1, T2 a2, T3 a3, T4 a4) { - return Event (new EventFunctionImpl4(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 -Event make_event(void (*f) (T1, T2, T3, T4, T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { - return Event (new EventFunctionImpl5(f, a1, a2, a3, a4, a5)); -} - - -}; // namespace ns3 - -#endif /* EVENT_TCC */ diff --git a/src/simulator/scheduler-heap.cc b/src/simulator/scheduler-heap.cc index c5628fc9f..46dd4982a 100644 --- a/src/simulator/scheduler-heap.cc +++ b/src/simulator/scheduler-heap.cc @@ -33,7 +33,7 @@ */ #include "scheduler-heap.h" -#include "event.h" +#include "event-impl.h" #include #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(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 tmp (m_heap[a]); + std::pair 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 diff --git a/src/simulator/scheduler-heap.h b/src/simulator/scheduler-heap.h index e56854d12..909957cd5 100644 --- a/src/simulator/scheduler-heap.h +++ b/src/simulator/scheduler-heap.h @@ -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 > BinaryHeap; - inline void store_in_event (Event ev, uint32_t index) const; - uint32_t get_from_event (Event const ev) const; + typedef std::vector > 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; diff --git a/src/simulator/scheduler-list.cc b/src/simulator/scheduler-list.cc index 767b71dc0..ff4ab8465 100644 --- a/src/simulator/scheduler-list.cc +++ b/src/simulator/scheduler-list.cc @@ -20,7 +20,7 @@ */ #include "scheduler-list.h" -#include "event.h" +#include "event-impl.h" #include #include @@ -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 diff --git a/src/simulator/scheduler-list.h b/src/simulator/scheduler-list.h index d316674d8..714ac4f4c 100644 --- a/src/simulator/scheduler-list.h +++ b/src/simulator/scheduler-list.h @@ -23,31 +23,32 @@ #define SCHEDULER_LIST_H #include "scheduler.h" +#include "event-id.h" #include #include #include 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 > Events; - typedef std::list >::iterator EventsI; - void store_in_event (Event ev, EventsI i); - EventsI get_from_event (Event const ev); + typedef std::list > Events; + typedef std::list >::iterator EventsI; + EventId get_event_id (Scheduler::EventKey key, EventsI i); + EventsI get_iterator (EventId id); Events m_events; }; diff --git a/src/simulator/scheduler-map.cc b/src/simulator/scheduler-map.cc index 630006cb8..ebd2ce30c 100644 --- a/src/simulator/scheduler-map.cc +++ b/src/simulator/scheduler-map.cc @@ -21,7 +21,7 @@ */ #include "scheduler-map.h" -#include "event.h" +#include "event-impl.h" #include #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 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 ()); } diff --git a/src/simulator/scheduler-map.h b/src/simulator/scheduler-map.h index 931b9e562..583839fab 100644 --- a/src/simulator/scheduler-map.h +++ b/src/simulator/scheduler-map.h @@ -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 EventMap; - typedef std::map::iterator EventMapI; - typedef std::map::const_iterator EventMapCI; - - void store_in_event (Event ev, EventMapI i) const; - EventMapI get_from_event (Event const ev) const; + typedef std::map EventMap; + typedef std::map::iterator EventMapI; + typedef std::map::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; diff --git a/src/simulator/scheduler.h b/src/simulator/scheduler.h index d43839268..17440ea06 100644 --- a/src/simulator/scheduler.h +++ b/src/simulator/scheduler.h @@ -23,10 +23,12 @@ #define SCHEDULER_H #include -#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; }; diff --git a/src/simulator/simulator.cc b/src/simulator/simulator.cc index c79f24670..382ee5635 100644 --- a/src/simulator/simulator.cc +++ b/src/simulator/simulator.cc @@ -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 #include @@ -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 > Events; + typedef std::list > 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 "<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 "<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 diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h index f89a15ffd..1fe2db8dd 100644 --- a/src/simulator/simulator.h +++ b/src/simulator/simulator.h @@ -23,10 +23,13 @@ #define SIMULATOR_H #include -#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 + 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 + 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; }; diff --git a/src/simulator/time.cc b/src/simulator/time.cc new file mode 100644 index 000000000..8763f47f9 --- /dev/null +++ b/src/simulator/time.cc @@ -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 + */ +#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 diff --git a/src/simulator/time.h b/src/simulator/time.h new file mode 100644 index 000000000..2b9b8c6a0 --- /dev/null +++ b/src/simulator/time.h @@ -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 + */ +#ifndef TIME_H +#define TIME_H + +#include + +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 */ diff --git a/utils/bench-simulator.cc b/utils/bench-simulator.cc index f5f39f7d6..a575cd57c 100644 --- a/utils/bench-simulator.cc +++ b/utils/bench-simulator.cc @@ -20,8 +20,6 @@ */ #include "ns3/simulator.h" -#include "ns3/event.h" -#include "ns3/event.tcc" #include "ns3/wall-clock-ms.h" #include #include @@ -75,7 +73,7 @@ Bench::bench (void) time.start (); for (std::vector::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++; }