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