I wonder if I can perform similar check in my methods to handle case of nested calls inDatabase... methods. kDispatchQueueSpecificKey is private and _queue too in FMDatabaseQueue class, so I cannot use dispatch_get_specific method
FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
Related
Does locking in one function from a thread, blocks all other thread trying to acquire the lock in different functions.
We can use gcd for accessing the critical sections mentioned below, just wanted to know how #synchronized(self) works.
For ex.
Do multiple threads with ONLY writeString() calls gets blocked when the execution is in #synchronized(self){ } in writeString()?
OR
all the threads calling the functions of the same class with #synchronized(self){} (e.g.readDataFromFile()) gets blocked when execution is in #synchronized(self){ } in writeString() ?
-(void)writeString:(NSString*)string forObj:(id)obj
{
#synchronized(self)
{
[obj write:string];
}
}
-(void)readDataFromFile:(NSString*)file
{
#synchronized(self)
{
[self read];
}
}
#synchronized(A) can be thought of as a lock where A identifies the lock to use.
If you pass the same value for A into two calls to #synchronized(), then they'll use the same lock and be exclusive. If you pass two different values for two calls, then they will not be exclusive.
So for this one, we need to zoom out to a bit of a larger context.
In the case where you have two instances:
YourClass *a = [[YourClass alloc] init];
YourClass *b = [[YourClass alloc] init];
a will sync access to both methods for itself.
b will sync access to both methods for itself.
So for instance, concurrently from two different threads, a and b can both run -writeString:forObj: at the same time without blocking.
Now if you changed the implementation to use #synchronized(self.class) that entirely changes the game. Rather than syncing on the 'instance', you would be syncing on the 'class' as a whole, so every instance would have to sync access to the methods.
So for instance using the use #synchronized(self.class) implementation, concurrently from two different threads, if a and b both run -writeString:forObj: at the same time, that would then serialize those calls so only one runs while the other is blocked waiting for the sync to unlock.
I hope that clarifies the difference between locking on an instance of a class vs locking every instance for a given class.
Edit:
May also be worth noting, if you use #synchronized(self) in a 'class' method like the following:
// implementation of 'ExampleClass'
+(void)serializeWriting:(NSString*)string toObj:(id)obj {
#synchronized(self) {
[obj write:string];
}
}
That also changes the game, so anytime that method is called, its synced against the class itself, so something like [ExampleClass serializeWriting:#"some string" toObj:somethingElse] would only ever run the critical section [obj write:string] on a single thread no matter how many places/threads it was called from.
What are the implications of creating a singleton class with:
+ (id)sharedCoordinator {
static MyCoordinator *sharedCoordinator = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedCoordinator = [[self alloc] init];
});
}
or as an instance method in the Application Delegate with class method:
- (CoreDataHelper *)cdh {
if (!_coreDataHelper) {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
_coreDataHelper = [CoreDataHelper new];
});
[_coreDataHelper setupCoreData];
}
return _coreDataHelper;
}
I have seen them both used, and would like to learn how they affect performance, simple code, debugging, etc.
The main difference is that the second code snippet has an error: when cdh is accessed concurrently from multiple threads, there is a possibility of [_coreDataHelper setupCoreData] being called twice.
This would happen if multiple threads arrived at cdh at the time when _coreDataHelper is nil. Only one of these threads would proceed to make the [CoreDataHelper new] call, yet all threads would end up in the setupCoreData method.
The proper way of doing initialization is to place the setup call into the block, and make the call unconditional:
- (CoreDataHelper *)cdh {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
_coreDataHelper = [CoreDataHelper new];
[_coreDataHelper setupCoreData];
});
return _coreDataHelper;
}
Now the two snippets look almost identical. The only difference is that the first snippet uses a method-static variable to store the singleton, while the updated second snippet "piggybacks" on the instance of app delegate.
This does not create any performance differences worth discussing. The biggest difference is that the first snippet lets you access the singleton without creating an additional dependency on the app delegate, which is a good thing: this avoids "polluting" your app delegate with code that is not directly relevant to the application state.
The first allows the Singleton class to be re-used in other places.
The second makes the single instance private to the app delegate.
Generally the first option is better (IMHO.) It allows you to reuse the single instance in a structured way anywhere in your code.
The second option can provide a guarantee of being a single instance, privately accessible in one place. That is probably useful in some circumstances, but it isn't really a Singleton. You could make this a public property on the AppDelegate, but then why not use a Singleton class?
As for performance considerations, they should be negliable. The only one I can think of is the slight extra overhead in the runtime caused by having an extra class object in your code.
I have an objective-c class with some methods, which use a GCD queue to ensure that concurrent accesses to a resource take place serially (standard way to do this).
Some of these methods need to call other methods of the same class. So the locking mechanism needs to be re-entrant. Is there a standard way to do this?
At first, I had each of these methods use
dispatch_sync(my_queue, ^{
// Critical section
});
to synchronize accesses. As you know, when one of these methods calls another such method, a deadlock happens because the dispatch_sync call stops the current executing until that other block is executed, which can't be executed also, because execution on the queue is stopped. To solve this, I then used e.g. this method:
- (void) executeOnQueueSync:(dispatch_queue_t)queue : (void (^)(void))theBlock {
if (dispatch_get_current_queue() == queue) {
theBlock();
} else {
dispatch_sync(queue, theBlock);
}
}
And in each of my methods, I use
[self executeOnQueueSync:my_queue : ^{
// Critical section
}];
I do not like this solution, because for every block with a different return type, I need to write another method. Moreover, this problem looks very common to me and I think there should exist a nicer, standard solution for this.
First things first: dispatch_get_current_queue() is deprecated. The canonical approach would now be to use dispatch_queue_set_specific. One such example might look like:
typedef dispatch_queue_t dispatch_recursive_queue_t;
static const void * const RecursiveKey = (const void*)&RecursiveKey;
dispatch_recursive_queue_t dispatch_queue_create_recursive_serial(const char * name)
{
dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
dispatch_queue_set_specific(queue, RecursiveKey, (__bridge void *)(queue), NULL);
return queue;
}
void dispatch_sync_recursive(dispatch_recursive_queue_t queue, dispatch_block_t block)
{
if (dispatch_get_specific(RecursiveKey) == (__bridge void *)(queue))
block();
else
dispatch_sync(queue, block);
}
This pattern is quite usable, but it's arguably not bulletproof, because you could create nested recursive queues with dispatch_set_target_queue, and trying to enqueue work on the outer queue from inside the inner one would deadlock, even though you are already "inside the lock" (in derision quotes because it only looks like a lock, it's actually something different: a queue — hence the question, right?) for the outer one. (You could get around that by wrapping calls to dispatch_set_target_queue and maintaining your own out-of-band targeting graph, etc., but that's left as an exercise for the reader.)
You go on to say:
I do not like this solution, because for every block with a different
return types, I need to write another method.
The general idea of this "state-protecting serial queue" pattern is that you're protecting private state; why would you "bring your own queue" to this? If it's about multiple objects sharing the state protection, then give them an inherent way to find the queue (i.e., either push it in at init time, or put it somewhere that's mutually accessible to all interested parties). It's not clear how "bringing your own queue" would be useful here.
I have extended NSOperationQueue to allow adding NSBlockOperation with a specific NSString as identifier.
The identifier value is held in a NSMutableArray serving as a registry. This is how I implement the registry.
-(void)addOperation:(NSOperation *)operation withID:(NSString*)operationID
{
#synchronized(self.queueReference)
{
[self.queueReference addObject:operationID]; // <-- just a mutable array
}
[operation setCompletionBlock:^(){
#synchronized(self.queueReference) {
[self.queueReference removeObject:operationID];
}
}];
[self addOperation:operation];
}
Basically I am adding a completion block which is cleaning the registry when that particular operation has finished.
However, while this works, I am in need to add more granularity to the queue.
I only use the queue with block operation, and during the execution of the block I may send different NSNotification to the listener depending how the execution went.
What I was trying to achieve:
A caller try to add a particular NSBlockOperation with identifier to queue. If queue already has such identifier just don't add block, and the calling class set itself as listener.
What is missing ? Checking for the identifier is not enough, there may be case when the NSBlockOperation already dispatched the NSNotification but the completion block has not yet being called.
So the caller class ask the queue, which is saying the identifier exists in registry, and caller wrongly set itself for listening to a notification that will never arrive because it's already being sent.
The scenario would be instead: caller ask the queue, which is saying 'identifier is in registry' but NSNotification is sent. And the caller put NSBlockOperation to queue.
The check of registry is made by means of a simple method:
-(BOOL)hasOperationWithID:(NSString*)operationID
{
#synchronized(self.queueReference)
{
return [self.queueReference containsObject:operationID];
}
}
but at this point I have not much idea on how to extend such method. The code I am working on is kind of 'academic', it does not serve any particular purpose, it is just me trying to experiment. Therefore I have great flexibility within the code. But this is quite new subject to me, so please be as much specific as possible of any downside of suggested implementation.
It looks like your current system has three fundamental events:
Operation is added to the queue
Operation sends notification while executing
Operation completion block is called
Unless the queue itself explicitly listens for any NSNotifications that might be sent by the blocks, it has no way of knowing whether they have happened yet. But even if it does listen, the ordering in which observers of NSNotifications are called is non-deterministic. In other words, even if the queue listens for the notification and interlocks its callback with enqueue/dequeue operations, it could (and eventually would) still be too late for another client to start listening for that NSNotification, and you would falsely reject an operation.
Consider this alternative: Instead of using the completion block to manage the identifier list, use the notification itself -- have the queue handle sending the notifications. Put differently, let's get rid of the third event and have the notification sending do double duty for identifier list maintenance. The simplest way I came up with to do this looked like:
Header:
//
// SONotifyingOperationQueue.h
// NotifyingOpQueue
//
typedef void (^SOSendNotificationBlock)(NSDictionary* userInfo);
typedef void (^SONotifyingBlock)(SOSendNotificationBlock sendNotificationBlock);
#interface SONotifyingOperationQueue : NSOperationQueue
- (BOOL)addOperationForBlock:(SONotifyingBlock)block withNotificationName:(NSString*)notificationName;
#end
Implementation
//
// SONotifyingOperationQueue.m
// NotifyingOpQueue
//
#import "SONotifyingOperationQueue.h"
#implementation SONotifyingOperationQueue
{
NSMutableSet* _names;
}
- (BOOL)addOperationForBlock: (SONotifyingBlock)block withNotificationName: (NSString*)notificationName
{
notificationName = [[notificationName copy] autorelease];
BOOL shouldAdd = NO;
#synchronized(self)
{
_names = _names ? : [[NSMutableSet alloc] init];
if (![_names containsObject: notificationName])
{
[_names addObject: notificationName];
shouldAdd = YES;
}
}
if (shouldAdd)
{
NSBlockOperation* blockOp = [[[NSBlockOperation alloc] init] autorelease];
__block SONotifyingOperationQueue* blockSelf = self;
SOSendNotificationBlock notificationBlock = ^(NSDictionary* userInfo){
#synchronized(blockSelf)
{
[blockSelf->_names removeObject: notificationName];
// Sending the notification from inside the #synchronized makes it atomic
// with respect to enqueue operations, meaning there can never be a missed
// notification that could have been received.
[[NSNotificationCenter defaultCenter] postNotificationName: notificationName object: blockSelf userInfo: userInfo];
}
};
dispatch_block_t executionBlock = ^{
block(notificationBlock);
};
[blockOp addExecutionBlock: executionBlock];
[self addOperation: blockOp];
}
return shouldAdd;
}
- (void)dealloc
{
[_names release];
[super dealloc];
}
#end
This approach makes several changes to your original approach. First, the API here adds blocks and not NSOperations. You could do the same thing with an NSOperation subclass, but it would be more code, and wouldn't change the overall pattern. It also merges the notion of the identifier and the notification name. If an operation could send multiple, different NSNotifications, this won't work without modification, but again, the overall pattern would be the same. The important feature of this pattern is that your id/name check is now interlocked with the notification sending itself, providing a strong guarantee that if someone goes to add a new block/operation to the queue, and another operation with the same id/name hasn't fired its notification yet, the new operation won't be added, but if the notification has been fired, then it will be added, even if the preceding block hasn't yet completed.
If having the NSOperation object was somehow important here, you could also have the method here return the operation it creates for the supplied block.
HTH.
I detach a new NSThread withObject:self so that the thread can callback the main thread as a delegate. However, I also need the new thread to be able to read some values in the parent. With NSThread, I can only pass one object withObject, and I'm using that to pass self because of the delegate methods. Is there a way my new thread can read values from it's parent? Perhaps through the self object that is passed to it?
Here's where I launch the thread:
MulticastDaemon* multicastDaemon = [[MulticastDaemon alloc] init];
[NSThread detachNewThreadSelector:#selector(doWorkWithDelegate:)
toTarget:multicastDaemon
withObject:self];
I want to pass a multicast IP address and port number to the daemon, so he knows what to listen on, but I'm not sure how to get those values to multicastDaemon.
How can multicastDaemon access those values?
Yes, you can access the variables by making them properties and then doing something like this (you don't say what the class is that this call is made from, so I've called it MyClass):
#implementation MulticastDaemon
-(void) doWorkWithDelegate:(MyClass*) cls
{
cls.value1 = 12;
...
}
...
#end
EDIT: Corrected implementation.
You'd better use the subclass of NSOperation and then add it to the NSOperationQueue. You can add any additional parameters to that operation subclass.
There is also another advantage of NSOperation over NSThread. NSOperation and NSOperationQueue are build on top of the GCD and threading is far more optimal then NSThread.
But you can also simply add some properties to your MulticastDaemon.
You can change your MulticastDaemon's interface slightly so that you set the delegate before creating the new thread. Then you free up the withObject: slot to pass something else along. This avoids accessing variables across threads.
Either:
MulticastDaemon* multicastDaemon = [[MulticastDaemon alloc] initWithDelegate:self];
[NSThread detachNewThreadSelector:#selector(doWorkWithInformation:)
toTarget:multicastDaemon
withObject:operatingInfo];
Or
MulticastDaemon* multicastDaemon = [[MulticastDaemon alloc] init];
[multicastDaemon setDelegate:self];
Otherwise, you'll have to create a method that the daemon can call on its delegate that gathers and packages up the information to pass back. In that case, you'll probably have to start worrying about thread safety.