     if task = @queuedTasks.shift()
       @runThisTask(task)
 
-  reuseLock: (lock, task) ->
-    unless lock == @currentLock
+  reuseLock: (task) ->
+    unless lock == @currentTask?.lock
       throw new Error('Lock expired')
 
     # Don't set @currentTask, it's already occupied by the task that
     # originally retrieved the lock.
 
-    return @callTask(task)
+    return task.start()
 
   queueTask: (task) ->
     task = u.previewable(task)
     @queuedTasks.push(task)
-    return task.promise
 
   runThisTask: (task) ->
     @currentTask = task
-    @currentLock = u.uid()
 
-    returnValue = @callTask(Task)
+    task.start()
 
     if u.isPromise(returnValue)
       u.always(returnValue, @taskDone)
     else
       @taskDone()
 
-    return returnValue
-
-  callTask: (task) ->
-    task.call(@currentLock)
-
   taskDone: =>
     @currentTask = null
-    @currentLock = null
     u.microtask(@poke)
 
-  cancelAll: ->
-    throw "implement me"
+  abortAll: ->
+    @abort({})
+
+  abort: (conditions) ->
+    candidates = u.compact([@currentTask, @queuedTasks...])
+
+    for task in candidates
+      if task.matches(conditions)
+        task.abort()

u = up.util

class up.TaskQueue2


  reset: ->
    @queuedTasks = []
    @currentTask = null

  asap: (args...) ->
    task = up.Task.fromAsapArgs(args)

    if task.lock
      @reuseLock(task)
    else if @isBusy()
      @queueTask(task)
    else
      @runThisTask(task)

    return task.promise


  isBusy: ->
    !!@currentTask
