Re: NSPrivateQueueConcurrencyType working outside of performBlock
On 29 Jul 2015, at 15:35, Trygve Inda cocoa...@xericdesign.com wrote: “Setter methods on queue-based managed object contexts are thread-safe. You can invoke these methods directly on any thread” https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreData Framework/Classes/NSManagedObjectContext_Class/index.html In Apple's example, they use two different contexts, each with their own NSPersistentStoreCoordinator. But the NSPersistentStoreCoordinators each point to the same store file URL. Where is it documented that this works? If the NSPersistentStoreCoordinator instances are separate, how does it actually work when they are both writing to the same store (potentially at the same time)? All Apple's notes say is: To ensure that the application can remain responsive during this operation, the view controller employs a second coordinator to manage interaction with the persistent store. It configures the coordinator to use the same managed object model and persistent store as the main coordinator vended by the stack controller. I can’t recall where it’s documented specifically, but this is supported. The PSCs then rely on SQLite's locking of the file on disk to manage access to it. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
“Setter methods on queue-based managed object contexts are thread-safe. You can invoke these methods directly on any thread” https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreData Framework/Classes/NSManagedObjectContext_Class/index.html In Apple's example, they use two different contexts, each with their own NSPersistentStoreCoordinator. But the NSPersistentStoreCoordinators each point to the same store file URL. Where is it documented that this works? If the NSPersistentStoreCoordinator instances are separate, how does it actually work when they are both writing to the same store (potentially at the same time)? All Apple's notes say is: To ensure that the application can remain responsive during this operation, the view controller employs a second coordinator to manage interaction with the persistent store. It configures the coordinator to use the same managed object model and persistent store as the main coordinator vended by the stack controller. Trygve ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On Jul 28, 2015, at 10:14 AM, Trygve Inda cocoa...@xericdesign.com wrote: On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. However it's quite possible to call the methods directly on the MOC in any thread context and they will work, all the performBlock() actually does is queue the same block of code onto the dispatch queue and when it's its turn, it executes by calling [ moc executeFetch.. blah blah]. If you do that of course you have no thread safety any more and are likely to blow up. In this case there's only one thread (I believe) and so the accesses are serialized anyway and it works. It's a bad piece of code. I filed an enhancement report requesting that the coredata stack assert if you called a private queue MOC method from the wrong queue, I don't recall seeing anything come of it, however I do remember there is quite a lot of logging you can turn up on CoreData and it's possible one such log will tell you you're doing this. If I do use performBlock and have to do several things: This code is sitting inside a completion block for a URL downloader { [self doSomething]; [myContext performBlock (do more stuff)]; [self doSomethingElse]; } Since the perform block will run in a different thread, how can I make sure the do more stuff is finished before calling doSomethingElse? Or in this case would using NSConfinementConcurrencyType be better since it is all within a completion block and presumably on it's own thread anyway. Use performBlockAndWait instead of performBlock. Or do something like (typed into Mail so not checked for syntax) [myContext performBlock:^{ //do whatever operation with myContext // assuming you want doSomethingElse done on main queue dispatch_async(dispatch_get_main_queue(), ^{ [self doSomethingElse]; }); }]; I believe NSConfementConcurrencyType is deprecated so you should not use it for new code. I highly recommend you read through the documentation. https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Referen ce/CoreDataFramework/Classes/NSManagedObjectContext_Class/index.html HTH, Dave Reed performBlockAndWait might work. In my completion handler I have basically: Context = [self createPrivateContect]; For (I = 1; I something ; i++) { ...do stuff with completetion data from URL... ...do stuff with the context... } So I need to make sure the context stuff finishes before the for loop goes onto the next pass through the loop. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
performBlockAndWait might work. In my completion handler I have basically: Context = [self createPrivateContect]; For (I = 1; I something ; i++) { ...do stuff with completetion data from URL... ...do stuff with the context... } So I need to make sure the context stuff finishes before the for loop goes onto the next pass through the loop. What’s wrong with for( i - i ; i something ; i++ ) { moc.performBlock( { … do stuff with completion data .. block which does stuff with the context } ) } nothing says you can only have MOC work in the block or even moc.performBlock( { for( i - i ; i something ; i++ ) { … do stuff with completion data .. do stuff with the context } } ) Which is basically your original code just in a performBlock on the MOC’s private thread. There are other ways too where, if you want to perform the first load of work on one thread and the MOC stuff on the MOC thread, you can do that by putting one iteration in a method or creating a local block which does one iteration with work on one queue, then sends the MOC stuff to the private queue, at the end of the work on the MOC you increment i and if you have another one to do, enqueue the whole thing back on the first thread again. int __block i = 1; void (^myBlock)() = { .. do stuff with completion data moc.performBlock( { .. do stuff with the context if( i++ something ) dispatch_async( myOtherQueue, myBlock ); } } myBlock() I’m sure there’s lots more. You can use performBlockAndWait but rarely need to. All examples typed in mail and I’ve not been using objc for a while so may have my (^) in the wrong place. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On 28 Jul 2015, at 10:14 pm, Trygve Inda cocoa...@xericdesign.com wrote: On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. However it's quite possible to call the methods directly on the MOC in any thread context and they will work, all the performBlock() actually does is queue the same block of code onto the dispatch queue and when it's its turn, it executes by calling [ moc executeFetch.. blah blah]. If you do that of course you have no thread safety any more and are likely to blow up. In this case there's only one thread (I believe) and so the accesses are serialized anyway and it works. It's a bad piece of code. I filed an enhancement report requesting that the coredata stack assert if you called a private queue MOC method from the wrong queue, I don't recall seeing anything come of it, however I do remember there is quite a lot of logging you can turn up on CoreData and it's possible one such log will tell you you're doing this. If I do use performBlock and have to do several things: This code is sitting inside a completion block for a URL downloader { [self doSomething]; [myContext performBlock (do more stuff)]; [self doSomethingElse]; } Since the perform block will run in a different thread, how can I make sure the do more stuff is finished before calling doSomethingElse? Or in this case would using NSConfinementConcurrencyType be better since it is all within a completion block and presumably on it's own thread anyway. Put the [ self doSomethingElse ] inside the block you are performing (do more stuff) as the last thing ie [ self doSomething ] [ myContext performBlock: { do more stuff ; [ self doSomethingElse ] } if you have to flip back to the main thread or another queue, then dispatch_async it back at the end. The beauty of blocks is you can do this, although the indentation gets a bit gnarly. NSConfinementConcurrencyType has had its day and is deprecated in 10.11 so I wouldn't recommend it for new code. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
Depending on what you are doing, you could either put doSomething and doSomethingElse inside the performBlock, or you could use performBlockAndWait On Jul 28, 2015, at 10:14 AM, Trygve Inda cocoa...@xericdesign.com wrote: If I do use performBlock and have to do several things: This code is sitting inside a completion block for a URL downloader { [self doSomething]; [myContext performBlock (do more stuff)]; [self doSomethingElse]; } Since the perform block will run in a different thread, how can I make sure the do more stuff is finished before calling doSomethingElse? Or in this case would using NSConfinementConcurrencyType be better since it is all within a completion block and presumably on it's own thread anyway. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/dave.fernandes%40utoronto.ca This email sent to dave.fernan...@utoronto.ca ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
NSPrivateQueueConcurrencyType working outside of performBlock
I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. Apple has sample code here: https://developer.apple.com/library/mac/samplecode/Earthquakes/History/Histo ry.html#//apple_ref/doc/uid/TP40014547-RevisionHistory-DontLinkElementID_1 That gets a private queue with: NSManagedObjectContext *privateQueueContext(NSError *__autoreleasing *error) { NSPersistentStoreCoordinator *localCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[AAPLCoreDataStackManager sharedManager].managedObjectModel]; if (![localCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[AAPLCoreDataStackManager sharedManager].storeURL options:nil error:error]) return nil; NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [context setPersistentStoreCoordinator:localCoordinator]; context.undoManager = nil; return context; } Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? Trygve ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. However it's quite possible to call the methods directly on the MOC in any thread context and they will work, all the performBlock() actually does is queue the same block of code onto the dispatch queue and when it's its turn, it executes by calling [ moc executeFetch.. blah blah]. If you do that of course you have no thread safety any more and are likely to blow up. In this case there's only one thread (I believe) and so the accesses are serialized anyway and it works. It's a bad piece of code. I filed an enhancement report requesting that the coredata stack assert if you called a private queue MOC method from the wrong queue, I don't recall seeing anything come of it, however I do remember there is quite a lot of logging you can turn up on CoreData and it's possible one such log will tell you you're doing this. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On Jul 28, 2015, at 10:01 AM, Roland King r...@rols.org wrote: On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. However it's quite possible to call the methods directly on the MOC in any thread context and they will work, all the performBlock() actually does is queue the same block of code onto the dispatch queue and when it's its turn, it executes by calling [ moc executeFetch.. blah blah]. If you do that of course you have no thread safety any more and are likely to blow up. In this case there's only one thread (I believe) and so the accesses are serialized anyway and it works. It's a bad piece of code. I filed an enhancement report requesting that the coredata stack assert if you called a private queue MOC method from the wrong queue, I don't recall seeing anything come of it, however I do remember there is quite a lot of logging you can turn up on CoreData and it's possible one such log will tell you you're doing this. As Roland states, it is a bug. You can edit the scheme and add this to the arguments passed on launch and it crashes. -com.apple.CoreData.ConcurrencyDebug 1 http://oleb.net/blog/2014/06/core-data-concurrency-debugging/ Dave Reed ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On Jul 28, 2015, at 10:14 AM, Trygve Inda cocoa...@xericdesign.com wrote: On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. However it's quite possible to call the methods directly on the MOC in any thread context and they will work, all the performBlock() actually does is queue the same block of code onto the dispatch queue and when it's its turn, it executes by calling [ moc executeFetch.. blah blah]. If you do that of course you have no thread safety any more and are likely to blow up. In this case there's only one thread (I believe) and so the accesses are serialized anyway and it works. It's a bad piece of code. I filed an enhancement report requesting that the coredata stack assert if you called a private queue MOC method from the wrong queue, I don't recall seeing anything come of it, however I do remember there is quite a lot of logging you can turn up on CoreData and it's possible one such log will tell you you're doing this. If I do use performBlock and have to do several things: This code is sitting inside a completion block for a URL downloader { [self doSomething]; [myContext performBlock (do more stuff)]; [self doSomethingElse]; } Since the perform block will run in a different thread, how can I make sure the do more stuff is finished before calling doSomethingElse? Or in this case would using NSConfinementConcurrencyType be better since it is all within a completion block and presumably on it's own thread anyway. Use performBlockAndWait instead of performBlock. Or do something like (typed into Mail so not checked for syntax) [myContext performBlock:^{ //do whatever operation with myContext // assuming you want doSomethingElse done on main queue dispatch_async(dispatch_get_main_queue(), ^{ [self doSomethingElse]; }); }]; I believe NSConfementConcurrencyType is deprecated so you should not use it for new code. I highly recommend you read through the documentation. https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/index.html HTH, Dave Reed ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. However it's quite possible to call the methods directly on the MOC in any thread context and they will work, all the performBlock() actually does is queue the same block of code onto the dispatch queue and when it's its turn, it executes by calling [ moc executeFetch.. blah blah]. If you do that of course you have no thread safety any more and are likely to blow up. In this case there's only one thread (I believe) and so the accesses are serialized anyway and it works. It's a bad piece of code. I filed an enhancement report requesting that the coredata stack assert if you called a private queue MOC method from the wrong queue, I don't recall seeing anything come of it, however I do remember there is quite a lot of logging you can turn up on CoreData and it's possible one such log will tell you you're doing this. If I do use performBlock and have to do several things: This code is sitting inside a completion block for a URL downloader { [self doSomething]; [myContext performBlock (do more stuff)]; [self doSomethingElse]; } Since the perform block will run in a different thread, how can I make sure the do more stuff is finished before calling doSomethingElse? Or in this case would using NSConfinementConcurrencyType be better since it is all within a completion block and presumably on it's own thread anyway. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
On 28 Jul 2015, at 9:12 pm, Trygve Inda cocoa...@xericdesign.com wrote: I gather that when using NSPrivateQueueConcurrencyType, all operations (a fetch for example) have to be done within a performBlock call. ... Then later, this context is used outside a performBlock: NSArray *matchingQuakes = [taskContext executeFetchRequest:matchingQuakeRequest error:anyError]; Why does this work? You are supposed to call performBlock so that all accesses to the MOC are serialized on the queue and so you get thread safety that way. So what has to be called though performBlock?? NSManagedObjectContext* privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; // Are these legal to call without using performBlock? [privateContext setPersistentStoreCoordinator:myCoordinator]; [privateContext setUndoManager:nil]; ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSPrivateQueueConcurrencyType working outside of performBlock
“Setter methods on queue-based managed object contexts are thread-safe. You can invoke these methods directly on any thread” https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/index.html On Jul 28, 2015, at 11:49 PM, Trygve Inda cocoa...@xericdesign.com wrote: So what has to be called though performBlock?? NSManagedObjectContext* privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; // Are these legal to call without using performBlock? [privateContext setPersistentStoreCoordinator:myCoordinator]; [privateContext setUndoManager:nil]; ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com