[BUG] Crash while working on a Future.

Tom Phoenix rootbeer at redcat.com
Thu Jun 22 21:08:39 UTC 2006


On 6/22/06, Michael van der Gulik <squeakml at gulik.co.nz> wrote:

> Attached is a change set with actually lets you use the debugger :-).

Thanks. This gave me a better idea about what you were trying to do, I think.

> Run "Future doing: [ByteString]" to crash the image.

Does it have to be ByteString? That's an important class in the
system. It seems to be an arbitrary choice, since it only shows up in
your halt code.

As I understand the operation of #becomeForward:, you're
instantaneously turning your MessageCapture instance into ByteString.
But the identity hash of your instance should stay the same, in case
it's in a dictionary, say. That means that the identity hash of
ByteString changes to become the hash of your object, even though that
can break any dictionaries that *it* was in.

So it would probably break even if you didn't use such an important
class as ByteString.

I'm not sure of the proper way to deal with identity hash invariance
when using #becomeForward:. We're into some serious magic here.
Object>>becomeForward:copyHash: seems to have been implemented to deal
with this sort of thing; though there may be further pitfalls.

Maybe a subclass of ProtoObject and wizardly uses of #become: isn't
the technology you need to use. Have I understood correctly what
you're trying to do? It seems to me that you want an object that is a
placeholder today and the real value tomorrow. That's probably
possible without much magic. But you must ensure that a client doesn't
send messages to the placeholder before it becomes the real value. I
don't see any good way to do that without asking the client to do
something active, such as using a Semaphore, or sending the
placeholder a signal. The trouble I see is that there's no way to tell
when a message to the placeholder is "really" destined for the real
value.

Here's some brainstorming....

  "A client wants to do something while a calculation completes"
  nilNowValLater := Future doing: [ 49 sqrt ].
  nilNowValLater inspect. "It's nil, maybe still"
  self doSomething.
  [ nilNowValLater isNil ] whileTrue. "Bad: Busy wait"
  nilNowValLater inspect. "Now it's 7"

The busy wait is undesirable, since we tie up the processor precisely
when we want it to devote time to the other process. We could put in a
Delay, but let's try a different way.

  stat := Future doing: [ 49 sqrt ].
  stat inspect. "It's an instance of Future"
  self doSomething.
  stat inspect. "It's still an instance of Future"
  stat wait. "stat updates, waiting if needed"
  stat inspect. "Now it's 7"

Now there's no busy wait. In this scheme, Future gives a status object
that can (presumably) be interrogated about the ongoing process, i.e,
whether it's complete or still running. And the status object doesn't
auto-convert; you have to send it #wait. (Because 7 won't necessarily
respond correctly to #wait, at least.) But why do this with a
magically-updating value, since it doesn't even auto-convert? Subtract
the magic and you get this:

  stat := Future doing: [ 49 sqrt ].
  stat inspect. "It's an instance of Future"
  self doSomething.
  stat isDone ifFalse: [ self doSomethingMore ].
  stat result inspect. "gives 7"

Under this metaphor, an instance of Future is the status of the
request, and you have to ask it for the result. Ask whenever you'd
like, but you may have to wait for the answer, if it's not ready yet.
Nothing magically updates, so I don't have to deal with any new
concepts. And it allows code like this:

  "Open an inspector as soon as the network request has returned a value."
  stat := Future doing: [ networkRequest value ].
  stat whenDoneDo: [:result | result inspect ].

  "If time runs out, return a failureToken"
  stat afterTimeoutSeconds: 300 terminateAndDo: [ stat return: self
failureToken ].

  "Another way to handle time-out: cancel the inspection"
  stat afterTimeoutSeconds: 300 terminateAndDo: [ stat abort ].

This seems like a fairly clean and flexible model that would be
relatively easy to implement. Would something like that work for you?

Hope this helps!

--Tom Phoenix



More information about the Squeak-dev mailing list