Concurrent Futures
Andreas Raab
andreas.raab at gmx.de
Mon Oct 29 20:05:45 UTC 2007
Igor Stasenko wrote:
>> Indeed. However, this is where E really helps you. Everything you can
>> express in E is by definition deadlock-free (in the classic sense) so
>> you stop worrying about these things and focus more on the solution to
>> the problem at hand. Not so different to manual memory management where
>> before the advent of GC you always had that nagging feeling in the back
>> of your head saying "and who's gonna know when and where to free that
>> reference?". The point is that as GC issues become tractable by not
>> causing a segfault, concurrency issues become tractable by not having
>> your system come to a screaching halt every time something goes wrong.
>>
> I'm not really sure, that GC example is good parallel for 'automatic
> deadlock-free'.
> What prevents me (or anyone) to write a deadlocks like following:
> [ self grabFork ] whileFalse: ["do nothing " ]
I know this can be hard to grok, but the above is sort of the equivalent
of asking "how do I free an object in Smalltalk". It doesn't make sense
in the way you are asking the question, because in the above you assume
that #grabFork is a remote message returning a value. In E (and Croquet)
remote message invocations *do not return values* they return promises
(futures) which get resolved only *after* the current message is
completed. In other words, writing a loop like this:
p := self future doSomething.
[p isResolved] whileFalse.
will *never* get passed that line. Not once, not ever. So in order to do
what you are trying to do you need to write it like here:
p := self future doSomething.
p whenComplete:[:value| ...].
Which allows the message invoking the above to complete, and once the
promise is resolved, the associated resolver block will be executed as a
new message. BTW, the above *does* allow you to write a recursion
similar to what you were trying to do in the above, e.g.,
getMyFork
table future grabFork whenComplete:[:haveIt|
haveIt ifFalse:[self getMyFork]. "retry"
].
but it is still deadlock-free since there is no wait involved (neither
"classic" nor "busy-wait). In fact, we use recursions like the above in
various places in Croquet.
> There is no such language (except from ones, which don't have
> loops/branches) which prevents from writing this. And the example
> above is 'busy waiting' which is even worser than waiting using
> semaphores, because it wasting CPU resources for evaluating same
> expression until some state will change by external entity.
You can *write* it, but it makes about as much sense as writing "Object
new free". Because the promise will not resolve, not ever, while you are
"busy-waiting" (just as the object will not get freed when you send the
free message or assign nil to a slot) so you'll very quickly abstain
from that practice ;-)
> So, unless a developer writes a better code, we will have same issues.
Absolutely not. See above. There is no deadlock in it.
> As for GC - you have automatic memory management instead of manual.
> But there's no automatic algorithm management and never will be ,
> given any language :)
And what's that supposed to mean?
Cheers,
- Andreas
More information about the Squeak-dev
mailing list
|