         }
     }
 
+    /// Accesses the data associated with the given key for reading and writing.
+    ///
+    /// When you assign a new data for a key and the key already exists, the cache
+    /// overwrites the existing data.
+    ///
+    /// When assigning or removing data, the subscript adds a requested operation
+    /// in a staging area and returns immediately. The staging area allows for
+    /// reading and writing data in parallel.
+    ///
+    ///     // Schedules data to be written asynchronously and returns immediately
+    ///     cache[key] = data
+    ///
+    ///     // The data is returned from the staging area
+    ///     let data = cache[key]
+    ///
+    ///     // Schedules data to be removed asynchronously and returns immediately
+    ///     cache[key] = nil
+    ///
+    ///     // Data is nil
+    ///     let data = cache[key]
+    ///
+    subscript(key: Key) -> Data? {
+        get {
+            return cachedData(for: key)
+        }
+        set {
+            if let data = newValue {
+                storeData(data, for: key)
+            } else {
+                removeData(for: key)
+            }
+        }
+    }
+
     // MARK: Managing URLs
 
     /// Uses the `FilenameGenerator` that the cache was initialized with to

        return try? Data(contentsOf: url)
    }

    private func _setData(data: Data, for key: Key) {
        _lock.sync {
            let change = _staging.add(data: data, for: key)
            _wqueue.async {

    /// Retrieves data for the given key. The completion will be called
    /// syncrhonously if there is no cached data for the given key.
    public func cachedData(for key: Key) -> Data? {
        _lock.lock()

        if let change = _staging.change(for: key) {
