[cpp-threads] Asynchronous Function Proposal

Boehm, Hans hans.boehm at hp.com
Mon Jun 8 22:18:34 BST 2009


> From:  Herb Sutter
> [Hans:]
> > Even if exceptions are handled only at the request point, 
> we need to 
> > explicitly allow running the task earlier, since that's visible by 
> > other means.
> 
> What other means? By definition, the task should be 
> independent of the caller, including that it shouldn't take 
> the same locks the caller might take, so it's unclear to me 
> how its side effects could become visible before the join in 
> a correct program. And with as-if + optimizations, we can 
> already execute the task earlier than the join if there are 
> no barriers in between.
We're not prohibiting other synchronization between the tasks.  The tasks can, for example, increment atomic counters.

Nor could we reasonably prevent this sort of thing if we tried.  Library functions may still acquire locks under the covers.  Memory allocation will need to do so, at least occasionally.  Programmers will want to maintain counters for performance measurements, if nothing else.

The issues here are sufficiently complex that I think the best approach is to specify fairly precisely how tasks may be executed and then stick to it.  If we could instead write down specific usage rules for such tasks, that would be OK.  But I have no confidence that we know how to do that.  At least I don't.

> 
> > I would still favor sticking with Lawrence's design that avoids
> > (visibly) reusing threads for multiple tasks.  The issues 
> with thread 
> > locals seem to me to be far more serious for C++ than Java.  On the 
> > other hand, it would be good to set things up so that we can easily 
> > add more policies later.  (I'm assuming that thread locals with 
> > arbitrary destructors are here to stay, though I think we now have 
> > strong arguments on both sides of that issue.)
> > 
> > A more minimalist approach may be to support only the 
> fully_threaded 
> > policy for now, but leave room for additional policies in 
> the future.
> 
> I disagree. We should provide "run on another thread" (not 
> necessarily a new thread!), "run on this thread," and 
> "implementation decides."
> 
This seems to hinge on the thread-locals issue.  (Even if we say "new" thread in the standard, the underlying threads implementation can of course still cache.  The real difference seems to be whether you get new thread_local variables or not.)

I'm still unsure what the programming rules for thread_locals should be.  And without that, it seems to be hard to answer these questions.

I think most people are arguing for an approach in which client code has to be very careful about storing unknown data D with nontrivial destructors into thread_locals, so that we can be sure that D is destroyed while it is still safe to do so, just as you would with static duration variables.  In that case, we might be able to allow running on another thread.

My only problem with this is that it makes it very hard to use thread_locals in generic library code, e.g. to cache the last value I looked up in a map.  Are there still good use cases for thread_locals with non-trivial destructors once we accept this restriction?

Hans


More information about the cpp-threads mailing list