public int cancel( Task task ) throws InterruptedException
    {
        m_lock.lock();
        try
        {
            for (;;)
            {
                final TimerInfo timerInfo = m_timers.get( task );
                if (timerInfo == null)
                {
                    /* Timer already canceled or was not scheduled. */
                    if (s_logger.isLoggable( Level.FINER))
                        s_logger.log( Level.FINER, System.identityHashCode(task) + ": not registered" );
                    return -1;
                }

                assert( timerInfo.task == task );

                if (timerInfo.threadID == Thread.currentThread().getId())
                {
                    /* Cancel from the timer callback */
                    return -1;
                }
                else if (timerInfo.threadID == 0)
                {
                    /* Timer is not fired yet */
                    if (s_logger.isLoggable( Level.FINER))
                        s_logger.log( Level.FINER, System.identityHashCode(task) + ": canceled" );
                    removeTimerLocked( timerInfo );
                    return 0;
                }
                else if (timerInfo.threadID == -2)
                {
                    /* Timer just fired */
                    if (s_logger.isLoggable(Level.FINER))
                        s_logger.log( Level.FINER, System.identityHashCode(task) + ": canceled, just fired" );
                    assert( timerInfo.cond != null );
                    timerInfo.cond = null;
                    m_timers.remove( task );
                    return 0;
                }
                else
                {
                    /* Timer is being executed now, let's wait */
                    Condition cond = timerInfo.cond;
                    if (cond == null)
                    {
                        cond = m_lock.newCondition();
                        timerInfo.cond = cond;
                    }
                    cond.await();
                }
            }
        }
        finally
        {
            m_lock.unlock();
        }
    }