386 lines
7.0 KiB
C++
386 lines
7.0 KiB
C++
/* -*- 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 "simulator.h"
|
|
#include "scheduler.h"
|
|
#include "event-impl.h"
|
|
|
|
#include <math.h>
|
|
#include <cassert>
|
|
#include <fstream>
|
|
#include <list>
|
|
#include <vector>
|
|
#include <iostream>
|
|
|
|
#define noTRACE_SIMU 1
|
|
|
|
#ifdef TRACE_SIMU
|
|
#include <iostream>
|
|
# define TRACE(x) \
|
|
std::cout << "SIMU TRACE " << Simulator::now_s () << " " << x << std::endl;
|
|
# define TRACE_S(x) \
|
|
std::cout << "SIMU TRACE " << x << std::endl;
|
|
#else /* TRACE_SIMU */
|
|
# define TRACE(format,...)
|
|
# define TRACE_S(format,...)
|
|
#endif /* TRACE_SIMU */
|
|
|
|
|
|
namespace ns3 {
|
|
|
|
|
|
class SimulatorPrivate {
|
|
public:
|
|
SimulatorPrivate (Scheduler *events);
|
|
~SimulatorPrivate ();
|
|
|
|
void enable_log_to (char const *filename);
|
|
|
|
bool is_finished (void) const;
|
|
Time next (void) const;
|
|
void stop (void);
|
|
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);
|
|
Time now (void) const;
|
|
|
|
private:
|
|
void process_one_event (void);
|
|
|
|
typedef std::list<std::pair<EventImpl *,uint32_t> > Events;
|
|
Events m_destroy;
|
|
uint64_t m_stop_at;
|
|
bool m_stop;
|
|
Scheduler *m_events;
|
|
uint32_t m_uid;
|
|
uint32_t m_current_uid;
|
|
uint64_t m_current_us;
|
|
std::ofstream m_log;
|
|
std::ifstream m_input_log;
|
|
bool m_log_enable;
|
|
};
|
|
|
|
|
|
|
|
|
|
SimulatorPrivate::SimulatorPrivate (Scheduler *events)
|
|
{
|
|
m_stop = false;
|
|
m_stop_at = 0;
|
|
m_events = events;
|
|
m_uid = 0;
|
|
m_log_enable = false;
|
|
m_current_us = 0;
|
|
}
|
|
|
|
SimulatorPrivate::~SimulatorPrivate ()
|
|
{
|
|
while (!m_destroy.empty ()) {
|
|
EventImpl *ev = m_destroy.front ().first;
|
|
m_destroy.pop_front ();
|
|
TRACE ("handle destroy " << ev);
|
|
ev->invoke ();
|
|
delete ev;
|
|
}
|
|
delete m_events;
|
|
m_events = (Scheduler *)0xdeadbeaf;
|
|
}
|
|
|
|
|
|
void
|
|
SimulatorPrivate::enable_log_to (char const *filename)
|
|
{
|
|
m_log.open (filename);
|
|
m_log_enable = true;
|
|
}
|
|
|
|
void
|
|
SimulatorPrivate::process_one_event (void)
|
|
{
|
|
EventImpl *next_ev = m_events->peek_next ();
|
|
Scheduler::EventKey next_key = m_events->peek_next_key ();
|
|
m_events->remove_next ();
|
|
TRACE ("handle " << next_ev);
|
|
m_current_us = next_key.m_time;
|
|
m_current_uid = next_key.m_uid;
|
|
if (m_log_enable) {
|
|
m_log << "e "<<next_key.m_uid << " " << next_key.m_time << std::endl;
|
|
}
|
|
next_ev->invoke ();
|
|
delete next_ev;
|
|
}
|
|
|
|
bool
|
|
SimulatorPrivate::is_finished (void) const
|
|
{
|
|
return m_events->is_empty ();
|
|
}
|
|
Time
|
|
SimulatorPrivate::next (void) const
|
|
{
|
|
assert (!m_events->is_empty ());
|
|
Scheduler::EventKey next_key = m_events->peek_next_key ();
|
|
return AbsTimeUs (next_key.m_time);
|
|
}
|
|
|
|
|
|
void
|
|
SimulatorPrivate::run (void)
|
|
{
|
|
while (!m_events->is_empty () && !m_stop &&
|
|
(m_stop_at == 0 || m_stop_at > next ().us ())) {
|
|
process_one_event ();
|
|
}
|
|
m_log.close ();
|
|
}
|
|
|
|
|
|
void
|
|
SimulatorPrivate::stop (void)
|
|
{
|
|
m_stop = true;
|
|
}
|
|
void
|
|
SimulatorPrivate::stop_at (Time at)
|
|
{
|
|
m_stop_at = at.us ();
|
|
}
|
|
EventId
|
|
SimulatorPrivate::schedule (Time time, EventImpl *event)
|
|
{
|
|
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.us () << std::endl;
|
|
}
|
|
m_uid++;
|
|
return m_events->insert (event, key);
|
|
}
|
|
Time
|
|
SimulatorPrivate::now (void) const
|
|
{
|
|
return AbsTimeUs (m_current_us);
|
|
}
|
|
|
|
void
|
|
SimulatorPrivate::remove (EventId 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 () << " "
|
|
<< key.m_uid << " " << key.m_time << std::endl;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
}; // namespace ns3
|
|
|
|
|
|
#include "scheduler-list.h"
|
|
#include "scheduler-heap.h"
|
|
#include "scheduler-map.h"
|
|
|
|
|
|
namespace ns3 {
|
|
|
|
SimulatorPrivate *Simulator::m_priv = 0;
|
|
Simulator::ListType Simulator::m_list_type = LINKED_LIST;
|
|
|
|
void Simulator::set_linked_list (void)
|
|
{
|
|
m_list_type = LINKED_LIST;
|
|
}
|
|
void Simulator::set_binary_heap (void)
|
|
{
|
|
m_list_type = BINARY_HEAP;
|
|
}
|
|
void Simulator::set_std_map (void)
|
|
{
|
|
m_list_type = STD_MAP;
|
|
}
|
|
void Simulator::enable_log_to (char const *filename)
|
|
{
|
|
get_priv ()->enable_log_to (filename);
|
|
}
|
|
|
|
|
|
SimulatorPrivate *
|
|
Simulator::get_priv (void)
|
|
{
|
|
if (m_priv == 0) {
|
|
Scheduler *events;
|
|
switch (m_list_type) {
|
|
case LINKED_LIST:
|
|
events = new SchedulerList ();
|
|
break;
|
|
case BINARY_HEAP:
|
|
events = new SchedulerHeap ();
|
|
break;
|
|
case STD_MAP:
|
|
events = new SchedulerMap ();
|
|
break;
|
|
default: // not reached
|
|
events = 0;
|
|
assert (false);
|
|
break;
|
|
}
|
|
m_priv = new SimulatorPrivate (events);
|
|
}
|
|
TRACE_S ("priv " << m_priv);
|
|
return m_priv;
|
|
}
|
|
|
|
void
|
|
Simulator::destroy (void)
|
|
{
|
|
delete m_priv;
|
|
m_priv = 0;
|
|
}
|
|
|
|
|
|
bool
|
|
Simulator::is_finished (void)
|
|
{
|
|
return get_priv ()->is_finished ();
|
|
}
|
|
Time
|
|
Simulator::next (void)
|
|
{
|
|
return get_priv ()->next ();
|
|
}
|
|
|
|
|
|
void
|
|
Simulator::run (void)
|
|
{
|
|
get_priv ()->run ();
|
|
}
|
|
void
|
|
Simulator::stop (void)
|
|
{
|
|
TRACE ("stop");
|
|
get_priv ()->stop ();
|
|
}
|
|
void
|
|
Simulator::stop_at (Time at)
|
|
{
|
|
get_priv ()->stop_at (at);
|
|
}
|
|
Time
|
|
Simulator::now (void)
|
|
{
|
|
return get_priv ()->now ();
|
|
}
|
|
|
|
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
|
|
|
|
|
|
#ifdef RUN_SELF_TESTS
|
|
|
|
#include "ns3/test.h"
|
|
|
|
namespace ns3 {
|
|
|
|
class SimulatorTests : public Test {
|
|
public:
|
|
SimulatorTests ();
|
|
virtual ~SimulatorTests ();
|
|
virtual bool run_tests (void);
|
|
};
|
|
|
|
SimulatorTests::SimulatorTests ()
|
|
: Test ("Simulator")
|
|
{}
|
|
SimulatorTests::~SimulatorTests ()
|
|
{}
|
|
bool
|
|
SimulatorTests::run_tests (void)
|
|
{
|
|
bool ok = true;
|
|
return ok;
|
|
}
|
|
|
|
SimulatorTests g_simulator_tests;
|
|
|
|
}; // namespace ns3
|
|
|
|
#endif /* RUN_SELF_TESTS */
|
|
|
|
|