Boost logo

Boost Users :

Subject: [Boost-users] multiple levels of bind nesting
From: Zachary Turner (divisortheory_at_[hidden])
Date: 2009-07-22 12:29:30


I have some code that implements an asynchronous worker model where a
client calls some function to request an asynchronous operation and
passes a callback function, whose type is determined by a template
parameter. e.g.

class worker
{
    template<class Handler>
    void async_do_work(Handler h)
    {
       ...
    }
};

class client
{
   void start_work();
   void work_finished(boost::system::error_code ec, size_t bytes_transferred);
};

However there are many classes implementing async_do_work but which do
the work in a different way. For this I use a boost::variant<A&, B&,
...> for each type and use a boost::static_visitor to delegate to the
appropriate async_do_work method. This uses code such as the
following:

void client::start_work()
{
   apply_visitor(
       bind(do_work_visitor(), _1,
           protect(bind(&client::work_finished, this, _1, _2)))
       , work_variant_);
}

So from async_do_work's point of view, it receives a function with 2
arguments.

How async_do_work operates internally should be separated from the
client. It may not even use another thread, or it may combine the
efforts of multiple threads to achieve the result. So because of
that, I want async_do_work to intercept the callback before it gets
posted back to the original caller. To do this, I tried the
following in the implementation of worker:

class worker
{
public:
    template<class Handler>
    void async_do_work(Handler h)
    {
       //impl supports the same basic interface as worker

       impl->async_do_work(
          bind(&worker::intercept_handler<Handler>, this, h, _1, _2));
    }

private:
   template<class Handler>
   void intercept_handler(Handler real_handler,
boost::system::error_code ec, size_t bytes_transferred)
   {
      //do whatever is necessary and then call the real handler.

      real_handler(ec, bytes_transferred);
   }
};

However this doesn't work. I've also tried protect(bind in the
async_do_work function and that doesn't work either. Is it supposed
to be possible to nest binds arbitrarily deep or is this just a
limitation? Or am I just doing it wrong?

Regards


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net