What would Squeak be like without non-local returns

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

Re: What would Squeak be like without non-local returns

Mathieu SUEN
By the way I have a suggestion for the #class and #==.
Instead of building a new VM you could patch the compiler to avoid  
emitting the bytecodePrimEquals...
So people can just use you code without having a compiled VM.

HTH
        Mth



On Nov 7, 2007, at 2:13 AM, Rob Withers wrote:

>
> ----- Original Message ----- From: "Mathieu Suen"  
> <[hidden email]>
> To: "The general-purpose Squeak developers list" <squeak-
> [hidden email]>
> Sent: Tuesday, November 06, 2007 5:10 PM
> Subject: Re: What would Squeak be like without non-local returns
>
>
>> eventual refs?
>
> This is what I am hoping to build: http://wiki.squeak.org/squeak/6011
> This also describes some of what I was trying to do: http://
> wiki.squeak.org/squeak/2410
>
> The canonical source for this is here: http://www.erights.org.  I  
> am reading Mark Miller's thesis, which is excellent.
>
> Rob
>


Reply | Threaded
Open this post in threaded view
|

RE: What would Squeak be like without non-local returns

Ron Teitelbaum
In reply to this post by Ralph Johnson
Hi Ralph,

That is not quite right.

What would this return?

[^3] fork.
^4.

(It is the same thing).

Ron Teitelbaum

> -----Original Message-----
> From: [hidden email] [mailto:squeak-dev-
> [hidden email]] On Behalf Of Ralph Johnson
> Sent: Wednesday, November 07, 2007 6:26 AM
> To: The general-purpose Squeak developers list
> Subject: Re: What would Squeak be like without non-local returns
>
> Consider the code
>
> object eventual: [...  ^3]
> ...
> ^4
>
> Depending on the missing code, it could return either 3 or 4.  If not,
> something is very strange, and the language is no longer Smalltalk.
>
> If you get rid of non-local returns, the language is no longer
> Smalltalk.  it might be a good language, but it is not Smalltalk.
>
> -Ralph



Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Andreas.Raab
In reply to this post by Ralph Johnson
Ralph Johnson wrote:
> Consider the code
>
> object eventual: [...  ^3]
> ...
> ^4
>
> Depending on the missing code, it could return either 3 or 4.  If not,
> something is very strange, and the language is no longer Smalltalk.

Not at all. Eventual/future sends introduce a new unit of concurrency
and the only thing we're arguing is whether that second unit of
concurrency will be executed before the first one. In E/Croquet this is
not possible, but it is really no different from, e.g.,

Object>>foo
   [^3] forkAt: Processor activePriority-1.
   ^4

When you run this, it will return 4 (every time) and fall over the
non-local return later (every time).

Cheers,
   - Andreas


Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Rob Withers
In reply to this post by Andreas.Raab

----- Original Message -----
From: "Andreas Raab" <[hidden email]>
To: "The general-purpose Squeak developers list"
<[hidden email]>
Sent: Tuesday, November 06, 2007 9:38 PM
Subject: Re: What would Squeak be like without non-local returns


> Rob Withers wrote:
>> Well, now I can't find that statement, but I was sure I had read it on
>> erights or Mark's thesis.  I searched and found nothing.  It may have
>> been a statement regarding eventual-sending specifically with non-local
>> return.  It IS strange thinking about the correct behavior of an
>> expression:
>>
>> object eventual ifTrue: [^3].
>> ^4
>>
>> What should be the result?
>
> Without any question, 4. Since ifTrue:[] is sent eventual it will return
> immediately (answering a promise), and the method will continue and return
> 4. There is absolutely no question about it.
>
> When the eventual ifTrue: is executed it will barf because it will try to
> return from a method with no home but that's the way out-of-scope blocks
> go. It's just as well-defined as a non-local return from an out-of-scope
> block today, e.g.,
>
> Foo>>createBlock
>   ^[^self]
>
> Foo>>callBlock
>   self createBlock value.
>
> This will simply signal BlockCannotReturn and the eventual ifTrue:[]
> will - and should - do the same.

This makes that percieved problem of non-local returns with eventual sending
just go away.  I am totally convinced.

The only difference I have at the moment, is that instead of getting an
unhandled BlockCannotReturn exception thrown, SqueakElib instead catches the
exception and resolves the promise for the eventually send #ifTrue: to be a
broken ref.  Since that promise was never utilized, it quietly goes away -
it never opens the notifier.  I am torn whether this is the correct thing to
do.

Cheers,
Rob

>
> Cheers,
>   - Andreas
>
>


Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Rob Withers
In reply to this post by Mathieu SUEN

----- Original Message -----
From: "Mathieu Suen" <[hidden email]>
To: "The general-purpose Squeak developers list"
<[hidden email]>
Sent: Wednesday, November 07, 2007 3:42 AM
Subject: Re: What would Squeak be like without non-local returns


> By the way I have a suggestion for the #class and #==.
> Instead of building a new VM you could patch the compiler to avoid
> emitting the bytecodePrimEquals...
> So people can just use you code without having a compiled VM.
>

I have actually decided that #== and #class are protocol belonging to the
reference and not to be eventually sent.  So I disabled the VM changes I
made in this regard.   I see now that I am more familiar with the Compiler,
that I could patch the compiler to make these msg sends, rather than
bytecodes and if I change my mind about these, that is definitely that
approach to take.

There is a need for an #eventuallyEquals: operation, when the distributed
stuff is added back in to the framework.  Object a holds Object b from Vat
B, and Object c calls Object a with a remote reference to Object b, called
b'.  b should equal b'.

Since I no longer need vm changes for #== and #class, the only current
changes I have are for the Larger Contexts (80) and for the extra long
jumps, added to support the combined macros I added to the compiler for
#ifTrue:, #whileTrue: and so on.  I still haven't gotten those changes to be
stable.

As the roadmap on http://wiki.squeak.org/squeak/6011 describes, I plan on
protecting primitives to allow them to have eventual arguments.  This would
entail vm changes.  Finally, supporting messaging between vats may entail vm
changes, which I attempted last week but failed.  I tried to add a word to
every object header, but it kept crashing on me.

So, in summary, vm changes are possible for:
    - support Compiler changes for combined macros
    - protecting Primitives from eventual arguments
    - support messaging between multiple vats

Cheers,
Rob


Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Ralph Johnson
In reply to this post by Andreas.Raab
On 11/7/07, Andreas Raab <[hidden email]> wrote:

> Ralph Johnson wrote:
> > Consider the code
> >
> > object eventual: [...  ^3]
> > ...
> > ^4
> >
> > Depending on the missing code, it could return either 3 or 4.  If not,
> > something is very strange, and the language is no longer Smalltalk.
>
> Not at all. Eventual/future sends introduce a new unit of concurrency
> and the only thing we're arguing is whether that second unit of
> concurrency will be executed before the first one. In E/Croquet this is
> not possible, but it is really no different from, e.g.,
>
> Object>>foo
>    [^3] forkAt: Processor activePriority-1.
>    ^4
>
> When you run this, it will return 4 (every time) and fall over the
> non-local return later (every time).

But that wasn't what I said.  Your code is different from mine.  Note the ...

For example,

Object >>foo
  [^3] fork.
  self halt.
  ^ 4

returns 3.

Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Igor Stasenko
On 08/11/2007, Ralph Johnson <[hidden email]> wrote:

> On 11/7/07, Andreas Raab <[hidden email]> wrote:
> > Ralph Johnson wrote:
> > > Consider the code
> > >
> > > object eventual: [...  ^3]
> > > ...
> > > ^4
> > >
> > > Depending on the missing code, it could return either 3 or 4.  If not,
> > > something is very strange, and the language is no longer Smalltalk.
> >
> > Not at all. Eventual/future sends introduce a new unit of concurrency
> > and the only thing we're arguing is whether that second unit of
> > concurrency will be executed before the first one. In E/Croquet this is
> > not possible, but it is really no different from, e.g.,
> >
> > Object>>foo
> >    [^3] forkAt: Processor activePriority-1.
> >    ^4
> >
> > When you run this, it will return 4 (every time) and fall over the
> > non-local return later (every time).
>
> But that wasn't what I said.  Your code is different from mine.  Note the ...
>
> For example,
>
> Object >>foo
>   [^3] fork.
>   self halt.
>   ^ 4
>
> returns 3.
>
This is all about same: what to do with two(or more) return values,
where we expecting one.

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Rob Withers
In reply to this post by Ralph Johnson

----- Original Message -----
From: "Ralph Johnson" <[hidden email]>
To: "The general-purpose Squeak developers list"
<[hidden email]>
Sent: Wednesday, November 07, 2007 9:55 PM
Subject: Re: What would Squeak be like without non-local returns


> On 11/7/07, Andreas Raab <[hidden email]> wrote:
>> Ralph Johnson wrote:
>> > Consider the code
>> >
>> > object eventual: [...  ^3]
>> > ...
>> > ^4
>> >
>> > Depending on the missing code, it could return either 3 or 4.  If not,
>> > something is very strange, and the language is no longer Smalltalk.
>>
>> Not at all. Eventual/future sends introduce a new unit of concurrency
>> and the only thing we're arguing is whether that second unit of
>> concurrency will be executed before the first one. In E/Croquet this is
>> not possible, but it is really no different from, e.g.,
>>
>> Object>>foo
>>    [^3] forkAt: Processor activePriority-1.
>>    ^4
>>
>> When you run this, it will return 4 (every time) and fall over the
>> non-local return later (every time).
>
> But that wasn't what I said.  Your code is different from mine.  Note the
> ...
>
> For example,
>
> Object >>foo
>  [^3] fork.
>  self halt.
>  ^ 4
>
> returns 3.

No, this halts, on the calling Process, and signals a BlockCannotReturn
Error, on the forked Process, presumably because the returnContext is nil.
Without the halt and with any number of statements (...), it would return 3.

Rob


Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Andreas.Raab
In reply to this post by Ralph Johnson
Hi Ralph -

Sorry, I thought it was clear that I was giving conceptual answer. But
if you need a literal one, here it is:

TestIsland>>initialize
   eventQueue := SharedQueue new.
   eventQueue nextPut:[self foo].
   self runEventLoop.

TestIsland>>runEventLoop
   [true] whileTrue:[eventQueue next value]

TestIsland>>foo
   eventLoop nextPut:[^3].
   self halt.
   ^4

This will result in 4 being returned from foo unless you introduce a
different model of concurrency. In any case, neither of my examples
qualifies for "the language is no longer Smalltalk" which was my point.

Cheers,
   - Andreas

Ralph Johnson wrote:

> On 11/7/07, Andreas Raab <[hidden email]> wrote:
>> Ralph Johnson wrote:
>>> Consider the code
>>>
>>> object eventual: [...  ^3]
>>> ...
>>> ^4
>>>
>>> Depending on the missing code, it could return either 3 or 4.  If not,
>>> something is very strange, and the language is no longer Smalltalk.
>> Not at all. Eventual/future sends introduce a new unit of concurrency
>> and the only thing we're arguing is whether that second unit of
>> concurrency will be executed before the first one. In E/Croquet this is
>> not possible, but it is really no different from, e.g.,
>>
>> Object>>foo
>>    [^3] forkAt: Processor activePriority-1.
>>    ^4
>>
>> When you run this, it will return 4 (every time) and fall over the
>> non-local return later (every time).
>
> But that wasn't what I said.  Your code is different from mine.  Note the ...
>
> For example,
>
> Object >>foo
>   [^3] fork.
>   self halt.
>   ^ 4
>
> returns 3.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Jason Johnson-5
In reply to this post by Rob Withers
I think you guys are over complicating this.  Return to a home context
from a future doesn't make any sense and should just toss an error, as
returning to a home context that no longer exist does now.

E style futures are basically some code asking a process somewhere
else to do something, and giving you the ability to attach a callback
for when the other process is finished.  I don't think it make sense
to have the remote code return to some context that isn't in it's
address space, and allowing home context returns in the callback is
certainly a bad idea, as the home context should not still be around
when the callback runs.

On Nov 7, 2007 5:00 AM, Rob Withers <[hidden email]> wrote:

>
> ----- Original Message -----
> From: "Igor Stasenko" <[hidden email]>
>
> >> Knowing we have blocks in play within the execution of a method, we say
> >> we
> >> want to synchronize the execution of the method and not run it
> >> eventually.
> >> How do we do this?
> >>
> >
> >
> > Ok, lets look again on the problem.
> > Consider a code:
> > --
> > f := object future doSomeThing: someBlock.
> > a := a + 1.
> > f doSomeThingElse.
> > --
> >
> > Semantically, if block (someBlock) does non-local return, that means
> > that next statements should not be evaluated at all means, because
> > this could lead to unpredictable behavior.
>
> Does it mean this?  Because this violates the rule that there should be no
> blocking.   Msgs should just be sent.  Maybe the rule in play is that
> someBlock does a non-local return that is no longer valid, because it was
> scheduled eventually outside the scope of the method it could return from,
> so it should cause an Error and the return value of doSomeThing: is a broken
> ref.    A way out of this pickle?
>
>
> > But there is no ways how to prevent that:
> > - any piece of code in #doSomeThing: can send a message to object(s)
> > which lead to execution of non-local returns or throwing an exception
> > causing stack unwinding.
>
> Ok, but if what I just said holds, then the unwinding terminates where the
> msg was eventually sent and never gets to interact with the sending context.
>
>
> > This means that if you using futures/promises in your code, you can't
> > make this code to be semantically equivalent as with not using them.
>
> I think that's true.
>
> > In that way, i think, its better to think of how to prevent obvious
> > pitfalls and give developer a clear ways how to use eventual refs
> > safely or teach them (in some manner), that writing a code with
> > futures is something different than writing same code in imperative
> > fashion.
>
> Yes, it is not transparent.   On the other hand, any ref could be eventual.
> So the rules for how they behave in various imperative situations are
> important.  As to how to write our example clearly, in the eventual style:
>
> f := object future doSomeThing: someBlock.
> f whenResolved: [:fVow |
>     a := a + 1.
>     fVow doSomeThingElse].
>
> Rob
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: What would Squeak be like without non-local returns

Kjell Godo
In reply to this post by Andreas.Raab
Hi Andreas

I would like to learn about this Croquet futures business.
And in so doing I would like to try to document it better.
Is this possible?
Where can I look for information?
Are there any isolated tests that I could step through?
Is there anyone who would be willing to teach me edit me?
Where could I put the new documentation?
I think the best way to teach people how futures work inside would
be to construct a sequence of tests that progress from simple
to more complex and that can be run on a single machine.
By stepping through these tests and documenting the methods
that show up along the way the implementation details can be
shown.  By putting each of the common usages into a test
you can also show how futures should be used from a user's
point of view starting with simple usage and moving on to
complex usage.  Such tests would not need to be single
stepped if the only purpose was to learn usages.  If the
implementation was to be learned then stepping could be done.
I give an example of how such things could work in the picoLARC
project on sourceforge.net for Dolphin Smalltalk community
edition 6.  You make a sequence of tests that run one after the
other.  These tests document usage and implementation in an
active way that doesn't go out of date.

Most people hate to make documentation.  I do not.  I like it.

What do you think?
Where is the info I need?
How can I upload the documentation that I make?
How can I upload new test sequences and the extra
    method documentations I will put into the methods that
    that show up along the way?
Who will edit me?

-Kjell
picoVerse

by the way there are a lot of ambiguous terms below that
I would like to make more concrete in the documentation
I attempt to make.

On Nov 7, 2007 12:31 AM, Andreas Raab <[hidden email]> wrote:

> Igor Stasenko wrote:
> > On 07/11/2007, Andreas Raab <[hidden email]> wrote:
> >> Same answer (though strictly speaking you may get an error that you
> >> can't *wait* in an eventual system).
> > This doesn't change anything, you may put:
> > (1 to: 1000000 atRandom) do: [1+1]
> > instead of delay.
>
> Sure. But it makes no difference. I was only pointing this out for
> completeness.
>
> > Hmm. An example above was to show that when running in parallel there
> > is equal chance to get to ^3 or ^4 first.
>
> No, there isn't. It's simply not how it works. This code cannot run in
> parallel because it's on the same island (necessarily so for non-shared
> state concurrency since blocks have access to receiver variables) and
> can therefore *not* be executed in parallel. The order is completely
> deterministic - scheduling the message in the future *guarantees* that
> it will be executed only after the ^4 has completed. It can't be any
> other way for it to work; if you'd want to run it in parallel you'd need
> to copy it to a different island first in which case the return value
> from the method would *still* be 4! It's completely deterministic, the
> result is 4.
>
> > And in previous message you described behavior, when running code gets
> > to ^4 first. But what if it gets to ^3 first?
>
> It cannot. It simply cannot. If you don't understand why, then you don't
> fully understand how E and Croquet works. The block is created in the
> same island as the receiver. When it is passed to another island (as
> argument to the future ifTrue: message) it will be converted into a
> remote reference. This reference only understands future messages (all
> the immediate messages relate entirely to its role as a reference not
> the underlying object) which is the reason why I distinguished these
> cases in the True>>ifTrue: code (simply because #value on a remote
> reference has no bearing on executing the block that this reference
> points to but scheduling a future value message does).
>
> This in turn means that the second island (the one containing the
> boolean) *must schedule* the future #value with the first island which
> means that the first island will only execute it after the ^4 has been
> executed. It is the *only* way in which this can work in an event-loop
> environment.
>
> What happens is something like here:
>
> Island A:                                     Island B:
> ->message starts running
>   -> aBool future ifTrue:[] ..... -> .....  <schedules True>>ifTrue:>
>   -> Delay wait
>
>                        ... time passes ...
>            <at this point Island A is running the message>
>            <and Island B has the #ifTrue: message scheduled>
>
>                                                -> executes True>>ifTrue:
>    <schedules aBlock value>   ..... <- .....   <- aBlock future value
>                                                -> True>>ifTrue: finishes
>
>                      .... time passes ....
>             <Island A is still not finished with the delay>
>             <Island B has posted the eventual #value to Island A>
>
>   -> Delay wait ends.
>   -> message returns 4
> -> message completes
>
>        <Now, and *only* now the pending #value call will be executed>
>
> -> aBlock value starts
>    -> Attempts to [^3]
>    -> Raises BlockCannotReturn
>
>
> The result is 4. Each and every time.
>
> Cheers,
>   - Andreas
>
>

12