adamleesaintfrancis / spacewar

Automatically exported from code.google.com/p/spacewar
0 stars 0 forks source link

Comodification exception JSpacewarComponent.usershadows #3

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. I'm drawing a lot of lines right now, connecting beacons/ships
2. Some of them appear/disappear a lot
3. Sometimes when this happens, some java.util.ComodificationExceptions are
thrown

What is the expected output? What do you see instead?
No exceptions should be generated by drawing/erasing a lot of lines. It
seems that something is modifying the member "usershadows" of
JSpacewarComponent even while the AWT thread is busy drawing it. I mean,
I'm drawing a lot of lines, but I'm only using the
registerShadows/unregisterShadows methods, and I don't even think that I
could be accidentally affecting the List in JSpacewarComponent, because it
seems that some other part of the code has to peel the Shadows out of the
Set in agent and feed them into the List in the component, and it's not
even complaining about changed shadows (not that I'm changing them either),
it's complaining about a changed list.

What version of the product are you using? On what operating system?
The latest off of SVN, Windows XP. 

Please provide any additional information below.
[java] Exception in thread "AWT-EventQueue-0"
java.util.ConcurrentModificationException
     [java] at
java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761)
     [java] at java.util.LinkedList$ListItr.next(LinkedList.java:696)
     [java] at
edu.ou.spacewar.gui.JSpacewarComponent.paintComponent(JSpacewarComponent.java:79
)

Original issue reported on code.google.com by b1m...@gmail.com on 7 Feb 2007 at 7:34

GoogleCodeExporter commented 9 years ago
Dangit, I meant ConcurrentModificationException. It's beig thrown by a method 
called
checkForComodification, but it's called Concurrent...

Original comment by b1m...@gmail.com on 7 Feb 2007 at 7:36

GoogleCodeExporter commented 9 years ago
Question for you (sorry this is late, I forgot to add this page to the list of 
pages that I check daily):  are you 
possibly accidentally setting the pointer to the shadows to null inside 
unregisterShadows()?  I was doing that and 
although the shadows were disappearing, I was getting a lot of exceptions.

Original comment by dramymcg...@gmail.com on 15 Feb 2007 at 3:34

GoogleCodeExporter commented 9 years ago
That wasn't it, but that did lead to my figuring it out. I was attempting to 
maintain
a "new shadows" set and an "old shadows" set, but when it came time to make the 
old
shadows into new shadows, I was copying the reference instead of copying the 
contents
of the set. My bad.

Original comment by b1m...@gmail.com on 15 Feb 2007 at 9:19

GoogleCodeExporter commented 9 years ago
I mean make the new shadows into old shadows

Original comment by b1m...@gmail.com on 15 Feb 2007 at 9:23

GoogleCodeExporter commented 9 years ago
Closing this issue.

Original comment by dramymcg...@gmail.com on 15 Feb 2007 at 10:43

GoogleCodeExporter commented 9 years ago
Wait, no, nevermind. I've returned to my original theory, as what I talked about
above did nothing. Wish I could figure out removing comments...

In JSpaceWarComponent, the List<Shadow2D> usershadows is used in two threads 
without
any sort of syncrhonization. My computer/JDK 1.6 combo for some reason reveals 
this
behavior

Methods JSpacewarComponent.addShadow and removeShadow are called from the main
thread, in World.handleDrawer, which is called in the main event loop, in 
World.run.
After run calls handleDrawer, then calls JSpacewarComponent.repaint (really
Component.repaint). Repaint, according to
http://java.sun.com/products/jfc/tsc/articles/painting/index.html, "registers an
asynchronous request to the AWT that this component needs to be repainted". This
repainting happens in the AWT thread. Then, run calls Thread.sleep(33) (for the 
main
thread), sleeps, wakes up and starts proceessing again, including calling
handleDrawer, which modifies usershadows of the JSpacewarComponent.

In the mean time, in that other (AWT) thread, JSpacewarComponent.paintComponent 
is
called, and uses the fancy "fail-fast" iterator on usershadows. It's this 
iterator
that's causing the error, because for apparently, 33 milliseconds sleep (plus 
the
time to have all the agents act) isn't long enough to stay out of the way on my
computer, and the AWT painter is still running even as the main thread starts
modifying the linked list again. 

My computer does have a fast processor and a slower graphics card, go figure. 
Also,
I'm only running one agent and it's making a simple decision (33 + very small
number), whereas I'm drawing a lot of stuff (apparently >33).

More to the point, sleeping 33 ticks controls the speed of the game, but it's 
not the
best way to control access to that linked list, usershadows. I used
Collections.synchronizedList and synchronized the iteration inside of 
paintComponent,
as per
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html#synchronizedL
ist(java.util.List)
and it works great now. Take that, non-deterministic race condition! Also
synchronized JSpacewarComponent.shadows, for good measure, because it could be
modified in clearAllShadows, but probably less of a big deal. My modified file 
is
attached.

Original comment by b1m...@gmail.com on 15 Feb 2007 at 11:09

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by dramymcg...@gmail.com on 15 Feb 2007 at 11:20

GoogleCodeExporter commented 9 years ago

Original comment by dramymcg...@gmail.com on 15 Feb 2007 at 11:20

GoogleCodeExporter commented 9 years ago
Fix added.  Thank you!

Original comment by jfa...@gmail.com on 16 Feb 2007 at 3:59