[squeak-dev] Future examples (Re: Inbox: #future keyword for asynchronous message invocation)

Colin Putney cputney at wiresong.ca
Thu Dec 17 22:13:19 UTC 2009


On 2009-12-17, at 1:28 PM, Andreas Raab wrote:

> Using timed future: messages
> ============================
> Now let's look at the implementation when using a timed future instead:
> 
> ScrollBar>>scrollDownInit
>  downButton borderInset.
>  keepScrolling := true.
>  self doScrollDown: 200. "i.e., delay1"
> 
> ScrollBar>>doScrollDown: delay
>  "keep scrolling as long as the mouse is down"
>  self setValue: (value + scrollDelta + 0.000001 min: 1.0).
>  keepScrolling ifTrue:[
>    (self future: delay) doScrollDown: (delay * 9 // 10 max: 40). "delay2"
>  ].
> 
> That's it. No #step, no #stepTime, no #wantsSteps, no #waitForDelay etc. Just a message shot into the future by a few milliseconds. We call the above pattern "recursion in time" since it sends messages recursively to itself at some later point in time.

We want these future sends to happen in the Morphic UI process, so the Morphic implementation of #future (via #futureDo:at:args:) implements this via #addDeferredUIMessage: ? Is there some process that waits on a delay and then queues the deferred UI message?

> Using non-timed future messages
> ===============================
> And if you don't like that pattern, there's an interesting alternative using non-timed futures and rather an explicitly forked block:
> 
> ScrollBar>>scrollDownInit
>  downButton borderInset.
>  keepScrolling := true.
>  [self doScrollDown] fork.
> 
> ScrollBar>>doScrollDown
>  "keep scrolling as long as the mouse is down"
>  delay := 200.
>  [keepScrolling] whileTrue:[
>    self future setValue: (value + scrollDelta + 0.000001 min: 1.0).
>    (Delay forMilliseconds: delay) wait.
>    delay := delay * 9 // 10 max: 40. "delay2"
>  ].
> 
> (the example has a small bug which I'll ignore for educational reasons - if you can spot it you're good ;-)

I'll take that as a challenge. :-) I assume that If the mouse button is released then keepScrolling will be set to false.  If the button is then pressed again before the delay wakes up, you'll have two processes doing the scrolling. It would seem that they'd cause scrolling to happen twice as fast. 

> In this example we use an untimed future message to synchronize the scrolling loop with the foreground morphic process. It's not quite as elegant as the first example but illustrates one of the primary uses for future messages - lock-free interprocess communication. Future messages allow you to use concurrency in cases where it would be very hard to synchronize with locks - in the above I would have to guard all the modifications of the scrollbar's value by some lock but using the future message allows us to introduce a level of concurrency that would be difficult to achieve otherwise.

Pretty interesting. I'm a bit ambivalent about a magic compiler change like this, but you make a pretty strong case for it's usefulness.

Colin


More information about the Squeak-dev mailing list