     while descriptor = @dequeueNextDescriptor()
       descriptor.callback.apply(undefined)
 
+  invalidateThreshold: ->
+    @nextThreshold = 0
+
+  updateThreshold: ->
+    @nextThreshold = Number.POSITIVE_INFINITY
+    for callback in @callbackDescriptors
+      @nextThreshold = Math.min( @nextThreshold, callback.registrationTime + callback.interval )
+
   invalidateBeatLength: ->
     for descriptor in @callbackDescriptors
       if descriptor.interval.hasValueInBeats()
         descriptor.interval = descriptor.interval.beats()
+    @invalidateThreshold()
 
 
 # All timer DSL functions (every, until, after) are called with an instance of

  registerCallback: (callback, interval, isLoop=false) ->
    id = @lastId++
    @callbackDescriptors.push { id: id, callback: callback, interval: interval, registrationTime: @time, isLoop: isLoop }
    id

  unregisterCallback: (id) ->
    i = 0 # Manual loop since all coffeescript iterators cache array.length
    while i < @callbackDescriptors.length
      descriptor = @callbackDescriptors[i]
      if descriptor.id == id
        @callbackDescriptors.splice i, 1
        i--
      i++

  # Find next elegible timer. If a loop, re-queue after firing.
  dequeueNextDescriptor: ->
    for descriptor, i in @callbackDescriptors
      fireThreshold = descriptor.registrationTime + descriptor.interval
      if fireThreshold <= @time
        if descriptor.isLoop
          descriptor.registrationTime = fireThreshold
        else

    @time = 0 # Initialize to 0 so any callers using getTime() can correctly
              # perform offset math.

    # This is an optimization that allows us to skip most calls to
    # fireCallbacks(). Maintain the lowest time threshold of our descriptors and
    # sleep until that time is reached.
    @nextThreshold = 0

  getTime: ->
    @time

