3

I'm having some problems with a Queue in Java. It's declared as follows:

Queue<MotionEvent> touchQueue = new LinkedList<MotionEvent>();

I only add elements in one place (but on a callback, most likely called from a thread):

@Override 
public boolean onTouchEvent(MotionEvent me) {
    touchQueue.add(me);
    return true;
}

And I consume the events on the main Thread with a call to a synchronized function:

public synchronized void UpdateTouches() {
    while(!touchQueue.isEmpty()) {
        try {
            MotionEvent me = touchQueue.poll();
            ProcessTouchEvent(me);
        } catch (NoSuchElementException e) {
            return;
        }
    }
}

The problem is that sometimes poll is rising a NoSuchElementException and after that all subsequent poll calls will raise that Exception.

Anyone has any idea what might be the cause? Or is there any way to remove the head object without getting the Exception again?

Please note that size() returns > 0 when the Exception occurs,

Thanks, /C.

EDIT:

Here is the callstack:

FATAL EXCEPTION: GLThread 302 java.util.NoSuchElementException
    at java.util.LinkedList.removeFirstImpl(LinkedList.java:689)
    at java.util.LinkedList.remove(LinkedList.java:899)
    at com.xxxxx.GG.GGActivity.UpdateTouches(GGActivity.java:718)
    at com.xxxxx.GG.GGView$Renderer.onDrawFrame(GGView.java:414)
    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Force finishing activity

And here is the latest version of the function that generated the log:

public synchronized void UpdateTouches()
{
    //System.out.println("Got touch event" + touchQueue.size());
    while(!touchQueue.isEmpty())
    {
        try {
            MotionEvent me = touchQueue.poll();
            ProcessTouchEvent(me);
        } catch (NoSuchElementException e)
        {
            touchQueue.remove();
            return;
        }

    }
}
Tom
  • 16,842
  • 17
  • 45
  • 54
Sulea Cosmin
  • 598
  • 1
  • 11
  • 24

1 Answers1

1

Calling remove() when you already know the queue is empty doesn't make any sense whatsoever. And catching NoSuchElementException on a method that doesn't throw it, ditto. Just delete all that code.

But your code is not thread-safe. The method that calls add() needs to synchronize on the queue, and the method that calls isEmpty() and poll() ditto, and it should wait on the queue while it is empty.

Or use a java.util.concurrent queue.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I know the documentation states that poll does not throw NoSuchElementException but how does it gets thrown while touchQueue.size() returns positive value and touchQueue.isEmpty() returns false and I only call this from onDrawFrame (I don't have any other mechanism to remove items from queue). I'll try to syncronize the block that adds and see if there's any change. – Sulea Cosmin Jul 03 '14 at 07:32