On Fri, Jan 2, 2009 at 4:48 PM, Chouser <chou...@gmail.com> wrote:
>
> 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.

Thanks Chris! Your explanation makes a lot of sense. I'll change the
code as you suggested and put up a new version soon.

-- 
R. Mark Volkmann
Object Computing, Inc.

--~--~---------~--~----~------------~-------~--~----~
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