Boost logo

Boost :

Subject: Re: [boost] [thread] terminating destructor
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2012-10-25 03:56:40


2012/10/24 Vicente J. Botet Escriba <vicente.botet_at_[hidden]>

> Le 24/10/12 13:35, Andrzej Krzemienski a écrit :
>
> 2012/10/14 Andrzej Krzemienski <akrzemi1_at_[hidden]>
>>
>>
>>> 2012/10/14 Vicente J. Botet Escriba <vicente.botet_at_[hidden]>
>>>
>>> Le 13/10/12 23:17, Andrzej Krzemienski a écrit :
>>>
>>>> 2012/10/13 Vicente J. Botet Escriba <vicente.botet_at_[hidden]>
>>>>
>>>>> I guess you are referring to the case the std::future is created by
>>>>> async
>>>>>
>>>>>> 0.
>>>>>>
>>>>>> If the implementation chooses the launch::async policy,
>>>>>>
>>>>>> *
>>>>>>
>>>>>> — a call to a waiting function on an asynchronous return
>>>>>> object
>>>>>> that shares the shared state created
>>>>>>
>>>>>> by this async call shall block until the associated thread
>>>>>> has
>>>>>> completed, as if joined (30.3.1.5);
>>>>>>
>>>>>>
>>>>>> C++ International Standard Otherwise
>>>>>>
>>>>>> ~std::future();
>>>>>> Effects:
>>>>>> — releases any shared state (30.6.4);
>>>>>> — destroys *this.
>>>>>>
>>>>>> Could you explain me what waiting function is called on the future
>>>>>> destructor that needs to block until the completion of the associated
>>>>>> thread?
>>>>>>
>>>>>> It is not any waiting function mentioned explicitly. It is the
>>>>> requirement
>>>>> in 30.6.8 para 5: "If the implementation chooses the launch::async
>>>>> policy,
>>>>> [...] the associated thread completion synchronizes with the return
>>>>> from
>>>>> the first function that successfully detects the ready status of the
>>>>> shared
>>>>> state or with the return from the last function
>>>>> that releases the shared state, whichever happens first."
>>>>>
>>>>> Why the future destructor should be the last function that release
>>>>> the
>>>>>
>>>> shared state?
>>>>
>>>
>>> Indeed, it doesn't have to be the destructor. I misinterpret this
>>> requirement. Sorry. I no longer claim that future's destructor blocks in
>>> this case. Although, others (like Herb) seem to claim that. I will
>>> investigate that.
>>>
>>> Or perhaps future destructor IS the last function that release the
>> shared
>> state. When we call async() two threads are involved: our 'master' thread
>> and a newly launched thread. Whatever function(s) releases the shared
>> state
>> it has to do it from one of the two threads. The last release cannot be
>> made from the 'launched' thread because 'launched' thread completion
>> synchronizes with the last release. So the last release has to be
>> performed
>> from the 'master' thread. And what other operation in the 'master' thread
>> apart from future's destructor can release the state?
>>
>>
>> You are right, but in this case there is no problem to block as the
> future is already ready.

I believe that when you are saying "there is no problem", you are referring
to the following situation:

master thread | launched thread
-------------------------+---------------------------
 async call >-- sync --> start executing
 ... | ...
 ... (other stuff) | ... (other stuff)
 ... | ...
 future dtor start | release state
   release state <-- sync -- finished execution
 future dtor end |

(please use fixed-size font to display this ASCII-Art diagram) In such
case, where the the launched thread finishes faster than the master thread
the blocking in ~future will be a no-time. But if the launched thread takes
longer, we have the following situation (and a noticable block):

master thread | launched thread
-------------------------+---------------------------
 async call >-- sync --> start executing
 ... | ...
 ... (other stuff) | ... (other stuff)
 ... | ...
 future dtor start | ...
   (blocked) | ...
                         | ...
                         | ...
                         | release state
   release state <-- sync -- finished execution
 future dtor end |

The third situation below shows a non blocking ~future. But such execution
is *disallowed *by the standard because the completion of launched thread
would not synchronize with the last release of the shared state.

master thread | launched thread
-------------------------+---------------------------
 async call >-- sync --> start executing
 ... | ...
 ... (other stuff) | ... (other stuff)
 ... | ...
 future dtor start | ...
   release state | ...
 future dtor end | ...
                         | ...
                         | release state
                         | finished execution

Regards,
&rzej


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk