objective c - What does Apple mean when they say that a NSManagedObjectContext is owned by the thread or queue that created it? -


it seems in november, apple updated both nsmanagedobjectcontext class reference , core data programming guide documents explicitly bless serial gcd dispatch queues , nsoperationqueues acceptable mechanisms synchronising access nsmanagedobjectcontext. advice seems ambiguous , possibly contradictory, , want make sure i've understood properly.

previously accepted wisdom seemed nsmanagedobjectcontext accessed thread created it, , using serial queue synchronisation not sufficient; although serial queues perform 1 operation @ time, these operations can potentially scheduled on different threads, , moc doesn't that.

but now, programming guide, have:

you can use threads, serial operation queues, or dispatch queues concurrency. sake of conciseness, article uses “thread” throughout refer of these.

so far, (although conflation of threads , queues unhelpful). can safely use single context per (serial) queue, instead of 1 per operation/block, right? apple has visual depiction of in core data wwdc sessions.

but... create context queue? in nsmanagedobjectcontext documentation, apple state:

[a context] assumes default owner thread or queue allocated it—this determined thread calls init method. should not, therefore, initialize context on 1 thread pass different thread.

so have idea of nsmanagedobjectcontext needing know owner is. i'm assuming means first operation executed in queue should create moc , save reference remaining operations use.

is right? reason i'm hesitant nsmanagedobjectcontext article goes on say:

instead, should pass reference persistent store coordinator , have receiving thread/queue create new context derived that. if use nsoperation, must create context in main (for serial queue) or start (for concurrent queue).

apple seem conflating operations queues schedule execution. head in, , makes me wonder if want create new moc every operation after all. missing?

the nsmanagedobjectcontext , managed objects associated should pinned single actor (thread, serialized queue, nsoperationqueue max concurrency = 1).

this pattern called thread confinement or isolation. there isn't great phrase (thread || serialized queue || nsoperationqueue max concurrency = 1) documentation goes on "we'll use 'thread' remainder of core data doc when mean of 3 ways of getting serialized control flow"

if create moc on 1 thread, , use on another, have violated thread confinement exposing moc object reference 2 threads. simple. don't it. don't cross streams.

we call out nsoperation explicitly because unlike threads & gcd, has odd issue -init runs on thread creating nsoperation -main runs on thread running nsoperation. makes sense if squint @ right, not intuitive. if create moc in -[nsoperation init], nsoperation helpfully violate thread confinement before -main method runs , you're hosed.

we actively discourage / deprecated using mocs , threads in other ways. while theoretically possible bbum mentions, no 1 ever got right. tripped up, forgot necessary call -lock in 1 place, "init runs ?", or otherwise out-clevered themselves. autorelease pools , application event loop , undo manager , cocoa bindings , kvo there many ways 1 thread hold on reference moc after you've tried pass elsewhere. far more difficult advanced cocoa developers imagine until start debugging. that's not useful api.

the documentation changed clarify , emphasize thread confinement pattern sane way go. should consider trying fancy using -lock , -unlock on nsmanagedobjectcontext (a) impossible , (b) de facto deprecated. it's not literally deprecated because code works ever did. code using wrong.

some people created mocs on 1 thread, , passed them without calling -lock. never legal. thread created moc has been default owner of moc. became more frequent issue mocs created on main thread. main thread mocs interact application's main event loop undo, memory management, , other reasons. on 10.6 , ios 3, mocs take more aggressive advantage of being owned main thread.

although queues not bound specific threads, if create moc within context of queue right things happen. obligation follow public api.

if queue serialized, may share moc succeeding blocks run on queue.

so not expose nsmanagedobjectcontext* more 1 thread (actor, etc) under circumstance. there 1 ambiguity. may pass nsnotification* didsave notification thread's moc's -mergechangesfromcontextdidsavenotification: method.

  • ben

Comments

Popular posts from this blog

java - SNMP4J General Variable Binding Error -

windows - Python Service Installation - "Could not find PythonClass entry" -

Determine if a XmlNode is empty or null in C#? -