Help fixing a ConcurrentModificationException

edited October 2013 in Questions about Code

Hi,

I'm getting a ConcurrentModificationException and regardless all my efforts to solve the problem I fail, let me explain what I'm doing:

1- Particles are created when the user clicks or drag the mouse

void addNumberAt(float _mx, float _my) {
  color dye = gui.getColorPickerValue();
  NumberParticle np = new NumberParticle(numbers.size(), dye, _mx, _my);
  if (isCanvasNameSet) {
    np.belongsToTitle = true;
  }
  numbers.add(np);
}

This NumberParticles consist of 2 VerletParticle2D and 1 VerletSpring2D

NumberParticle(int _id, color _dye, float _mx, float _my) {
  anchor = new VerletParticle2D(new Vec2D(_mx, _my));
  world.addParticle(anchor);
  world.addBehavior(new AttractionBehavior2D(anchor, repulsiveForceRadius, -repulsiveForce, repulsiveForceJitter));
  anchor.lock();

   label = new VerletParticle2D(new Vec2D(_mx, _my).addSelf(Vec2D.randomVector().scale(5)));
   world.addParticle(label);
   world.addBehavior(new AttractionBehavior2D(label, repulsiveForceRadius, -repulsiveForce, repulsiveForceJitter));

   spring = new VerletSpring2D(anchor, label, numberSpringAnchorLength, numberSpringAnchorStrength);
   world.addSpring(spring);
 }

public void kill() {
    // anchor.removeAllBehaviors();
    // label.removeAllBehaviors();
    world.removeSpringElements(spring);
    // world.removeSpring(spring);
    // world.removeParticle(anchor);
    // world.removeParticle(label);
  }

2- NumberParticles can also be added when the user adds a name so a bunch of NumberParticles are added at once using the same addNumberAt() method

3- There is a button to remove the last NumberParticle like a Undo button, it flags the item os it can be remove from the list on the next draw loop

void removeNumber() {
  ListIterator<NumberParticle> it = numbers.listIterator(numbers.size());
  if (it.hasPrevious()) {
    NumberParticle p = (NumberParticle)it.previous();
    // p.kill();
    // it.remove();
    p.readyToDelete = true;
  }
}

4- There is also a button to remove all the NumberParticles at once from the name, it flags all the NumberParticles so they can be remove in the next draw loop

void removeTitleNumbers() {
  for (ListIterator it = numbers.listIterator(numbers.size()); it.hasPrevious();) {
    NumberParticle p = (NumberParticle)it.previous();
    if (p.belongsToTitle) {
      // p.kill();
      // it.remove();
      p.readyToDelete = true;
    }
  }
}

5- Main draw() here is what happens in the main loop

void draw() {
    world.update();
    updateNumberParticleProperties();

    startPDFexport();
    if (showDotToDotLine && !enableSavePDF) {
      renderDotToDotLine();
    }
    renderNumbers(numberTextSize, numberAnchorPointSize);
}


void updateNumberParticleProperties() {
    // Update physics world attraction behaviour force radius
    for (Iterator b = world.behaviors.iterator(); b.hasNext();) {
      AttractionBehavior2D att = (AttractionBehavior2D)b.next();
      att.setRadius(repulsiveForceRadius);
    }
}


void renderNumbers(int _textSize, float _anchorSize) {
  textAlign(CENTER);
  textSize(numberTextSize);

  for (ListIterator it = numbers.listIterator(); it.hasNext();) {
    NumberParticle np = (NumberParticle)it.next();
    if (np.readyToDelete) {
      np.kill();
      it.remove();
    }
    else {
      np.numberTextSize = _textSize;
      np.anchorRadius = _anchorSize;
      np.render();
    }
  }
}


void renderDotToDotLine() {
  noFill();
  stroke(60);
  strokeWeight(2);

  beginShape();
  for (ListIterator<NumberParticle> it = numbers.listIterator(); it.hasNext();) {
    VerletParticle2D p = (VerletParticle2D)it.next().anchor;
    vertex(p.x, p.y);
  }
  endShape();
}

So what happens?

The error happens very random when removing NumberParticles, I know I'm iterating in different places for NumberParticles and the VerletPhysics2D particles and springs in different places, and the error seems to be then the physics engine does not sync when I remove elements from it, but I dont know how to bullet proof when I need to delete particles and springs from the simulation

Any help will much appreciated!

Oh here is the error I get:

Caused by: java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) at java.util.AbstractList$Itr.remove(AbstractList.java:357) at DotToDot13.renderNumbers(DotToDot13.java:352) at DotToDot13.draw(DotToDot13.java:187) at processing.core.PApplet.handleDraw(PApplet.java:2305) at processing.opengl.PGL$PGLListener.display(PGL.java:2601) at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:588) at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:572) at javax.media.opengl.awt.GLCanvas$7.run(GLCanvas.java:1054) at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1034) at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:909) at javax.media.opengl.awt.GLCanvas$8.run(GLCanvas.java:1065) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:715) at java.awt.EventQueue.access$400(EventQueue.java:82) at java.awt.EventQueue$2.run(EventQueue.java:676) at java.awt.EventQueue$2.run(EventQueue.java:674) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86) at java.awt.EventQueue.dispatchEvent(EventQueue.java:685) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Could not run the sketch (Target VM failed to initialize). Finished.Make sure that you haven't set the maximum available memory too high.

Answers

  • http://stackoverflow.com/questions/12487915/removing-an-item-from-a-list-using-listiterator

    specifically the bit in answer 1 about adding whilst removing (which i think is possible because of the "Particles are created when the user clicks or drag the mouse" thing)

  • edited October 2013

    Difficult but you need to separate out the update logic from the rendering logic.

    First iI would register the pre method in setup with

    registerMethod("pre", this);

    and create the method with

    void pre(){

    }

    This method is always executed just before the draw() method so is a great place to update the physics engine.

    I also suggest that you have two global lists

    (1) a list of all NumberParticles that have been created since the last call to pre()

    (2) a list of all NumberParticles that have been marked for removal since the last call to pre()

    NumberParticles can be safely added to these lists from anywhere in the sketch (e.g. mouseClicked, mouseMoved, keyTyped etc) because these lists are only iterated over in the pre method.

    The pre method would

    (1) iterate over the death list removing each NumberParticle from the Physics engine in turn

    (2) iterate over the born list adding each NumberParticle to the physics engine in turn

    (3) clear both the death and birth lists

    (4) any other updating of NumberParticles (if any)

    (5) world.update()

    This leaves the draw(0 method the sole responsibility or rendering the particles.

    HTH

  • Interesting! I will give it a shot

Sign In or Register to comment.