public Object removeWait(long timeout) throws QueueClosedException, TimeoutException {
        synchronized(mutex) {
            if(closed)
                throw new QueueClosedException();

            final long end_time=System.currentTimeMillis() + timeout;
            long wait_time, current_time;

            /*if the queue size is zero, we want to wait until a new object is added*/
            while(size == 0 && (current_time=System.currentTimeMillis()) < end_time) {
                if(closed)
                    throw new QueueClosedException();
                try {
                    /*release the mutex lock and wait no more than timeout ms*/
                    wait_time=end_time - current_time;  // guarnteed to be > 0
                    mutex.wait(wait_time);
                }
                catch(InterruptedException ex) {
                }
            }
            /*we either timed out, or got notified by the mutex lock object*/
            if(closed)
                throw new QueueClosedException();

            /*get the next value*/
            Object retval=removeInternal();
            /*null result means we timed out*/
            if(retval == null) throw new TimeoutException("timeout=" + timeout + "ms");

            return retval;
        }
    }