private EventSetImpl removeUnfiltered(long timeout)
                                               throws InterruptedException {
        EventSetImpl eventSet = null;

        /*
         * Make sure the VM has completed initialization before
         * trying to build events.
         */
        vm.waitInitCompletion();

        synchronized(this) {
            if (!eventSets.isEmpty()) {
                /*
                 * If there's already something there, no need
                 * for anything elaborate.
                 */
                eventSet = (EventSetImpl)eventSets.removeFirst();
            } else {
                /*
                 * If a timeout was specified, create a thread to
                 * notify this one when a timeout
                 * occurs. We can't use the timed version of wait()
                 * because it is possible for multiple enqueue() calls
                 * before we see something in the eventSet queue
                 * (this is possible when multiple threads call
                 * remove() concurrently -- not a great idea, but
                 * it should be supported). Even if enqueue() did a
                 * notify() instead of notifyAll() we are not able to
                 * use a timed wait because there's no way to distinguish
                 * a timeout from a notify.  That limitation implies a
                 * possible race condition between a timed out thread
                 * and a notified thread.
                 */
                TimerThread timerThread = null;
                try {
                    if (timeout > 0) {
                        timerThread = startTimerThread(timeout);
                    }

                    while (shouldWait(timerThread)) {
                        this.wait();
                    }
                } finally {
                    if ((timerThread != null) && !timerThread.timedOut()) {
                        timerThread.interrupt();
                    }
                }

                if (eventSets.isEmpty()) {
                    if (closed) {
                        throw new VMDisconnectedException();
                    }
                } else {
                    eventSet = (EventSetImpl)eventSets.removeFirst();
                }
            }
        }

        // The build is synchronized on the event set, don't hold
        // the queue lock.
        if (eventSet != null) {
            target.notifyDequeueEventSet();
            eventSet.build();
        }
        return eventSet;
    }