
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 30 May 2008 09:25 am, Johan Torp wrote:
Anthony Williams-4 wrote:
Alternatively, you could have future_or spawn a thread to run the task rather than do it lazily as a wait callback.
I don't think spawning a thread is acceptable.
1. Starting a new thread is expensive. Thread-pools might help here but they don't exist yet. 2. Context switching is expensive. Typically, the evaluation work is real small. This approach requires an additional context switch compared to if the future-listener performed the evaluation. It might also reduce the performance of a thread-pool if composite futures are frequently evaluated. 3. Composed futures might need to access data belonging to the future-listener in it's evaluation. If the evaluation is performed by a single future-listener, it can use const references. Now such the data needs to be copied or protected by mutexes. 4. Nested composed futures might get a context switch at every depth level.
I wouldn't be surprised if the context switching would rule out futures from libraries such as asio or poet. That would be a real shame. Frank or somebody with asio insight, what do you think?
I've been working on the "wait for any/all" issue with libpoet's futures, and for me it has boiled down to the question of how this function should behave: template<typename R, typename Combiner, typename T1, typename T2, ..., typename TN> future<R> future_combining_barrier(Combiner combiner, future<T1> f1, future<T2> f2, ..., future<TN> fN); The idea of future_combining_barrier is the returned future<R> gets its value by calling combiner(f1.get(), f2.get(), ..., fN.get()) once all the input futures are ready. I see 3 options: 1) The combiner is run in a future-waiting thread. 2) The combiner is run in a promise-fulfilling thread. 3) The combiner is run in its own thread. I initially tried to implement option (1) but could not make it work satisfactorily with my implementation (which relies on completion callbacks). Basically, I couldn't get the returned future<R> to work well enough. I wanted it to run the combiner without holding any internal library locks, and also to run its own completion callback without undue goading from external code. Also, it is easy to accidentally run the combiner in a promise-fulfilling thread if the combiner gets run by the future::ready() query as well as when waiting. I haven't fully explored the uses of wait callbacks though, maybe something can be made to work. Currently, I have implemented solution (2). It seems to work well enough. Exceptions thrown in the combiner are transported to the returned future<R>. However, it does mean that a combiner which blocks or takes a long time can cause the promise-fulfilling thread to stall running it. Solution (3) has the advantage that it insulates the promise-fulfilling thread from the possibility of being stalled by a future-waiting thread which inserts a slow-running combiner. However, it is a relatively heavyweight solution, since I'd expect the typical combiner to be a fairly trivial and quick function to execute. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFIQEu25vihyNWuA4URAlB1AKCuwXXwJD9yRcooajshi2jyzPhgKgCfXBF7 SkoHgkcRO2JQiPXEB75t1oM= =TDTm -----END PGP SIGNATURE-----