$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
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.