Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion On callbacks
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
crai...@ee.washington.edu  
View profile  
 More options Sep 10 2009, 5:10 pm
From: <crai...@ee.washington.edu>
Date: Thu, 10 Sep 2009 14:10:37 -0700
Local: Thurs, Sep 10 2009 5:10 pm
Subject: RE: On callbacks

> I am a bit confused about the use of callbacks.
> in particular, in the example named 'tcp-large-transfer.cc', there's a
> function called 'CwndTracer':

> static void
> CwndTracer (uint32_t oldval, uint32_t newval)
> {
>   NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
> }

> Simply, I don't get where the two parameters are taken from.
> Please forgive me if it is a silly question, but how can I find out
> that CwndTracer takes exactly two uint32_t parameters?

It's not a silly question at all.  The implementation is non-trivial.
Fortunately, you only have to figure this out once.  It may be easier to
just accept that when you trace a plain-old data type, you need to define a
function that receives the old and the new value.  i.e., don't ask :-)

Here are the internals.  Look at the connect to begin putting the pieces
together.

  Config::ConnectWithoutContext (
    "/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
    MakeCallback (&CwndTracer));

Then take a look at the path string, reading backward.  The last part of the
path is the attribute defining the trace source.  Probably the easiest thing
to do to get your bearings is just recursively grep for this Attribute name.

  find . -name '*.cc' | xargs grep CongestionWindow

You will see,

  ./src/internet-stack/nsc-tcp-socket-impl.cc:    .AddTraceSource
("CongestionWindow",
  ./src/internet-stack/tcp-socket-impl.cc:    .AddTraceSource
("CongestionWindow",

It's the AddTraceSource call that you are interested in.  If you are using
the standard ns-3 TCP, you would look in the file
internet-stack/tcp-socket-impl.cc to go further.  You need to identify the
trace source.  Look in this file for the .AddTraceSource you see in the grep
results.  You will see,

    .AddTraceSource ("CongestionWindow",
                     "The TCP connection's congestion window",
                     MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))

Look at the MakeTraceSourceAccessor call and find that the actual traced
variable is

  TcpSocketImpl::m_cWnd

Now, go and look in tcp-socket-impl.h for the declaration of this variable.
This is a

 TracedValue<uint32_t>

Unless you know where this is defined you are probably stuck here.  Again,
grep is your friend.  Nothing interesting will show up in '*.cc' so try
'*.h'

If you do this you will find lots and lots of hits in ./core/traced-value.h
which is the next place you need to look.

You will find that the way these things work is to overload the operators
that cause the value to be changed.  So you look for the = operator.  If you
look there,

  TracedValue &operator = (const TracedValue &o) {
    TRACED_VALUE_DEBUG ("x=");
    Set (o.m_v);
    return *this;
  }

You will find a call to Set().  There you will find:

  void Set (const T &v) {
    if (m_v != v)
      {
        m_cb (m_v, v);
        m_v = v;
      }
  }

One thing to point out is that the trace hook will only be called if the new
value is different than the old value.  This sometimes surprises people.

Anyway, the variable v is the new value and m_v is the existing (old) value,
Notice the line,

  m_cb (m_v, v);

This is the callback that is hit when you make the change to the variable by
doing m_variable = something.

In the TracedValue class you can find,

private:
  T m_v;
  TracedCallback<T,T> m_cb;

So, in the case of TracedValue<uint32_t>, the T becomes int32_t and you have

  int32_t v
  int32_t m_v

So m_cb is calling (via an overloaded operator () ) a method that takes two
uint32_t, the first parameter is the existing (old) value and the second is
the new value.

So,

  MakeCallback (&CwndTracer)

Needs to hook a function that takes two uint32_t, the first being the old
value and the second being the new value;  which it does:

  void CwndTracer (uint32_t oldval, uint32_t newval);

Non trivial, but now you know how all TracedValue work since it is
templated.

Regards,

-- Craig


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.