mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-18 23:44:14 +01:00
Fixes #98 (deadlock when merge happens while main queue is querying)
This commit is contained in:
@@ -10,10 +10,10 @@
|
|||||||
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "F347F55F-7F5C-4476-9148-6E902F06E4AD",
|
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "F347F55F-7F5C-4476-9148-6E902F06E4AD",
|
||||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
|
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
|
||||||
"8B2E522D57154DFA93A06982C36315ECBEA4FA97" : "CoreStoreLibraries\/GCDKit",
|
"8B2E522D57154DFA93A06982C36315ECBEA4FA97" : "CoreStoreLibraries\/GCDKit",
|
||||||
"4B60F1BCB491FF717C56441AE7783C74F417BE48" : "CoreStore"
|
"4B60F1BCB491FF717C56441AE7783C74F417BE48" : "CoreStore\/"
|
||||||
},
|
},
|
||||||
"DVTSourceControlWorkspaceBlueprintNameKey" : "CoreStore",
|
"DVTSourceControlWorkspaceBlueprintNameKey" : "CoreStore",
|
||||||
"DVTSourceControlWorkspaceBlueprintVersion" : 203,
|
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
|
||||||
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CoreStore.xcodeproj",
|
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CoreStore.xcodeproj",
|
||||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
|
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ internal extension NSManagedObjectContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@nonobjc
|
@nonobjc
|
||||||
internal func saveSynchronously() -> SaveResult {
|
internal func saveSynchronously(mergeSynchronously: Bool = true) -> SaveResult {
|
||||||
|
|
||||||
var result = SaveResult(hasChanges: false)
|
var result = SaveResult(hasChanges: false)
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ internal extension NSManagedObjectContext {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
self.isSavingSynchronously = true
|
self.isSavingSynchronously = mergeSynchronously
|
||||||
try self.save()
|
try self.save()
|
||||||
self.isSavingSynchronously = nil
|
self.isSavingSynchronously = nil
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ internal extension NSManagedObjectContext {
|
|||||||
|
|
||||||
if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
|
if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
|
||||||
|
|
||||||
switch parentContext.saveSynchronously() {
|
switch parentContext.saveSynchronously(mergeSynchronously) {
|
||||||
|
|
||||||
case .Success:
|
case .Success:
|
||||||
result = SaveResult(hasChanges: true)
|
result = SaveResult(hasChanges: true)
|
||||||
|
|||||||
@@ -60,6 +60,32 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
|
|||||||
return 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.
|
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