#ensure: What would you expect?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

#ensure: What would you expect?

Tobias Pape
Dear All,

given the following class:

Object subclass: #Foo
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Foo'!
a
        self b: [^ 1].! !

b: aBlock

        [self c: aBlock] ensure: [^ 2].

c: aBlock

        aBlock value.
        ^ 3

And you would do

Foo new a

what would you expect?

I am very curious.
Please, first guess, then execute.

Best
        -Tobias





Foo.st (755 bytes) Download Attachment
PGP.sig (251 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: #ensure: What would you expect?

Bert Freudenberg

On 02.12.2011, at 15:18, Tobias Pape wrote:

> Dear All,
>
> given the following class:
>
> Object subclass: #Foo
>        instanceVariableNames: ''
>        classVariableNames: ''
>        poolDictionaries: ''
>        category: 'Foo'!
> a
>        self b: [^ 1].! !
>
> b: aBlock
>
>        [self c: aBlock] ensure: [^ 2].
>
> c: aBlock
>
>        aBlock value.
>        ^ 3
>
> And you would do
>
> Foo new a
>
> what would you expect?
>
> I am very curious.
> Please, first guess, then execute.
>
> Best
> -Tobias
>
>
> <Foo.st>


I expected two possible outcomes (because putting a return in the ensure block is unusual).

But what it actually answers is surprising.

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: #ensure: What would you expect?

Andreas.Raab
In reply to this post by Tobias Pape
There is only one possibly correct answer which is raising
BlockCannotReturn, because we're trying to return while we're in the
midst of returning already, so there is no place to return to. That
answer is implemented by the attached change set.

BTW, the code duplication between ContextPart>>restart
ContextPart>>resume:, ContextPart>>unwindTo:, and Process>>terminate
bothers me greatly. The change set only fixes one of these locations
(the one triggered by your problem statement) but having such critical
code duplicated all over the places can't be good. Any takers?

Cheers,
   - Andreas

On 12/2/2011 15:18, Tobias Pape wrote:

> Dear All,
>
> given the following class:
>
> Object subclass: #Foo
>          instanceVariableNames: ''
>          classVariableNames: ''
>          poolDictionaries: ''
>          category: 'Foo'!
> a
>          self b: [^ 1].! !
>
> b: aBlock
>
>          [self c: aBlock] ensure: [^ 2].
>
> c: aBlock
>
>          aBlock value.
>          ^ 3
>
> And you would do
>
> Foo new a
>
> what would you expect?
>
> I am very curious.
> Please, first guess, then execute.
>
> Best
> -Tobias
>
>
>
>
>
>



ContextPart-resume.st (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: #ensure: What would you expect?

Bert Freudenberg
On 02.12.2011, at 17:17, Andreas Raab wrote:

> There is only one possibly correct answer which is raising BlockCannotReturn

+1

- Bert -

> , because we're trying to return while we're in the midst of returning already, so there is no place to return to. That answer is implemented by the attached change set.
>
> BTW, the code duplication between ContextPart>>restart ContextPart>>resume:, ContextPart>>unwindTo:, and Process>>terminate bothers me greatly. The change set only fixes one of these locations (the one triggered by your problem statement) but having such critical code duplicated all over the places can't be good. Any takers?
>
> Cheers,
>  - Andreas
>
> On 12/2/2011 15:18, Tobias Pape wrote:
>> Dear All,
>>
>> given the following class:
>>
>> Object subclass: #Foo
>>         instanceVariableNames: ''
>>         classVariableNames: ''
>>         poolDictionaries: ''
>>         category: 'Foo'!
>> a
>>         self b: [^ 1].! !
>>
>> b: aBlock
>>
>>         [self c: aBlock] ensure: [^ 2].
>>
>> c: aBlock
>>
>>         aBlock value.
>>         ^ 3
>>
>> And you would do
>>
>> Foo new a
>>
>> what would you expect?
>>
>> I am very curious.
>> Please, first guess, then execute.
>>
>> Best
>> -Tobias
>>
>>
>>
>>
>>
>>
>
> <ContextPart-resume.st>




Reply | Threaded
Open this post in threaded view
|

Re: #ensure: What would you expect?

Nicolas Cellier
2011/12/2 Bert Freudenberg <[hidden email]>:
> On 02.12.2011, at 17:17, Andreas Raab wrote:
>
>> There is only one possibly correct answer which is raising BlockCannotReturn
>
> +1
>
> - Bert -
>

I didn't and don't want to look into the implementation...
My own expectations for (firstBlock ensure: secondBlock) are:
1) firstBlock is executed first and secondBlock is executed just after
2) secondBlock gets executed even if firstBlock has a non local return
(this happens during stack unwinding)
3) secondBlock is executed in the context sending  #ensure:
4) the result of (firstBlock ensure: secondBlock) is that of (firstBlock value)

If secondBlock has a non local return, It violates rule 4), is this acceptable?

If answer is no, then don't bother, this means we should never honour
a non local return outside the context executing #ensure: from within
the ensure block (or any other unwind block).
This would be my favourite answer but maybe there are other subtle
implications in exception handlers... (can they contain a non local
return ?).

If answer is yes, then we have to handle the conflict when both blocks
have a non local return, which is the case you submitted.
Should we give priority to firstBlock or secondBlock or raise an
exception ? The later seems wise... Maybe a bit nasty to explain.
Though, if we remove rule 4), since we execute secondBlock during the
unwind we can as well preempt non local return and ^2 in the senders
of #b:.
In which case execution will continue in #a and answer a Foo, which
has a certain logic.
I did not browse nor execute anything, but read the answer other
obtained, so consider that I'm a cheater.

Nicolas


>> , because we're trying to return while we're in the midst of returning already, so there is no place to return to. That answer is implemented by the attached change set.
>>
>> BTW, the code duplication between ContextPart>>restart ContextPart>>resume:, ContextPart>>unwindTo:, and Process>>terminate bothers me greatly. The change set only fixes one of these locations (the one triggered by your problem statement) but having such critical code duplicated all over the places can't be good. Any takers?
>>
>> Cheers,
>>  - Andreas
>>
>> On 12/2/2011 15:18, Tobias Pape wrote:
>>> Dear All,
>>>
>>> given the following class:
>>>
>>> Object subclass: #Foo
>>>         instanceVariableNames: ''
>>>         classVariableNames: ''
>>>         poolDictionaries: ''
>>>         category: 'Foo'!
>>> a
>>>         self b: [^ 1].! !
>>>
>>> b: aBlock
>>>
>>>         [self c: aBlock] ensure: [^ 2].
>>>
>>> c: aBlock
>>>
>>>         aBlock value.
>>>         ^ 3
>>>
>>> And you would do
>>>
>>> Foo new a
>>>
>>> what would you expect?
>>>
>>> I am very curious.
>>> Please, first guess, then execute.
>>>
>>> Best
>>>      -Tobias
>>>
>>>
>>>
>>>
>>>
>>>
>>
>> <ContextPart-resume.st>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: #ensure: What would you expect?

Eliot Miranda-2
In reply to this post by Andreas.Raab


On Fri, Dec 2, 2011 at 8:17 AM, Andreas Raab <[hidden email]> wrote:
There is only one possibly correct answer which is raising BlockCannotReturn, because we're trying to return while we're in the midst of returning already, so there is no place to return to. That answer is implemented by the attached change set.

BTW, the code duplication between ContextPart>>restart ContextPart>>resume:, ContextPart>>unwindTo:, and Process>>terminate bothers me greatly. The change set only fixes one of these locations (the one triggered by your problem statement) but having such critical code duplicated all over the places can't be good. Any takers?

The first thing is a good set of tests.  Do we have some of them?  Clearly we don't have them for this case.  What's the scope of the tests?

The second thing I find related is that I find ContextPart>jump incomprehensible and worrying.  Using simulation machinery to advance execution just seems wrong with me and yet this code is used in process termination (via runUntilErrorOrReturnFrom:) and in exception handling (via ContextPart>restart).  ContextPart>jump is extremely complex and slow and buggy (I recently ( eem 11/16/2011 10:58) found and fixed a bad bug in runUntilErrorOrReturnFrom: that was causing too much peeling back of the stack in exception delivery when trying to advance a process to a particular point suitable for presenting to the user.  If we could simplify this code that would be a relief to me :)

The third thing that is related is that if a process is terminated from a different process, then unwinds execute in the context of the process that initiated the termination, not the process being terminated.

The fourth thing that is related in my mind is that Cog supports a much faster Mutex which is in use in OpenQwaq and could be ported to Squeak and Pharo.  But it needs some work on process termination, to avoid losing a signal when a process is terminated while in a critical section on the mutex.  This is related because fixing this requires some work on unwind implementation.

I think all of these need addressing, but they shouldn't be conflated.  I'm just writing them down here so they don't get forgotten.

cheers,
Eliot


Cheers,
 - Andreas


On 12/2/2011 15:18, Tobias Pape wrote:
Dear All,

given the following class:

Object subclass: #Foo
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Foo'!
a
        self b: [^ 1].! !

b: aBlock

        [self c: aBlock] ensure: [^ 2].

c: aBlock

        aBlock value.
        ^ 3

And you would do

Foo new a

what would you expect?

I am very curious.
Please, first guess, then execute.

Best
       -Tobias













--
best,
Eliot