On 28/08/2015 00:58, Hartmut Kaiser wrote:
Third, the terminology 'consuming' and 'non-consuming' future does not make any sense (to me). More importantly it is by no means Standard- terminology - thus reasoning in terms of those makes it much more difficult for us to talk about the same thing.
future.get() moves the result of the promise from the internal state, thereby consuming it. Further calls to get() or then() fail.
shared_future.get() copies the result of the promise from the internal state, thereby not consuming it. Further calls to get() or then() succeed.
All of this is an irrelevant implementation detail. Nobody forces the future to share its state with a promise. It could very well be a packaged_task, for instance, or any other asynchronous provider.
You're sidestepping.
No. I'm trying to get your attention.
Some mechanism results in the value given to the promise arriving at the future, and thereby allowing it to return the value from get() or invoke then() continuations. For the purposes of this discussion I frankly don't care how that implementation is done, or whether it arrives via some other source such as a packaged_task.
However, the consequence of the front-end interface (future and shared_future) is as I described above. One of them is one-use-only and the other allows multiple uses. This is a visible and important characteristic -- in fact it is probably the *most* visible and important characteristic from a usage perspective. And that is the perspective that Niall appears to be using as well.
I'm not arguing that. I'm arguing, that the fact that you can use the value more than once is not the rationale of the design but a consequence of it. The rationale is to differentiate between unique ownership and shared ownership with regard to the value provided by the future. Thus the question whether code asking for a value is making the future invalid (is 'consuming the future' as you put it) is a consequence and not the purpose of the design either. Thus talking about 'consuming' a future is making it more difficult to understand than needed.
Whether the future internally uses shared state or not is actually the inconsequential part from the perspective of users of the classes. (Except where it affects performance -- and even that is inconsequential to some users. Perhaps even most users, given the prevalence of people saying "just use shared_ptr everywhere" not that long ago.)
Which is as wrong as is using shared_future everywhere (as done in AFIO). Even worse, AFIO does both, btw.
If somebody forgets, then an exception is the correct thing to do. Alternatively an assertion could be used in this case as well. BTW, an exception is not difficult to find, even gdb can break on a specific exception being thrown.
But only if the code path actually executes. While in an ideal world the unit tests will have 100% coverage, we don't live in that ideal world.
If the code path does not execute the fact you forgot is inconsequential :-P But seriously, you're trying to argue in favor of a bad design decision (namely creating the wrappers which apparently require using shared_futures) by saying that if we don't use the shared_futures the user suffers. What about not having the wrappers in the first place and create a proper API instead which would allow for unique ownership wherever possible and leave the decision whether shared ownership is necessary to the user? Regards Hartmut --------------- http://boost-spirit.com http://stellar.cct.lsu.edu