|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next > |
|
|
Re: Review Request: future library (N2561/Williams version)vicente.botet:
>>> I don't understand the need of this function. Could you show a use case >>> for promise::get_future() function? >> >> promise::get_future() is the only way to get a future from a promise. >> Since the whole point of using promise is to get the future, it's rather >> pointless without it. > > why this is not an internal feautre? You have to have a way to create the initial future, but for the "one time" semantics one can have for example promise::promise( future& f ); instead of get_future. FWIW, Braddock has argued (see the archives) that it's convenient to be able to obtain a future from a promise, without the "one time" restriction. ("His" futures are "shared" though, as are "mine".) I argued that without this feature, a promise can detect that no futures are left and can cancel its task. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Review Request: future library (N2561/Williams version)Hi all,
I have updated my prototype futures library implementation in light of various comments received, and my own thoughts. The new version is available for download, again under the Boost Software License. It still needs to be compiled against the Boost Subversion Trunk, as it uses the Boost Exception library, which is not available in an official boost release. Sample usage can be seen in the test harness. The support for alternative allocators is still missing. Changes * I have removed the try_get/timed_get functions, as they can be replaced with a combination of wait() or timed_wait() and get(), and they don't work with unique_future<R&> or unique_future<void>. * I've also removed the move() functions on unique_future. Instead, get() returns an rvalue-reference to allow moving in those types with move support. Yes, if you call get() twice on a movable type then the second get() returns an empty shell of an object, but I don't really think that's a problem: if you want to call get() multiple times, use a shared_future. I've implemented this with both rvalue-references and the boost.thread move emulation, so you can have a unique_future<boost::thread> if necessary. test_unique_future_for_move_only_udt() in test_futures.cpp shows this in action with a user-defined movable-only type X. * Finally, I've added a set_wait_callback() function to both promise and packaged_task. This allows for lazy-futures which don't actually run the operation to generate the value until the value is needed: no threading required. It also allows for a thread pool to do task stealing if a pool thread waits for a task that's not started yet. The callbacks must be thread-safe as they are potentially called from many waiting threads simultaneously. At the moment, I've specified the callbacks as taking a non-const reference to the promise or packaged_task for which they are set, but I'm open to just making them be any callable function, and leaving it up to the user to call bind() to do that. I've left the wait operations as wait() and timed_wait(), but I've had a suggestion to use wait()/wait_for()/wait_until(), which I'm actively considering. Please download it, try it out, and let me know what you think. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Review Request: future library (N2561/Williams version)----- Original Message -----
From: "Anthony Williams" <anthony_w.geo@...> To: <boost@...> Sent: Sunday, May 11, 2008 11:53 AM Subject: Re: [boost] Review Request: future library (N2561/Williams version) > Hi all, > > I have updated my prototype futures library implementation in light of > various > comments received, and my own thoughts. > > The new version is available for download, again under the Boost Software > License. It still needs to be compiled against the Boost Subversion Trunk, > as > it uses the Boost Exception library, which is not available in an official > boost release. Hi, Sorry for the question, but where can we download the new version? I have followed the old link http://www.justsoftwaresolutions.co.uk/files/n2561_future.hpp and there is no modification. Best Vicente _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Review Request: future library (N2561/Williams version)"vicente.botet" <vicente.botet@...> writes:
> ----- Original Message ----- > From: "Anthony Williams" <anthony_w.geo@...> >> I have updated my prototype futures library implementation in light of >> various >> comments received, and my own thoughts. >> >> The new version is available for download, again under the Boost Software >> License. It still needs to be compiled against the Boost Subversion Trunk, >> as >> it uses the Boost Exception library, which is not available in an official >> boost release. > > Hi, > > Sorry for the question, but where can we download the new version? I have > followed the old link > http://www.justsoftwaresolutions.co.uk/files/n2561_future.hpp > and there is no modification. Oops. It's http://www.justsoftwaresolutions.co.uk/files/n2561_futures_revised_20080511.zip Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Review Request: future library (N2561/Williams version)Nice work! Let's hope we can all agree on a best interface - and get it standardized directly :)
If you haven't, please read my concerns about direct callbacks in http://www.nabble.com/Review-Request%3A-future-library-%28Gaskill-version%29-to16600402.html I like timed_wait because that's the same name as in condition_variable. wait_until could be confusing - one might think the thread will wait until the specified time regardless of the future is set or not. time_limited_wait or wait_max_time are further alternatives. Best Regards, Johan |
|
|
Re: Re view Request: future library (N2561/Williams version)Johan Torp <johan.torp@...> writes:
> Nice work! Let's hope we can all agree on a best interface - and get it > standardized directly :) Yes, I hope so. > Anthony Williams-3 wrote: >> >> * Finally, I've added a set_wait_callback() function to both promise and >> packaged_task. This allows for lazy-futures which don't actually run the >> operation to generate the value until the value is needed: no threading >> required. It also allows for a thread pool to do task stealing if a pool >> thread waits for a task that's not started yet. The callbacks must be >> thread-safe as they are potentially called from many waiting threads >> simultaneously. At the moment, I've specified the callbacks as taking a >> non-const reference to the promise or packaged_task for which they are >> set, >> but I'm open to just making them be any callable function, and leaving >> it up >> to the user to call bind() to do that. >> > > If you haven't, please read my concerns about direct callbacks in > http://www.nabble.com/Review-Request%3A-future-library-%28Gaskill-version%29-to16600402.html I have read your comments. My primary reason for including this came from thread pools: if you know that the current thread (from the pool) is blocked on a future related to a task in the pool, you can move it up the queue, or maybe even invoke on the blocked thread. Braddock suggested lazy futures, and I think that's also an important use case. For one thing, it shows that futures are useful without thread pools: you can use them in single-threaded code. > Anthony Williams-3 wrote: >> >> I've left the wait operations as wait() and timed_wait(), but I've had a >> suggestion to use wait()/wait_for()/wait_until(), which I'm actively >> considering. >> > > I like timed_wait because that's the same name as in condition_variable. > wait_until could be confusing - one might think the thread will wait until > the specified time regardless of the future is set or not. time_limited_wait > or wait_max_time are further alternatives. This was alongside a suggestion that we change the names for condition_variable waits. The important part was the separation of timed_wait(duration) vs timed_wait(absolute_time) with distinct names, so it was clear which you were calling, and you wouldn't accidentally pass a duration when you meant a fixed time point. We could go for timed_wait_for() and timed_wait_until(), but they strike me as rather long-winded. Maybe that's a good thing ;-) Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)I don't quite understand you. What is the "current" thread in a thread pool? If there are dependencies between tasks in a thread-pool, shouldn't prioritizing be the task of an external scheduler - and solved before the tasks are initiated? I'd like to know your thoughts on what the thread pool should be and what problems it should solve more specifically than what's explained in N2276. I thought the most common use case for futures was the active object pattern. We should all try to agree what use cases/design patterns/higher level abstractions are most important and which we want to support. IMHO, this should be top priority for the "future ambition". Even though no higher level abstractions built on futures will make it to C++0x or boost anytime soon, it's important that the future interface needn't change to support them in the - future :) To me, being able to wait for any or all of a number of futures seems like an important use case. I'd use it to implement "i'm waiting on the result of a number of time-consuming commands and queries". Maybe this is implemented better in another way - any ideas? Yes, long names is a good thing :) duration_timed_wait/absolute_timed_wait are other alternatives. duration and absolute_time will have two different types, right? If so I don't think they should have different function names because: - IMO it doesn't increase code readability to repeat type information in symbol names - It reduces genericity. Function overloading can be used to implement LSP for generic functions. template<class TimeType> void foo_algorithm(future<void>&f, TimeType t) { ... do stuff ... f.timed_wait(t); // LSP for TimeType, more generic } I vote for 2 x time_limited_wait. Best Regards, Johan |
|
|
Re: Re view Request: future library (N2561/Williams version)Johan Torp <johan.torp@...> writes:
> Anthony Williams-3 wrote: >> >> I have read your comments. My primary reason for including this came from >> thread pools: if you know that the current thread (from the pool) is >> blocked >> on a future related to a task in the pool, you can move it up the queue, >> or >> maybe even invoke on the blocked thread. Braddock suggested lazy futures, >> and >> I think that's also an important use case. For one thing, it shows that >> futures are useful without thread pools: you can use them in >> single-threaded >> code. >> > > I don't quite understand you. What is the "current" thread in a thread pool? In this case I mean the thread that called some_future.wait(). > If there are dependencies between tasks in a thread-pool, shouldn't > prioritizing be the task of an external scheduler - and solved before the > tasks are initiated? I'd like to know your thoughts on what the thread pool > should be and what problems it should solve more specifically than what's > explained in N2276. Suppose you're using a thread pool to provide a parallel version of quick-sort. The easiest way to do that is to partition the values into those less than and those not-less-than the chosen pivot (as you would for a single-threaded version), and submit tasks to the thread pool to sort each half and then waits for them to finish. This doubles the number of tasks with each level of recursion. At some point the number of tasks will exceed the number of threads in the pool, in which case you have some tasks waiting on others that have been submitted to the pool but not yet scheduled. If you can arrange for the implementation to identify this scenario as it happens, and thus schedule the task being waited for to run on the waiting thread, you can achieve greater thread reuse within the pool, and reduce the number of blocked threads. One way to do this is have the pool use packaged_tasks internally, and set a wait callback which is invoked when a thread waits on a future from a pool task. When the callback is invoked by the waiting thread (as part of the call to wait()), if that waiting thread is a pool thread, it can proceed as above. If not, then it might arrange to schedule the waited-for task next, or just do nothing: the task will get its turn in the end. > I thought the most common use case for futures was the active object > pattern. That's one possible use. I wouldn't have pegged it as "most common" unless you're considering all cases of a background thread performing operations for a foreground thread as uses of active object. > We should all try to agree what use cases/design patterns/higher > level abstractions are most important and which we want to support. IMHO, > this should be top priority for the "future ambition". Even though no higher > level abstractions built on futures will make it to C++0x or boost anytime > soon, it's important that the future interface needn't change to support > them in the - future :) I agree we should think about the higher-level abstractions we want to support, to ensure the "futures" abstraction provides the necessary baseline. I'd like higher-level stuff to be built on top of C++0x futures without having to replace them with a different low-level abstraction that provides a similar feature set. > To me, being able to wait for any or all of a number of futures seems like > an important use case. I'd use it to implement "i'm waiting on the result of > a number of time-consuming commands and queries". Maybe this is implemented > better in another way - any ideas? Waiting for one of a number of tasks is an important use case. I'm not sure how best to handle it. I've seen people talk about "future_or" and "f1 || f2", but I'm not sure if that's definitely the way to go. > Anthony Williams-3 wrote: >> >> This was alongside a suggestion that we change the names for >> condition_variable waits. The important part was the separation of >> timed_wait(duration) vs timed_wait(absolute_time) with distinct names, so >> it >> was clear which you were calling, and you wouldn't accidentally pass a >> duration when you meant a fixed time point. >> >> We could go for timed_wait_for() and timed_wait_until(), but they strike >> me as >> rather long-winded. Maybe that's a good thing ;-) >> > > Yes, long names is a good thing :) duration_timed_wait/absolute_timed_wait > are other alternatives. > duration and absolute_time will have two different types, right? If so I > don't think they should have different function names because: > - IMO it doesn't increase code readability to repeat type information in > symbol names > - It reduces genericity. Function overloading can be used to implement LSP > for generic functions. > > template<class TimeType> > void foo_algorithm(future<void>&f, TimeType t) > { > ... do stuff ... > f.timed_wait(t); // LSP for TimeType, more generic > } > > I vote for 2 x time_limited_wait. duration and absolute_time will have distinct types. In Boost at the moment, for boost::condition_variable, duration is anything that implements the Boost Date-Time duration concept, such as boost::posix_time::milliseconds, and absolute_time is boost::system_time. However, even though distinct overloads will be called, this is not necessarily desirable, as the semantics are distinct. The members of the LWG are discussing renaming condition_variable::timed_wait to have distinct names for the duration and absolute time overloads in order to ensure that the user has absolute clarity of intent: wait_for(absolute_time) or wait_until(duration) won't compile. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)Anthony Williams:
> One way to do this is have the pool use packaged_tasks internally, and set > a > wait callback which is invoked when a thread waits on a future from a pool > task. When the callback is invoked by the waiting thread (as part of the > call > to wait()), if that waiting thread is a pool thread, it can proceed as > above. It actually doesn't matter whether the waiting thread is a pool thread or not. If the task hasn't been scheduled, it can be "stolen" and executed synchronously from within the wait(). _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)"Peter Dimov" <pdimov@...> writes:
> Anthony Williams: > >> One way to do this is have the pool use packaged_tasks internally, and set >> a >> wait callback which is invoked when a thread waits on a future from a pool >> task. When the callback is invoked by the waiting thread (as part of the >> call >> to wait()), if that waiting thread is a pool thread, it can proceed as >> above. > > It actually doesn't matter whether the waiting thread is a pool thread or > not. If the task hasn't been scheduled, it can be "stolen" and executed > synchronously from within the wait(). Yes, you could do that. I'm not convinced it's necessarily a good idea, though. Different threads potentially have different priorities or access permissions. Also, thread interruption will behave differently: in my prototype implementation, future::wait() is an interruption point. If a call to wait() stole a task from a thread pool, interrupting the thread would instead interrupt the task, which is not necessarily what was intended, as this may have consequences for other threads waiting on that task. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)I misunderstood - I thought set_wait_callback was Gaskill's proposed callback when a future was ready. If I understand you correctly this use case is as follows; Each future correlates to an unfinished task. A. When a worker thread calls wait(), instead of/prior to blocking it might perform another task B. By detecting when client/non-worker threads are waiting we can use that information to serve them faster. A seems very dangerous. The worker thread has a stack associated with the task it is carrying out. If the thread crashes or an exception is thrown, only the current task is affected. If it should carry out another task [task2] on top of the first task [task1], task2 crashing would destroy task1 too. Also, we could get a problem with too deep stack nesting if the same thread starts working on more and more tasks. B might be useful. It can't detect waiting by periodic is_ready-polling - which with todays interface is needed to wait for more than one future. Rather than implicitly trying to guess client threads' needs wouldn't it be better to either: - Let the thread-pool be a predictable FIFO queue. Trust client code to do the scheduling and not submit too many tasks at the same time. - Open up the pool interface and let users control some kind of prioritization or scheduling I'm probably misunderstanding something here. I think we should allow waiting on a dynamically changing number of futures. Operators are poorly suited for this because they require function recursion. Maybe some kind of future container with wait_all() and wait_any() functions. My biggest question is how this will map to condition_variables. Also, could this facility be some layer below futures which can be reused? Dependency deduction and lazy return value composition functionality - like operators - should probably be built on top of the dynamic waiting facility. In what way are the semantics different? To be extra clear, I'll repeat myself: This will complicate writing parallel algorithms which works generically with any time type. For both library vendors and users. My 5 cents is still that 2 x time_limited_wait is clear and readable enough but it's no strong opinion. For good or bad you are forcing users to supply their intent twice - by both argument type and method name. Is this a general strategy for the standard library? Best Regards, Johan |
|
|
Re: Re view Request: future library (N2561/Williams version)Johan Torp <johan.torp@...> writes:
> Anthony Williams-3 wrote: > I misunderstood - I thought set_wait_callback was Gaskill's proposed > callback when a future was ready. No problem. > If I understand you correctly this use case is as follows; > Each future correlates to an unfinished task. > A. When a worker thread calls wait(), instead of/prior to blocking it might > perform another task > B. By detecting when client/non-worker threads are waiting we can use that > information to serve them faster. Yes. > A seems very dangerous. The worker thread has a stack associated with the > task it is carrying out. If the thread crashes or an exception is thrown, > only the current task is affected. If it should carry out another task > [task2] on top of the first task [task1], task2 crashing would destroy task1 > too. Also, we could get a problem with too deep stack nesting if the same > thread starts working on more and more tasks. If the thread "crashes", you've got a serious bug: all bets are off. It doesn't matter whether that's the same thread that's performing another task or not. If the task throws an exception, I expect this to be swallowed by the task-launching code, and get stored in the future corresponding to that task. This therefore will not affect the original waiting task. Stack overflow is potentially a real problem. If a thread pool implementation decides to do such task nesting, it needs to ensure the stack is sufficiently large to handle it. For example, if you're going to allow N nested tasks, the stack for that pool thread ought to be N times larger than the stack for a single task. > B might be useful. It can't detect waiting by periodic is_ready-polling - > which with todays interface is needed to wait for more than one future. I would use timed_wait() calls when waiting for more than one future: doing a busy-wait with is_ready just consumes CPU time which would be better spent actually doing the work that will set the futures to ready, and timed_wait is more expressive than sleep: void wait_for_either(jss::unique_future<int>& a,jss::unique_future<int>& b) { if(a.is_ready() || b.is_ready()) { return true; } while(!a.timed_wait(boost::posix_time::milliseconds(1)) && !b.timed_wait(boost::posix_time::milliseconds(1))); } This will trigger the callback. > Rather than implicitly trying to guess client threads' needs wouldn't it be > better to either: > - Let the thread-pool be a predictable FIFO queue. Trust client code to do > the scheduling and not submit too many tasks at the same time. That's not appropriate for situations where a task on the pool can submit more tasks to the same pool, as in my quicksort example. > - Open up the pool interface and let users control some kind of > prioritization or scheduling Allowing callbacks doesn't preclude this option. > I'm probably misunderstanding something here. There are many ways of scheduling threads in a thread pool, not all of which are suitable for all circumstances. Providing set_wait_callback gives the writer of the thread pool flexibility to choose the most appropriate model for the circumstances he is trying to handle. > Anthony Williams-3 wrote: >> >> Waiting for one of a number of tasks is an important use case. I'm not >> sure >> how best to handle it. I've seen people talk about "future_or" and "f1 || >> f2", >> but I'm not sure if that's definitely the way to go. >> > > I think we should allow waiting on a dynamically changing number of futures. > Operators are poorly suited for this because they require function > recursion. Maybe some kind of future container with wait_all() and > wait_any() functions. My biggest question is how this will map to > condition_variables. Also, could this facility be some layer below futures > which can be reused? My wait_for_either above could easily be extended to a dynamic set, and to do wait_for_both instead. Condition variables are more complicated, since they don't inherently support wait-for-any or wait-for-all operations, and every wake from a timed_wait call removes the thread from the waitset for that cv. To make it work, you would have to supply all the predicates associated with each cv, and all the associated mutexes. I think I'd rather just use futures. > Dependency deduction and lazy return value composition functionality - like > operators - should probably be built on top of the dynamic waiting facility. It would be relatively simple to build an operator on top of wait_for_either(). > Anthony Williams-3 wrote: >> >> However, even though distinct overloads will be called, this is not >> necessarily desirable, as the semantics are distinct. >> > > In what way are the semantics different? timed_wait(duration) waits for a specified amount of time to elapse. timed_wait(absolute_time) waits until the clock reads the specified time. This can be important if you're using a cv in a loop: boost::mutex m; boost::condition_variable cv; bool done=false; template<typename Duration> bool wait_with_background_processing(Duration d) { boost::system_time timeout=boost::get_system_time()+d; boost::unique_lock<boost::mutex> lk(m); while(!done) { if(!cv.timed_wait(d)) // oops, meant timeout { return false; } lk.unlock(); do_background_processing(); lk.lock(); } } This code will compile and run, but will wait up to the specified duration every time round the loop rather than waiting only the specified duration in total. By giving the duration and absolute-time overloads different names, you can avoid this bug. > Anthony Williams-3 wrote: >> >> The members of the LWG are discussing renaming >> condition_variable::timed_wait to have distinct names >> for the duration and absolute time overloads in order to ensure that the >> user >> has absolute clarity of intent: wait_for(absolute_time) or >> wait_until(duration) won't compile. >> > > To be extra clear, I'll repeat myself: This will complicate writing parallel > algorithms which works generically with any time type. For both library > vendors and users. Generic code needs to know whether it's got a duration or an absolute time, so this is not an issue, IMHO. > My 5 cents is still that 2 x time_limited_wait is clear and readable enough > but it's no strong opinion. For good or bad you are forcing users to supply > their intent twice - by both argument type and method name. Is this a > general strategy for the standard library? This is an important strategy with condition variables, and it is probably sensible to do the same elsewhere in the standard library for consistency. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)----- Original Message -----
From: "Anthony Williams" <anthony_w.geo@...> To: <boost@...> Sent: Monday, May 12, 2008 12:52 PM Subject: Re: [boost] Re view Request: future library (N2561/Williams version) > duration and absolute_time will have distinct types. In Boost at the > moment, > for boost::condition_variable, duration is anything that implements the > Boost > Date-Time duration concept, such as boost::posix_time::milliseconds, and > absolute_time is boost::system_time. Please could you add this to the documentation of the Boost.Thread (duration_type is anything that implements the Boost Date-Time duration concept). I have no seen it on the documentation. The same should be true for the other uses of dureation_type as template parameter. I think that it becomes urgent to solve the time versus duration concepts usable on real time applications and doispose of specific models. template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time) Effects: Atomically call lock.unlock() and blocks the current thread. The thread will unblock when notified by a call to this->notify_one() or this->notify_all(), after the period of time indicated by the rel_time argument has elapsed, or spuriously. When the thread is unblocked (for whatever reason), the lock is reacquired by invoking lock.lock() before the call to wait returns. The lock is also reacquired by invoking lock.lock() if the function exits with an exception. Best, icente _____________________ Vicente Juan Botet Escriba _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Review Request: future library : what does future of references exactly means?----- Original Message -----
From: "Johan Torp" <johan.torp@...> To: <boost@...> Sent: Monday, May 12, 2008 12:14 PM Subject: Re: [boost] Re view Request: future library (N2561/Williams version) > I thought the most common use case for futures was the active object > pattern. We should all try to agree what use cases/design patterns/higher > level abstractions are most important and which we want to support. IMHO, > this should be top priority for the "future ambition". Even though no > higher > level abstractions built on futures will make it to C++0x or boost anytime > soon, it's important that the future interface needn't change to support > them in the - future :) I don't know if the most common use case is the active object pattern, I use it every time I call a functions whic could finish or not depending on its internals. Some times the function sould wait on some messages and then the best is to return a future. But the function can also finish on the same thread if it don't needs external interaction. The client could later on wait in the future (active) or attach a callback to be called when the future is ready (reaction). For example: { // ... future<T> f = call_somme_fct(); // ... // when the result is needed either wait by using it or if (!f) // attach some callback and change the intenal state else // continue // ... } I agree with you that the best test for the future interface is to show some good usages in the tutorial and examples of the library. The threadpool library could be one, but not the only one. Imagine now we had a function which returs a value and had an out parameter (maybe by reference) Result f(InOut& ref); Now we want to refactor this function (either because the new implementation will introduce an IO wait, or because the old blocking implementation could not be supported. Which should be the interface of the new function. The first thing could be to try with future<Result> f(InOut& ref); but nothing forbids the caller to use the ref parameter before the operation has completed and which could be invalid. If we want consistency what we would need is something like future<Result> f(future<InOut&>& ref); IMO this do not works in any proposal? Do we need future to works with in/out references? Yet another example future<Out&> f(); Note that future<Out&> and future<InOut&> should not mean the same. Do we need two future of reference classes? future<InOut&> will need a constructor future<InOut&>(InOut&), but the assocaited promise should copy the value when doint the set_value. Any thought? Has all this a sense or I'm completly lost? This example was there only to introdude other use cases, and in particular future of reference types or pointer types. If you have a better choice for the f function do not hesitate. Anthony, sorry for short cut (futures instead of unique_future or shared_future). In order to be coherent with the thread library (mutex/shared_mutex), should't unique_future be named future? Vicente _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Review Request: future library : what does future of references exactly means?"vicente.botet" <vicente.botet@...> writes:
> Imagine now we had a function which returs a value and had an out parameter > (maybe by reference) > > Result f(InOut& ref); > > Now we want to refactor this function (either because the new implementation > will introduce an IO wait, or because the old blocking implementation could > not be supported. Which should be the interface of the new function. The > first thing could be to try with > > future<Result> f(InOut& ref); > > but nothing forbids the caller to use the ref parameter before the operation > has completed and which could be invalid. If we want consistency what we > would need is something like > > future<Result> f(future<InOut&>& ref); > > IMO this do not works in any proposal? You can write it with my proposal, but I'm not sure it means what you intend, given what you write below. > Do we need future to works with in/out references? > > Yet another example > future<Out&> f(); > > Note that future<Out&> and future<InOut&> should not mean the same. Do we > need two future of reference classes? future<InOut&> will need a constructor > future<InOut&>(InOut&), > but the assocaited promise should copy the value when doint the set_value. If the promise associated with your future<InOut&> should copy the value, then what you want is a future<InOut>. If you had a future<InOut&>(InOut&) constructor, then you could /still/ use the original InOut& before the future had returned, just as if you passed a plain reference to the function. With my (updated) proposal, unique_future<T>::get() returns an rvalue-reference, so you could move/copy this into the InOut value you intend to use, or you could use shared_future<T>, where get() returns a const reference. > Anthony, sorry for short cut (futures instead of unique_future or > shared_future). In order to be coherent with the thread library > (mutex/shared_mutex), should't unique_future be named future? unique_future/shared_future is by analogy to unique_ptr/shared_ptr, which I think is a closer match than mutex/shared_mutex. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)"vicente.botet" <vicente.botet@...> writes:
> ----- Original Message ----- > From: "Anthony Williams" <anthony_w.geo@...> > To: <boost@...> > Sent: Monday, May 12, 2008 12:52 PM > Subject: Re: [boost] Re view Request: future library (N2561/Williams > version) > >> duration and absolute_time will have distinct types. In Boost at the >> moment, >> for boost::condition_variable, duration is anything that implements the >> Boost >> Date-Time duration concept, such as boost::posix_time::milliseconds, and >> absolute_time is boost::system_time. > > Please could you add this to the documentation of the Boost.Thread > (duration_type is anything that implements the Boost Date-Time duration > concept). I have no seen it on the documentation. The same should be true > for the other uses of dureation_type as template parameter. I think that it > becomes urgent to solve the time versus duration concepts usable on real > time applications and doispose of specific models. It's on my list. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library (N2561/Williams version)I agree that something is seriously wrong and that we perhaps don't need to handle things gracefully. But if the threading API allows us to detect "crashing" threads somehow, we could avoid spreading a thread-local problem to the whole process. The client thread could even be notified with a thread_crash exception set in the future. I'm haven't had time to read up on what possibilities the C++0x threading API will supply here, but I suppose you know. Maybe there isn't even a notion of a thread crashing without crashing the process. At the very least, I see a value in not behaving worst than if the associated client thread would have spawned it's own worker thread. That is: std::launch_in_pool(&crashing_function); should not behave worse than std::thread t(&crashing_function); It could as well have been implemented by: while (!a.is_ready() || !b.is_ready()) { a.timed_wait(boost::posix_time::milliseconds(1)); } You can't detect that b is needed here. I would not implement dynamic wait by timed_waiting on every single future, one at a time. Rather i would have done something like: void wait_for_any(const vector<future<void>>& futures) { while (1) { for (...f in futures...) if (f.is_ready()) return; sleep(10ms); } } Ah - I knew I missed something. Agreed, child tasks should be prioritized. But that mechanism could be kept internal in the thread pool. Still you don't really wait for more than one future at a time. Both yours and mine suggestion above are depressingly inefficient if you were to wait on 1000s of futures simultaneously. I don't know if this will be a real use case or not. If the many core prediction comes true and we get 1000s of cores, it might very well be. I understand your point, even though I'm not sure it's the best strategy. Rather than arguing with more experienced people, I'll adopt whatever public code I write to this. Johan |
|
|
Re: Review Request: future library : what does future of references exactly means?Firstly, this is a dangerous design. The calling thread must keep the reference alive until the future is ready - no matter what. For instance, what if it's owner thread tells it to terminate? Secondly, you can't prohibit the calling thread to access it's original reference. So the problem isn't really solved. Presently, I haven't seen any use cases which would motivate reference support for futures. Not allowing references is a safety net in it's own right. This is also very dangerous, the promise-fulfilling thread must guarantee that the reference is valid until program termination as it can't detect when the future dies. Even if it could detect future destruction, it would be a strange design. Shared_ptrs or some kind of moving should be applied here. Johan |
|
|
Re: Review Request: future library : what does future ofreferences exactly means?----- Original Message -----
From: "Anthony Williams" <anthony_w.geo@...> To: <boost@...> Sent: Tuesday, May 13, 2008 8:51 AM Subject: Re: [boost] Review Request: future library : what does future ofreferences exactly means? > "vicente.botet" <vicente.botet@...> writes: > >> Imagine now we had a function which returs a value and had an out >> parameter >> (maybe by reference) >> >> Result f(InOut& ref); >> >> Now we want to refactor this function (either because the new >> implementation >> will introduce an IO wait, or because the old blocking implementation >> could >> not be supported. Which should be the interface of the new function. The >> first thing could be to try with >> >> future<Result> f(InOut& ref); >> >> but nothing forbids the caller to use the ref parameter before the >> operation >> has completed and which could be invalid. If we want consistency what we >> would need is something like >> >> future<Result> f(future<InOut&>& ref); >> >> IMO this do not works in any proposal? > > You can write it with my proposal, but I'm not sure it means what you > intend, > given what you write below. > >> Do we need future to works with in/out references? >> >> Yet another example >> future<Out&> f(); >> >> Note that future<Out&> and future<InOut&> should not mean the same. Do we >> need two future of reference classes? future<InOut&> will need a >> constructor >> future<InOut&>(InOut&), >> but the assocaited promise should copy the value when doint the >> set_value. > > If the promise associated with your future<InOut&> should copy the value, > then > what you want is a future<InOut>. If you had a future<InOut&>(InOut&) > constructor, then you could /still/ use the original InOut& before the > future > had returned, just as if you passed a plain reference to the function. > > With my (updated) proposal, unique_future<T>::get() returns an > rvalue-reference, so you could move/copy this into the InOut value you > intend > to use, or you could use shared_future<T>, where get() returns a const > reference. Well let me come back to my initial example. Supose that I had Result f(InOut& ref); // ... { InOut v=0; // ... v = 13; Result r = f(v); // ... use r or v; g(r, v); v = 15; } Do you mean that the following works with your proposal? unique_future<Result> f(shared_future<InOut>& ref); // ... { shared_future<InOut> v; v->get()=0; // ... v->get() = 13; unique_future<Result> r = f(v); // ... use r or v; g(r->get(), v->get()); v->get() = 15; } >> Anthony, sorry for short cut (futures instead of unique_future or >> shared_future). In order to be coherent with the thread library >> (mutex/shared_mutex), should't unique_future be named future? > > unique_future/shared_future is by analogy to unique_ptr/shared_ptr, which > I > think is a closer match than mutex/shared_mutex. OK. I understand Vicente _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: Re view Request: future library : what does future of references exactly means?--------------------------- Vicente Juan Botet Escriba ----- Original Message ----- From: "Johan Torp" <johan.torp@...> To: <boost@...> Sent: Tuesday, May 13, 2008 11:42 AM Subject: Re: [boost] Re view Request: future library : what does future of references exactly means? > > > vicente.botet wrote: >> >> Imagine now we had a function which returs a value and had an out >> parameter >> (maybe by reference) >> >> Result f(InOut& ref); >> >> Now we want to refactor this function (either because the new >> implementation >> will introduce an IO wait, or because the old blocking implementation >> could >> not be supported. Which should be the interface of the new function. The >> first thing could be to try with >> >> future<Result> f(InOut& ref); >> >> but nothing forbids the caller to use the ref parameter before the >> operation >> has completed and which could be invalid. If we want consistency what we >> would need is something like >> >> future<Result> f(future<InOut&>& ref); >> > > Firstly, this is a dangerous design. The calling thread must keep the > reference alive until the future is ready - no matter what. For instance, > what if it's owner thread tells it to terminate? What do you propose instead? What do you think of future<Result> f(cosnt InOut& in, future<InOut>& out); future<InOut> fv; r= f(v, fv) v = fv.get(); > Secondly, you can't prohibit the calling thread to access it's original > reference. So the problem isn't really solved. You are right, the problem is not solved. > Presently, I haven't seen any use cases which would motivate reference > support for futures. Not allowing references is a safety net in it's own > right. > vicente.botet wrote: >> >> Yet another example >> future<Out&> f(); >> > > This is also very dangerous, the promise-fulfilling thread must guarantee > that the reference is valid until program termination as it can't detect > when the future dies. Even if it could detect future destruction, it would > be a strange design. Shared_ptrs or some kind of moving should be applied > here. This is not more dangerous that Out& f(); We know how dangerous it is and we use every time. This reference point usualy to a member object, and the object can be deleted. Vicente _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
| < Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |