On Fri, Jan 2, 2009 at 5:20 PM, Mark Volkmann <r.mark.volkm...@gmail.com> wrote:
>
> On Fri, Jan 2, 2009 at 4:04 PM, Chouser <chou...@gmail.com> wrote:
>>
>> I don't feel I have much authority in the realm of designing
>> concurrent programs, but here are a couple thoughts:
>>
>> It seems to me that 'apple' and 'snake' together describe the state of
>> the game, and therefore need their changes coordinated.
>
> I'm thinking their changes don't need to be coordinated. Here's why.
> The only state for an apple is it's color and cell. The color never
> changes. The cell only changes when the snake eats it. That is
> determined in the actionPerformed method which is also responsible for
> triggering movement of the snake, thus changing its state.

But if any other thread were to observe apple and snake immediately
after the apple has been moved (because of a collision), it might be
surprised to find that a moment later the snake has grown even though
the apple was nowhere near it (having already been moved).

Worse yet, suppose some other thread moves the apple, perhaps because
the player is taking too long in driving the snake to it.  If this
were to happen after the collision detection but before the apple is
moved, you'd again get unexpected results.

You can know of course that neither of these will happen because there
are no other threads doing any such thing.  But (1) that may change in
a future version of the program and (2) even as it is this requires
you to reason about the *entire* program, not just the part you're
dealing with at the moment.

Thus I'd argue that for a correct and robust program, you should use
refs for apple and snake, and think carefully about the appropriate
scope for the dosync(s) that you use to modify them.

> actionPerformed is called on the Swing event dispatch thread.

This means that while the "application logic" part of the program is
running, the UI will not respond to user interaction.  Again, this
hardly matters for a toy program, but is something you'd want to avoid
when demonstrating the "right way" to do things.

>> I think it might also be very natural to use a single agent with
>> Thread/sleep and send-off to itself instead of the Timer.  This would
>> detangle the actionPerformed method from the panel, and allow you to
>> give the action function a meaningful name instead.
>
> It would also invalidate what I said above about knowing that the
> actionPerformed code was always being executed from a single thread.
> Do you think it's a good idea to do that anyway?

actionPerformed would no longer be run in the Swing thread, and might
indeed be run in different threads at different times, but as long as
it was always run on the same agent, you're guaranteed that no two
actionPerformed would be run at the same time.  Actions are serialized
for a given agent.

So yes, I'd still say it's a good idea.  Though you would want to use
invokeLater in your new-game function.

--Chouser

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to