|
Boost : |
Subject: Re: [boost] [afio] Formal review of Boost.AFIO
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2015-08-28 08:49:18
> >> 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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk