         }
     }
     
-    private func addObserverForName(name: String, object: AnyObject? = nil, closure: (NSNotification!) -> Void) {
-        let observer = NSNotificationCenter.defaultCenter().addObserverForName(name, object: object ?? self, queue: nil, usingBlock: closure)
+    private func addObserverForName(name: String, object: AnyObject, closure: (NSNotification!) -> Void) {
+        let observer = NSNotificationCenter.defaultCenter().addObserverForName(name, object: object, queue: nil, usingBlock: closure)
         self.observers.append(observer)
     }
     
 }
 
-extension Context {
-    
-    internal func executeAsynchronousFetchRequestWithFetchRequest(fetchRequest: NSFetchRequest, completionHandler: ([AnyObject]?, NSError?) -> Void) -> FetchAsyncHandler {
-        //
-        var completionHandlerCalled = false
-        
-        //
-        let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in
-            if !completionHandlerCalled {
-                completionHandlerCalled = true
-                completionHandler(asynchronousFetchResult.finalResult, asynchronousFetchResult.operationError)
-            }
-        }
-        
-        //
-        let handler = FetchAsyncHandler(asynchronousFetchRequest: asynchronousFetchRequest)
-        
-        //
-        var error: NSError? = nil
-        if handler.cancelled {
-            completionHandlerCalled = true
-            completionHandler(nil, NSError(domain: "com.alecrim.AlecrimCoreData", code: NSUserCancelledError, userInfo: nil))
-        }
-        else {
-            handler.foolProgress.becomeCurrentWithPendingUnitCount(1)
-            handler.asynchronousFetchResult = self.executeRequest(asynchronousFetchRequest, error: &error) as? NSAsynchronousFetchResult
-            handler.foolProgress.resignCurrent()
-            
-            if error != nil {
-                completionHandlerCalled = true
-                completionHandler(nil, error)
-            }
-            else if handler.asynchronousFetchResult?.operationError != nil {
-                completionHandlerCalled = true
-                completionHandler(nil, handler.asynchronousFetchResult!.operationError)
-            }
-        }
-        
-        //
-        return handler
-    }
-    
-    internal func executeBatchUpdateRequestWithEntityDescription(entityDescription: NSEntityDescription, propertiesToUpdate: [NSObject : AnyObject], predicate: NSPredicate, completionHandler: (Int, NSError?) -> Void) {
-        let batchUpdateRequest = NSBatchUpdateRequest(entity: entityDescription)
-        batchUpdateRequest.propertiesToUpdate = propertiesToUpdate
-        batchUpdateRequest.predicate = predicate
-        batchUpdateRequest.resultType = .UpdatedObjectsCountResultType
-        
-        //
-        // HAX:
-        // The `executeRequest:` method for a batch update only works in the root saving context.
-        // If called in a context that has a parent context, both the `batchUpdateResult` and the `error` will be quietly set to `nil` by Core Data.
-        //
-        
-        var moc: NSManagedObjectContext = self
-        while moc.parentContext != nil {
-            moc = moc.parentContext!
-        }
-        
-        moc.performBlock {
-            var error: NSError? = nil
-            
-            if let batchUpdateResult = moc.executeRequest(batchUpdateRequest, error: &error) as? NSBatchUpdateResult, let count = batchUpdateResult.result as? Int {
-                completionHandler(count, nil)
-            }
-            else {
-                completionHandler(0, error ?? alecrimCoreDataError())
-            }
-        }
-    }
-    
-}
-
-private class RootSavingDataContext: Context {
-    
-    private static let genericError = alecrimCoreDataError()
-    private static let savedChildContextUserInfoKey = "com.alecrim.AlecrimCoreData.DataContext.SavedChildContext"
-    
-    private let rootSavingDataContextOptions: ContextOptions
-    
-    private let childDataContextHashTable = NSHashTable.weakObjectsHashTable()
-    private var childDataContexts: [NSManagedObjectContext] { return self.childDataContextHashTable.allObjects as! [Context] }
-    
-    private var savedChildContext: NSManagedObjectContext? {
-        get {
-            return self.userInfo![RootSavingDataContext.savedChildContextUserInfoKey] as? NSManagedObjectContext
-        }
-        set {
-            if newValue == nil {
-                self.userInfo!.removeObjectForKey(RootSavingDataContext.savedChildContextUserInfoKey)
-            }
-            else if self.savedChildContext == nil { // do not assign if previous value is not nil
-                self.userInfo![RootSavingDataContext.savedChildContextUserInfoKey] = newValue
-            }
-        }
-    }
-    
-    private init(rootSavingDataContextOptions: ContextOptions) {
-        self.rootSavingDataContextOptions = rootSavingDataContextOptions
+// MARK: - root saving data context
+
+public class RootSavingContext: BaseContext {
+    
+    private let contextOptions: ContextOptions
+    
+    public init(contextOptions: ContextOptions) {
+        self.contextOptions = contextOptions
         super.init(concurrencyType: .PrivateQueueConcurrencyType)
         
         self.name = "Root Saving Context"

public func performInBackground<T: Context>(parentContext: T, usingNewBackgroundManagedObjectContext: Bool, closure: (T) -> Void) {
    let backgroundContext = createBackgroundContext(parentContext, usingNewBackgroundManagedObjectContext)
    
    backgroundContext.perform {
        closure(backgroundContext)
    }
}

    
}

// MARK: - ChildContext

public class ChildContext: BaseContext {

    // MARK: - private properties
    
    private var enableMergeFromRootSavingContext = true
    
    // MARK: - public properties
    
    public let rootSavingContext: RootSavingContext
    
    // MARK: - init and dealloc
    
    public init(concurrencyType: NSManagedObjectContextConcurrencyType, rootSavingContext: RootSavingContext) {
        self.rootSavingContext = rootSavingContext
        super.init(concurrencyType: concurrencyType)
        
        self.parentContext = self.rootSavingContext
    }

    public required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - public overrided methods

    public override func save(error: NSErrorPointer) -> Bool {
        if !self.hasChanges { return true }
        
        var success = super.save(error)
        
        if success {
            self.rootSavingContext.performBlockAndWait {
                self.enableMergeFromRootSavingContext = false
                success = self.rootSavingContext.save(error)
                self.enableMergeFromRootSavingContext = true
            }
        }
        
        return success
    }
    
    // MARK: - private overrided methods
    
    private override func addObservers() {
        //
        super.addObservers()
        
        //
        // the root data context did save
        self.addObserverForName(NSManagedObjectContextDidSaveNotification, object: self.rootSavingContext) { [unowned self] notification in
            if !self.enableMergeFromRootSavingContext {
                return
            }
            
            if let savedContext = notification.object as? RootSavingContext, let changeNotificationData = notification.userInfo {
                self.performBlock {
                    //
                    let updatedObjects = changeNotificationData[NSUpdatedObjectsKey] as? Set<NSManagedObject>
                    if let updatedObjects = updatedObjects where !updatedObjects.isEmpty {
                        for objectObject in updatedObjects {
                            self.objectWithID(objectObject.objectID).willAccessValueForKey(nil) // ensures that a fault has been fired
                        }
                    }
                    
                    //
                    self.mergeChangesFromContextDidSaveNotification(notification)
                }
            }
        }
    }
    
}

// MARK: - BaseContext extensions

extension BaseContext {
    
    internal func executeAsynchronousFetchRequestWithFetchRequest(fetchRequest: NSFetchRequest, completionHandler: ([AnyObject]?, NSError?) -> Void) -> FetchAsyncHandler {
        //
        var completionHandlerCalled = false
        
        //
        let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in
            if !completionHandlerCalled {
                completionHandlerCalled = true
                completionHandler(asynchronousFetchResult.finalResult, asynchronousFetchResult.operationError)
            }
        }
        
        //
        let handler = FetchAsyncHandler(asynchronousFetchRequest: asynchronousFetchRequest)
        
        //
        var error: NSError? = nil
        if handler.cancelled {
            completionHandlerCalled = true
            completionHandler(nil, NSError(domain: "com.alecrim.AlecrimCoreData", code: NSUserCancelledError, userInfo: nil))
        }
        else {
            handler.foolProgress.becomeCurrentWithPendingUnitCount(1)
            handler.asynchronousFetchResult = self.executeRequest(asynchronousFetchRequest, error: &error) as? NSAsynchronousFetchResult
            handler.foolProgress.resignCurrent()
            
            if error != nil {
                completionHandlerCalled = true
                completionHandler(nil, error)
            }
            else if handler.asynchronousFetchResult?.operationError != nil {
                completionHandlerCalled = true
                completionHandler(nil, handler.asynchronousFetchResult!.operationError)
            }
        }
        
        //
        return handler
    }
    
    internal func executeBatchUpdateRequestWithEntityDescription(entityDescription: NSEntityDescription, propertiesToUpdate: [NSObject : AnyObject], predicate: NSPredicate, completionHandler: (Int, NSError?) -> Void) {
        let batchUpdateRequest = NSBatchUpdateRequest(entity: entityDescription)
        batchUpdateRequest.propertiesToUpdate = propertiesToUpdate
        batchUpdateRequest.predicate = predicate
        batchUpdateRequest.resultType = .UpdatedObjectsCountResultType
        
        //
        // HAX:
        // The `executeRequest:` method for a batch update only works in the root saving context.
        // If called in a context that has a parent context, both the `batchUpdateResult` and the `error` will be quietly set to `nil` by Core Data.
        //
        
        var moc: NSManagedObjectContext = self
        while moc.parentContext != nil {
            moc = moc.parentContext!
        }
        
        moc.performBlock {
            var error: NSError? = nil
            
            if let batchUpdateResult = moc.executeRequest(batchUpdateRequest, error: &error) as? NSBatchUpdateResult, let count = batchUpdateResult.result as? Int {
                completionHandler(count, nil)
            }
            else {
                completionHandler(0, error ?? alecrimCoreDataError())
            }
        }
    }
    
}

// MARK: - public global functions - background contexts

// This functions will be removed in the next major version.

public func createBackgroundContext<T: Context>(parentContext: T, usingNewBackgroundManagedObjectContext: Bool) -> T {
    if usingNewBackgroundManagedObjectContext {
        return T(parentContext: parentContext)
    }
    else {
        return parentContext.defaultCreatedBackgroundContext()
    }
}

public func performInBackground<T: Context>(parentContext: T, closure: (T) -> Void) {
