[Ns-developers] NS-3 GUI (visualization again)

Gustavo Carneiro gjcarneiro at gmail.com
Wed Jul 30 04:25:19 PDT 2008


2008/7/30 <craigdo at ee.washington.edu>

> [ ... ]
>
> > > RunOne what?  RunOne when?  In what context?
> >
> > Run one event from the event queue and return immediately. Gustavo
> > suggested adding a bool return value to return whether or not further
> > events are left in the queue. A trivial sample implementation:
> >
> > bool
> > DefaultSimulatorImpl::RunOne (void)
> > {
> >   if (!m_events->IsEmpty ())
> >     {
> >       ProcessOneEvent ();
> >     }
> >
> >   NS_ASSERT(!m_events->IsEmpty () || m_unscheduledEvents == 0);
> >
> >   return !m_events->IsEmpty ();
> > }
> >
> >
> > I thought that the context in which this function would be
> > used would be
> > obvious: it could be used to move the mainloop from ns3 to the
> > application to allow the application to decide when and how to execute
> > events.
>
> Well, not obvious to me, but I haven't been having this conversation with
> Gustavo and I'm coming from an entirely different place.  In any case, now
> I
> can answer your question about emu.
>
> This approach is funamentally incompatible with a realtime scheduler unless
> you want to move basically the whole multithreaded interruptible-wait
> realtime-synchronizer thing up into the GUI application.  Realtime GUI.
> Yeah-baby :-)
>
> But it does represent something that can be optional and implemented
> differently in different simulator implementations.  In the default
> simulator implementation, it makes sense to do something as you show above.
> In a realtime scheduler, it would be implemented as,
>
>  bool
>  DefaultSimulatorImpl::RunOne (void)
>  {
>    NS_ASSERT_MSG(false, "No, you really don't want to do that");
>    return false;
>  }
>
>
I thought you said there is a single simulation thread that dispatches
events, although multiple threads can schedule events.  Presumably
(guessing) the simulation thread is the one that calls Simulator::Run.  In
that case, wouldn't it make sense to allow multiple RunOne calls to replace
a single Run call?  Something like:

void MySimulatorRun ()
{
    while (!Simulator::IsFinished ())
   {
      Simulator::Lock ();
      Simulator::RunOne ();
      Simulator::UnLock ();
   }
}

I would expect the above to work and make sense even for the threaded
simulator.  It's all about documentation.  No need to assert in
Simulator::RunOne, just put in the documentation that you must hold the
simulator lock before calling it.

Back to my GUI problem, the naive approach that I had in mind was:

Mutext g_myMutex;

void MySimulatorRun ()
{
    while (!Simulator::IsFinished ())
   {
      g_myMutex.Lock ();
      Simulator::RunOne ();
      g_myMutex.Unlock ();
   }
}

// called every 100ms or so
void GuiUpdateTimeout ()
{
      g_myMutex.Lock ();
      // collect data, update display
      g_myMutex.Unlock ();
}

Now, the above approach is kind of naive because it does a lock/unlock pair
for _every event_, which is bound to have some performance implication.   A
more clever approach is to unlock-then-lock only once out of N events.  N
should be selected such that lock/unlock is done only about once every ~
10ms.  The hard part is to figure out what is the correct N for that.  I
think it depends on the simulation, and N cannot even be constant, so it has
to be discovered adaptively, by measuring elapsed time for any previous N
iterations and adjusting N accordingly.

-- 
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert


More information about the Ns-developers mailing list