mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-15 13:43:43 +01:00
Fixes #98 (deadlock when merge happens while main queue is querying)
This commit is contained in:
@@ -101,8 +101,8 @@ internal extension NSManagedObjectContext {
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
internal func saveSynchronously() -> SaveResult {
|
||||
|
||||
internal func saveSynchronously(mergeSynchronously: Bool = true) -> SaveResult {
|
||||
|
||||
var result = SaveResult(hasChanges: false)
|
||||
|
||||
self.performBlockAndWait {
|
||||
@@ -114,7 +114,7 @@ internal extension NSManagedObjectContext {
|
||||
|
||||
do {
|
||||
|
||||
self.isSavingSynchronously = true
|
||||
self.isSavingSynchronously = mergeSynchronously
|
||||
try self.save()
|
||||
self.isSavingSynchronously = nil
|
||||
}
|
||||
@@ -131,7 +131,7 @@ internal extension NSManagedObjectContext {
|
||||
|
||||
if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
|
||||
|
||||
switch parentContext.saveSynchronously() {
|
||||
switch parentContext.saveSynchronously(mergeSynchronously) {
|
||||
|
||||
case .Success:
|
||||
result = SaveResult(hasChanges: true)
|
||||
|
||||
@@ -59,7 +59,33 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
|
||||
self.result = result
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Saves the transaction changes and waits for completion synchronously, but merges into the main context asynchronously. This method should not be used after the `commit()` method was already called once.
|
||||
|
||||
This method can be used to avoid potential deadlocks that can arise when a background thread attempts to merge changes into the main context while the main queue is querying from that context. Note that this
|
||||
introduces a possibility that the main thread can attempt to query for the changes before the asynchronous merge operation has happened.
|
||||
|
||||
- returns: a `SaveResult` containing the success or failure information
|
||||
*/
|
||||
public func commit() -> SaveResult {
|
||||
|
||||
CoreStore.assert(
|
||||
self.transactionQueue.isCurrentExecutionContext(),
|
||||
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
|
||||
)
|
||||
CoreStore.assert(
|
||||
!self.isCommitted,
|
||||
"Attempted to commit a \(cs_typeName(self)) more than once."
|
||||
)
|
||||
|
||||
self.isCommitted = true
|
||||
|
||||
let result = self.context.saveSynchronously(false)
|
||||
self.result = result
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user