Boost logo

Boost Users :

From: Trent Hill (trent.hill_at_[hidden])
Date: 2005-01-06 18:20:14


Hi Peter,

Peter Dimov wrote:

<snip>

>> Four copies - I had hoped to only see a single copy. Logically, there
>> doesn't seem to be a need for more than one copy. Is there an
>> implementation issue that requires this many copies?
>
>
> Not really, but eliminating the unnecessary copies is (relatively) hard,
> at least with the current code base (it has been developed with
> portability in mind and supports VC6, among others). The specification
> requires one copy. One more is almost unavoidable. The other two can be
> eliminated, in theory. But...

Ok, thanks. Out of interest, is there a simple explanation for why one
more is almost unavoidable.

<snip>

> ... please note that the copies occur at bind time. In a typical
> scenario you bind once and call O(N) times (or bind and store in a
> function<> with the associated dynamic memory allocation), so this isn't
> usually a problem. And, as others have pointed out, there's always
> ref(). ;-)

Yes I understand. I guess I'm not using bind typically ;-)

FYI and for those suggesting boost::ref, the actual case is using bind
for message passing between threads. I have a polymorphic wrapper for
bind something like this:

     class bind_wrapper
     {
     public:
         virtual void execute() = 0;
     };

     template <typename binder_t>
     class bind_wrapper_impl : public bind_wrapper
     {
     public:
         bind_wrapper_impl(const binder_t &binder_a)
             : binder_m(binder_a)
         {
         }
         virtual void execute()
         {
             binder_m();
         }
     private:
         binder_t binder_m;
     };

     template <typename binder_t>
     std::auto_ptr<bind_wrapper>
     make_bind_wrapper(const binder_t &binder_a)
     {
         return std::auto_ptr<bind_wrapper>(
             new bind_wrapper_impl<binder_t>(binder_a));
     }

Now the idea is that certain functions transparently transfer work to a
worker thread. So for such a function "foo", there would be an internal
implementation function:

     void foo_impl(const std::string &string_a)
     {
         // do stuff
     }

and a public proxy that requests foo_impl to be called on the worker thread:

     future foo_async(const std::string &arg_a)
     {
         std::auto_ptr<bind_wrapper> message_l(
             make_bind_wrapper(boost::bind(&foo_impl, arg_a)));
         // add message_l to message queue and return future to allow
         // rendezvous
         ...
     }

The worker thread will collect this message and call execute(),
something like:

     void worker_thread()
     {
         // retrieve from message queue and execute
         std::auto_ptr<bind_wrapper> message_l = ...
         message_l->execute();
     }

So, in this case:
   1. Yes, a copy is required - boost::ref is not appropriate.
   2. Each bind corresponds to a single call (not O(N) calls)

We have a home grown solution (less general than bind of course)
requiring only a single copy. I was hoping to replace it with bind but
it's hard to justify adding the extra argument copies.

Thanks for the info though,
Cheers, Trent.


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