Edd Dawson wrote:
Hi folks,
I'm currently attempting to create a little facility that will allow me to eaily kick off a function call in another thread and get the result through a "future". Something like:
[snip]
To achieve this I'm using boost::bind and boost::function quite heavily. I've discovered that by the time the final boost::function
is composed for the boost::thread constructor, I've copied each of the arguments (such as 9876543210 in the above) about 30 times!.
I've done what you're describing. I've not looked to see how many times the arguments are copied though. It does sound a bit extreme. I wouldn't start a new thread for each invocation though. Normally you'd be better off re-using an earlier thread. Unless you're talking about very large parameters the thread start up and shut down will probably still take longer than the argument copying, but you'll have to take timings to be sure.
Now, I can use boost::ref() internally in such a way that no copying of arguments happens at all. However, this is also undesirable; I would like the thread that is created to have its own copy of each argument unless the client explicitly wraps an argument in boost::ref/cref in order to avoid dangling cross-thread references.
So what I'd like is a way to copy the result of my final boost::bind() call in to a new functor where all the ref() arguments are deep-copied once and only once at the end.
Why not copy them once at the beginning into a structure with a pointer? I've not looked at how I might do this in mine, but I imagine our architectures aren't that dissimilar -- I use multiply nested functions that wrap the functions to execute at the higher levels into the new function signatures needed by the lower levels. Note that the refs you're talking about are probably the same number of bits as the integer. What you really need to do is to decide whether to just copy the argument or not depending on what the argument is. One thought might be to create a mismatch between the function signature and what you're passing in. Say your prime number function took a string as an argument. Normally you would do this: long primes( const std::string &bignum ); std::string limit( "9876543210" ); async::call(cage, &count_primes_upto, limit ); This will copy the string a load of times. But wouldn't this copy it once at the end when passed into primes? long primes( std::string bignum ); std::string limit( "9876543210" ); async::call(cage, &count_primes_upto, boost::ref( limit ) ); Another alternative that might work for strings is this: long primes( const std::string &bignum ); std::string limit( "9876543210" ); async::call(cage, &count_primes_upto, limit.c_str() ); That should force a string constructor only at the end of the chain, the rest of the time passing a pointer. I'm not sure if any of those will work, or if they will really address your problem though. Maybe something to try? K