[cpp-threads] Asynchronous Execution Issues

Boehm, Hans hans.boehm at hp.com
Sat Apr 25 00:09:19 BST 2009


 

> -----Original Message-----
> From: cpp-threads-bounces at decadentplace.org.uk 
> [mailto:cpp-threads-bounces at decadentplace.org.uk] On Behalf 
> Of Lawrence Crowl
> Sent: Friday, April 24, 2009 1:39 PM
> To: C++ threads standardisation
> Cc: Bjarne Stroustrup
> Subject: [cpp-threads] Asynchronous Execution Issues
> 
> At the Summit meeting I took the action item of producing a 
> proposal for a simple asynchronous execution.  The idea was 
> to facilities, with an API along the lines of:
> 
>     auto x = std::creating_async( function1 );
>     auto y = std::caching_async( function2 );
>     ....
>     auto a = x.get();
>     auto b = y.get();
> 
> The difference between the two is that creating_async would 
> always create a new thread, while the caching_async is 
> permitted to reuse threads.  The primary operational 
> difference is that thread-local storage is reused in the latter case.
> 
> There are a couple of issues that make the task more 
> difficult than we thought at the time.  As a result, I have a 
> couple of questions.
> 
> First, consider the case of the caching_async.  Because the 
> threads may persist, we need a handle on the list of threads 
> so that we can inform a thread to die so that we destroy any 
> thread-local variables before the global variables that they 
> reference.  So, we start needing a manager object, and the 
> whole facility is starting to look too much like a thread 
> pool.  I don't feel as though I have a mandate to propose 
> anything that looks like a thread pool.  Do you agree?
I agree.  But that may not mean much, since I wasn't enthusiastic about this anyway.  This feels to me like a fairly ugly optimization to address performance issues that may also be addressable by just working on the implementation of creating_async.

> 
> Second, consider the case of the creating_async.  The problem 
> here is a touch more subtle.  In particular, once the working 
> thread has set its promise, it can start destroying 
> thread-local variables.
> Unfortunately, we have no idea when that has or might happen.
> That thread could be stalled immediately after providing the value.
> The solution is to wait for thread termination before 
> returning the value from the future.  This solution implies 
> keeping the thread as part of the future so that we can wait. 
>  We have no such mechanism.
> So, an asynchronous execution function needs another kind of future.
> Is such a future going beyond my mandate?
Interesting and disconcerting observation.

Is there any reason to believe that if the current future doesn't work for this, it works for anything else?  My inclination would be to fix what's there, if it's broken.

This sounds to me like a serious problem in the current draft, which is highlighted by creating_async.  It's not something we should work around in creating_async.

I'm not quite sure I understand exactly which one of several problem scenarios you're worried about here.  Presumably the child thread sets the promise, and then exits without additional library calls.  I think the intent was to make a thread that behaves this way (i.e. that makes a synchronization call to the library to indicate it is done and then exits) safe in the sense that it is guaranteed not to race with destruction of static objects needed by the standard library (guarantee A).  I can no longer find a statement to that effect.  But I think we need such a guarantee if we ever want to safely shut down a detached thread (in the sense of making it safe to call exit() rather than quick_exit()).

Without destructors for thread_local variables, I think this can be made to work.  But I'm not sure that guarantee A is acheivable in the presence of arbitrary thread_local destructors, at least the way we had envisioned.

And even if we fix this case (by having exit() wait for detached threads ???), I'm still worried about destructors for thread locals that refer to automatic variables on the parent stack.  I think most people's reaction is "don't do that".  But I'm not convinced it can reasonably be avoided, if I have nontrivial destructors for thread_locals at all.

Hans
 
> 
> --
> Lawrence Crowl
> 
> --
> cpp-threads mailing list
> cpp-threads at decadentplace.org.uk
> http://www.decadentplace.org.uk/cgi-bin/mailman/listinfo/cpp-threads
> 


More information about the cpp-threads mailing list