                 task = combinedTask
             }
         }
+        
+        tracker.addTracking(progress: progress, completion: completion)
+        spinLock(&lock) { self.tasks["\(unsafeAddressOf(task))"] = tracker }
         return task
     }
     
-    public func taskForURL(url: NSURL, progress: DownloadProgressHandler?, completion: DownloadCompletionHandler) -> Task {
+    public func trackerForTask(task: Task) -> TaskTracker? {
+        var tracker: TaskTracker?
+        spinLock(&lock) { tracker = self.tasks["\(unsafeAddressOf(task))"] }
+        return tracker
+    }
+    
+    private func removeTracker(task: Task) {
+        spinLock(&lock){ self.tasks.removeValueForKey("\(unsafeAddressOf(task))") }
+    }
+    
+    private func taskForURL(url: NSURL, progress: DownloadProgressHandler?, completion: DownloadCompletionHandler) -> Task {
         let sessionTask = session.downloadTaskWithURL(url)
         sessionTask.taskDelegate = TaskDelegate(url: url, progress: progress, completion: completion)
         sessionTask.resume()

    }
}


private func notifyProgressInvalid(progress: DownloadProgressHandler?) {
    let metric = PTInvalidDownloadProgressMetric
    progress?((metric, metric, metric))
}

// MARK: - sharedDownloader
public var sharedDownloader: Downloader = {
    return DefaultDownloader()
}()


// MARK: - DefaultDownloader
public class DefaultDownloader: Downloader {

                    if let diskURL = cache?.diskURLForCachedURL(url), data = NSData(contentsOfURL: diskURL) {
                        dispatch_sync(queue) {
                            if combinedTask.cancelled {
                                tracker.notifyProgress(PTInvalidProgressInfo)
                                tracker.notifyCompletion(.Cancelled(url: url))
                            } else {
                                let length = Int64(data.length)
                                tracker.notifyProgress((length, length ,length))
                                tracker.notifyCompletion(.Success(url: url, data: data))
                            }
                            self?.removeTracker(task)
                        }
                    } else {
                        dispatch_sync(queue) {
                            if !combinedTask.cancelled {
                                combinedTask.sessionTask = taskGenerator(url: url,
                                    progress: { c, tr, te in
                                        tracker.notifyProgress((c, tr, te))
                                    },
                                    completion: { result in
                                        let _ = combinedTask // just keep task's live
                                        if case .Success(let url, let data) = result {
                                            cache?.cache(url, data: data)
                                        } else {
                                            tracker.notifyProgress(PTInvalidProgressInfo)
                                        }
                                        tracker.notifyCompletion(result)
                                        self?.removeTracker(task)
                                })
                            } else {
                                tracker.notifyProgress(PTInvalidProgressInfo)
                                tracker.notifyCompletion(.Cancelled(url: url))
                                self?.removeTracker(task)
                            }
                        }
                    }
