[cpp-threads] Asynchronous Function Proposal
Lawrence Crowl
Lawrence at Crowl.org
Tue Jun 16 01:08:52 BST 2009
On 6/13/09, Herb Sutter <hsutter at microsoft.com> wrote:
> I've now looked at the proposal further. It has implemented some
> of the changes suggested in the earlier thread, but still hasn't
> implemented some that I consider essential. In particular (and
> I don't think I was the only person to argue for these):
>
>
> - The async policy parameter is still first, and we don't need
> a variadic overload. There should be just one async() with a
> defaulted policy parameter.
I have no objection to this approach a-priori, but I think the
async parameters should be consistent with the thread constructor
parameters. If thread changes, the async should change as well.
> - The wording for the first policy still says "in a new thread,"
> which prevents the implementation from caching threads in any way
> (including the highly desirable option of running on a thread
> pool). It should say "in another thread."
N2880 says why allowing thread caching is not feasible. We can do
caching when we have thread pools, but I don't believe that we can
do so until then.
BTW, the OS can still cache threads underneath, but it still has
to destroy and reconstruct the thread-local variables.
> - There is still a new future type, async_future. It should be
> unique_future. (In related news, the return type of async()
> should be convertible to shared_future. Adding a conversion
> from async_future to shared_future would satisfy that part,
> but not satisfy the main point in this bullet.)
Can you provide a rationale based on use cases?
> As I mentioned to Lawrence privately last week, I strongly prefer
> to avoid having competing proposals for Frankfurt, but I feel
> strongly enough about these issues that if we feel we don't have
> consensus to word this proposal this way, I'm willing to write
> a competing proposal to make sure a version that looks like the
> above appears in an on-time paper for consideration in Frankfurt.
I am quite happy to have one paper present alternate technical
solutions, if the one in the paper is not what you want. However,
both technical solutions need rationale.
> Less importantly, the policy names are awkward. I'd prefer names
> more like "elsewhere/here/either" or "async/sync/either" or
> "this_thread/another_thread/either".
The names are likely to change to reflect semantic details.
> Also, whether we diverge proposals or not, I would like to see
> this paragraph reworded:
>
> > The proposed solution consists of a set of async functions
> > to launch asychronous work and a new kind of future to
> > manage the function result. This solution derives from
> > an extensive discussion on the C++ threads standardisation
> > <cpp-threads at decadentplace.org.uk> mailing list.
>
> That wrongly implies that the discussion blessed/suggested both the
> "set of async functions" and "a new kind of future" design points
> -- both of which I and others have objected to. At minimum this
> needs to acknowledge that there were strong objections against
> both of these features.
Note that I said discussion, not consensus. It was my intent to
capture the discussion and choices in the document. If you feel
that I have not done so accurately, please send me text.
> > The model for this feature, as I understand it, is to provide
> > a means for people with a sequential program to easily upgrade
> > it to exploit a small number of cores.
>
> No, it's simply to provide a simple means to perform an async
> function call that yield an async result, that is instead of
>
> T t = f();
>
> to write (I'll say just "future" to avoid the argument about the
> exact type here)
>
> future<T> t = async( []{ f(); } );
>
> without writing packaged_tasks and having to fill futures/promises
> manually.
Unfortunately, packaged tasks and futures are only part of the
specification. The issues presented in N2880 are handled in the
code around those primitives. That is, by providing a set of very
primitive mechanisms, packaged task et al punt on the hard issues.
By introducing async, we are squeezing out that code, and hence
need to address those issues.
>
> Beyond that basic requirement, there's also the desire (which the
> proposal already supports, thanks!) to allow, but not require,
> implementations that run the task on a thread pool or a work
> stealing runtime. To enable all of that, it's sufficient to have
> the three options "on this thread," "on a different thread,"
> or "either." The latter two enable thread pools; the last alone
> enables work stealing.
Unfortunately, the latter two do not enable thread pools because
of the problems outlined in N2880. Use of a thread pool, without
exposing the pool object to programmers, is dangerous.
When I said "new thread", I meant a new thread with new TLS lifetimes
because it solves the problems in N2880.
>
> Policy new thread thread pool work stealing
>
> on this thread no no no
> on another thread yes yes no
> either yes yes yes
Furthermore, any implementation that permits thread pools will
necessarily restrict the kinds of tasks that can be programmed,
because otherwise the pool synchronization interacting with
inter-task synchronization may introduce deadlock.
> > Switching to unique_future can be done relatively easily at
> > Frankfurt.
>
> No, I want there to be a concrete on-time proposal on the table
> in Frankfurt whose basic parts look correct to me, including
> that it does not invent some new future type and the other major
> points above.
The proposal is concrete, on-time, and looks correct to me. I am,
however, realistic enough to know that whatever we have ready will
be modified by the committee.
> I wasn't the only one who argued against having yet another
> future type only for use with async. I want async() to return a
> unique_future and I am happy with requiring the implementer to
> make it work. (Yes, it would be better still if unique_future
> and shared_future more easily let us accomplish what we want,
> but that's not necessary to have async() return the correct
> type, which I believe is unique_future as long as that remains
> convertible to shared_future.)
I do not particularly like having to propose a new future type.
Nor do I like the consequences of trying to reuse the existing
future types. If you can present an implementation that avoids
the consequences, I am quite happy to change the async return type.
> > Creating an async_future proposal at Frankfurt would not be easy.
> > So, in the interests of leaving our options open,
>
> It's not an option I want to see open. ;-) We have a future
> type; we should use it. I do not think this is a case where it's
> desirable to keep options open, because inventing a new one-off
> future type is just undesirable.
But requiring a massive increase in the implementation complexity
of the existing futures is also undesireable. It also violates
the principle of "pay for what you use".
> If you want to keep it in this proposal that's fine, but I
> disagree and I need there to be some proposal for Frankfurt that
> uses unique_future.
>
> > I addressed the choice in the paper, and I'll happily expand
> > that section to meet your concerns.
>
> I appreciate that, and I'd be okay with the proposal introduction
> mentioning this discussion and the pros/cons of using a
> separate future type -- as long as the proposed text itself uses
> unique_future and doesn't invent a new future type.
>
> Are you open to doing a revision along those lines, as well as
> the other points at top? I understand if you're not and either
> way I do appreciate the work you've put into this and the very
> useful discussion it has made possible! Thanks Lawrence,
I am open to a revision, but not without new information.
In particular, I need convincing text on:
Why the parameters to async should be different from the thread
constructor. (If the thread constructor parameters change, this
point becomes moot.)
Why the issues presented in N2880 are not a problem using the
existing unique_future.
Why the performance and implementation costs of any fixes to
the above are acceptable.
At present, I am happier with the proposal as it stands than with
the suggestions that you have made. While I like benefits of your
suggestions, I dislike their consequences more. If you can change
the consequences, I will be even happer to change the proposal.
--
Lawrence Crowl
More information about the cpp-threads
mailing list