On Apr 1, 2014, at 12:16 AM, Trygve Inda wrote:

> I have an object with a dictionary property defined as:
> 
> @property (nonatomic, retain) NSMutableDictionary*  myDict;
> 
> This gets set when it is received via an AppleEvent from another
> application.
> 
> 
> 
> Multiple threads in the receiving app need to read (the threads never write,
> only read) from the Dictionary like:
> 
> [self setValueOne:[[myDict objectForKey:kValueOneKey] intValue]];
> [self setValueTwo:[[myDict objectForKey:kValueTwoKey] intValue]];
> 
> I need to be able to set a new myDict and not have it happen between the
> reading of different values from the dictionary by other threads.
> 
> Should this be done best with a @synchronize around a copy:
> 
> @synchronize(myDict)
> {
>    myCopy = [[NSDictionary alloc] initWithDictionary:myDict copyItems:YES];
> }
> 
> [self setValueOne:[[myCopy objectForKey:kValueOneKey] intValue]];
> [self setValueTwo:[[myCopy objectForKey:kValueTwoKey] intValue]];
> [myCopy release];
> 
> This would seem to ensure that valueOne and valueTwo were obtained from the
> same instance of a given dictionary and that the dictionary did not change
> in between the reading and setting of these two dictionary content objects.
> 
> I need to avoid valueOne and valueTwo coming from two different instances of
> myDict.

An @synchronized directive only at the read site accomplishes nothing.  The 
reads need to be synchronized with the setter, so the setter also has to use 
@synchronized _on the same object_.  It also doesn't make sense to synchronize 
on the myDict object.  That's what is in flux.  You should synchronize on 
"self", the object which owns and manages myDict.  I wouldn't bother making a 
copy within the @synchronized block.  I'd just read and retain both values you 
want.  Or read and convert to int, so they're no longer objects.  You could 
call the setters within the block if they are not long running and don't 
synchronize against other locks, but it's probably safest to call the setters 
outside of the block.

An alternative would be to use GCD to implement synchronization, especially 
since you can implement a read-write scheme.  Create a private concurrent 
queue.  Submit all operations on the myDict property to that queue.  For read 
operations, use dispatch_sync().  For write operations, use 
dispatch_barrier_async() (you can also use dispatch_barrier_sync(), but you 
often don't need to care when the write operation completes, so long as all 
subsequent read operations are guaranteed to see the result of the write).  
This way, readers can all run concurrently so long as there's no writing 
happening.  A write will not begin until all other operations (read or write) 
are done and will prevent any other operations from beginning until it 
completes.

Again, to make sure two values are read without the possibility of the 
dictionary being changed, do both reads within a single block submitted to the 
queue.

Regards,
Ken


_______________________________________________

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

Reply via email to