[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 Bound Callbacks

A very useful extension to the functor concept is that of a Bound Callback. Previously it was mentioned that closures were originally function calls packaged up for later execution. Notice that in all of the Callback descriptions above, there is no way to package up any parameters for use later – when the Callback is called via operator(). All of the parameters are provided by the calling function.

What if it is desired to allow the client function (the one that provides the callback) to provide some of the parameters? Alexandrescu calls the process of allowing a client to specify one of the parameters binding. One of the parameters of operator() has been bound (fixed) by the client.

Some of our pcap tracing code provides a nice example of this. There is a function that needs to be called whenever a packet is received. This function calls an object that actually writes the packet to disk in the pcap file format. The signature of one of these functions will be,

  static void SniffEvent (Ptr<PcapWriter> writer, Ptr<const Packet> packet);

The static keyword means this is a static function which does not need a this pointer, so it will be using C-style callbacks. We don’t want the calling code to have to know about anything but the Packet. What we want there is just a call that looks like,

  m_promiscSnifferTrace (m_currentPkt);

What we want to do is to bind the Ptr<PcapWriter> writer to the specific callback implementation when it is created and arrange for the operator() of the Callback to provide that parameter for free.

We provide the MakeBoundCallback template function for that purpose. It takes the same parameters as the MakeCallback template function but also takes the parameters to be bound. In the case of the example above,

    MakeBoundCallback (&CsmaHelper::SniffEvent, pcap));

will create a specific callback implementation that knows to add in the extra bound arguments. Conceptually, it extends the specific functor described above with one or more bound arguments

  template <typename T, typename ARG, typename BOUND_ARG>
  class SpecificFunctor : public Functor
   {
   public:
      SpecificFunctor(T* p, int (T::*_pmi)(ARG arg), BOUND_ARG boundArg)
      {
        m_p = p;
        m_pmi = pmi;
        m_boundArg = boundArg;
      }

      virtual int operator() (ARG arg)
      {
        (*m_p.*m_pmi)(m_boundArg, arg);
      }
  private:
      void (T::*m_pmi)(ARG arg);
      T* m_p;
      BOUND_ARG m_boundArg;
   };

You can see that when the specific functor is created, the bound argument is saved in the functor / callback object itself. When the operator() is invoked with the single parameter, as in

  m_promiscSnifferTrace (m_currentPkt);

the implementation of operator() adds the bound parameter into the actual function call:

  (*m_p.*m_pmi)(m_boundArg, arg);

[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated on April 21, 2010 using texi2html 1.82.