- (NSHashTable *)pollers
{
if (!_pollers) {
dispatch_sync(self.serialQueue, ^{
_pollers = [NSHashTable weakObjectsHashTable];
});
}
return _pollers;
}
pollers is a nonatomic property on a singleton. There are some other methods in the singleton where objects are added to pollers, and I'm using #synchronized for their addition ([self.pollers addObject:____]).
Anyway... I have a question about the code above. If 2 threads simultaneously call this function, they could both get past the if (!_pollers) code, and then both will dispatch the _pollers = [NSHashTable weakObjectsHashTable]; code synchronously on our custom serialQueue. So we'll actually run the code twice.
Is there a better way to do this?
You only need a single dispatch_once function for this
Your serial queue is now redundant, as dispatch_once will ensure that the block is only called once (even if invoked at the same time from multiple threads), contrary to what pds says.
The documentation clearly states that:
If [dispatch_once is] called simultaneously from multiple threads, this function waits synchronously until the block has completed.
Your if statement is also redundant, as pointed out by Josh.
Therefore you just want:
- (NSHashTable *)pollers
{
static dispatch_once_t t;
dispatch_once(&t, ^{
_pollers = [NSHashTable weakObjectsHashTable];
});
return _pollers;
}
It's also worth noting that you'll need a thread safe implementation of your singleton's sharedInstance in order for this to be bulletproof. You can do this in much the same way with a dispatch_once. For example:
static singleton* sharedInstance;
+(instancetype) sharedInstance {
static dispatch_once_t t;
dispatch_once(&t, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Use dispatch_once like this
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dispatch_sync(self.serialQueue, ^{
_pollers = [NSHashTable weakObjectsHashTable];
});
});
return pollers;
Related
without ARC, does dispatch_block_cancel release the dispatch block or it need be manually released?
dispatch_block_t work = dispatch_block_create(0, ^{
//...
});
dispatch_block_cancel(work); // Is work released here?
Block_release(work); // Or it need to be released?
Assuming dispatch_block_cancel releases the block, what would be the difference between those two cases?
// Case 1
dispatch_block_t work = dispatch_block_create(0, ^{
//...
});
dispatch_block_cancel(work);
// Case 2
dispatch_block_t work = dispatch_block_create(0, ^{
//...
});
Block_release(work);
Cancelation has no impact on memory management. You called dispatch_block_create, which includes the word "create." That means you are responsible for releasing the memory. Nothing will do it for you.
I've been reading around and its hard to get a clear feel if I have written a thread safe implementation here.
My getter looks like
+ (MySingleton *)getSingleton
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[MySingleton alloc] init];
});
return singleton;
}
And my setter is:
+ (void)updateSingleton:(MySingleton *)newSingleton
{
#syncronized(self) {
singleton = newSingleton;
}
}
No, that isn't thread safe. Your exclusion mechanism between your two modification methods are not the same. dispatch_once has nothing to do with #synchronized in any way.
Beyond that a singleton must never be replaced by definition. A singleton can come into existence at any time and, once it does, it never, ever, goes away.
Also, getSingleton should be sharedInstance or some similar objective-c standard moniker. Methods should never be prepended with get unless they are returning stuff by reference.
What is the difference between dispatch_once and using runtime conditional check for the property that requires only once initialization
Method 1: runtime checking
- (MyProp *)myProp{
if (!_myProp){
_myProp = [[MyProp alloc] init];
}
return _myProp;
}
Method 2: use dispatch_once
- (MyProp *)myProp{
dispatch_once_t once;
dispatch_once(&once, ^{
_myProp = [[MyProp alloc] init];
}
return _myProp;
}
I guess that method 2 is somehow faster but not really sure.
Could anyone give me any deal?
Thanks
dispatch_once is thread safe. So if two threads call myProp for the first time simultaneously, dispatch_once ensures only one initializes the variable. Method 1 may initialize the variable twice, and could even corrupt memory such that the reference is invalid. Once the property has been initialized, these behave identically.
Method 2 is actually slightly slower than Method 1, particularly during the first initialization. But in the usual case (reading after initialization), it is extremely close (possibly identical) in performance. If you want a much more in-depth exploration of how it works and why, see Mike Ash's Secrets of dispatch_once.
Note that your Method 2 code is incorrect. You've made once an automatic local variable. It needs to be static or dispatch_once can't do its job. What you meant was:
- (MyProp *)myProp{
static dispatch_once_t once; // <--- this "static" is critical
dispatch_once(&once, ^{
_myProp = [[MyProp alloc] init];
}
return _myProp;
}
I'm reading through a book trying to brush the dust off of Objective-C, and I ran into this question while reading how to implement a singleton. This is the implementation as they have it in the book:
+ (ClassName *)sharedClass {
static ClassName *sharedClass = nil;
if (!sharedClass) {
sharedClass = [[super allocWithZone:nil] init];
return shared store
}
My question is, why would they set it to nil each time the method is ran, then check if it's nil, which it now obviously is, and create a new instance? That sounds like it defeats the whole purpose of a singleton, to only have one instance of a class. I've noticed a ton of questions related to singleton implementation, but none specific to this aspect of it. Believe me, I combed through before posting.
The static variable is set to nil only for the first time. Once the sharedClass instance is instantiated, you will alway have the same instance whenever you invoke [ClassName sharedClass].
You should use thread-safe pattern to use singleton pattern.
+ (instancetype)shared {
static id shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return sharedInstance;
}
This will prevent possible crashes.
I'm trying to create a NSOperationQueue and add a NSOperation to it. Later I wan't to check if the queue is running and maybe abort it. All of that is supposed to be called from within different functions. What's the best approach to do this? I would be glad for a code example. Thanks!
I would create an operation queue that's managed by a singleton.
First, create your singleton class. It will provide access to the NSOperationQueue. Let's call the singleton MyGlobalQueueManager.
It will have an ivar called myGlobalQueue:
#property (nonatomic) NSOperationQueue* myGlobalQueue;
In the .m file of MyGlobalQueueManager, create a fairly standard init method that will set up the operation queue:
- (id)init
{
self = [super init];
if (self)
{
myGlobalOperationQueue = [[NSOperationQueue alloc] init];
}
return self;
}
Now, the method that provides itself as a singleton. Again, this is pretty standard stuff:
+ (MyGlobalQueueManager *)sharedInstance
{
static MyGlobalQueueManager *sharedInstance = nil;
static dispatch_once_t isDispatched;
dispatch_once(&isDispatched, ^
{
sharedInstance = [[MyGlobalQueueManager alloc] init];
});
return sharedInstance;
}
Let's access that queue from wherever you want to use it:
MyGlobalQueueManager* myGlobalQueueManager = [MyGlobalQueueManager sharedInstance];
NSOperationQueue *myGlobalQueue = myGlobalQueueManager.myGlobalOperationQueue;
You can then add operations to that queue as you fancy.
How to know if anythings queued?
NSUInteger count = [myGlobalQueue operationCount];
How to abort? Cancel everything as follows:
[myGlobalQueue cancelAllOperations];
Cancelling of course depends on the operations. If you're writing custom NSOperation classes, you'll need to handle that yourself.
I find NSOperation and NSOperationQueue to be fairly easy to use and quite straightforward.
A great document to read for all this is the Concurrency Programming Guide. Specifically, have a look at Operation Queues
An easier way to do it is to make a "globally visible" function. AKA, declare it in a public header:
extern NSOperationQueue * SharedQueue();
and define it within your compilation "unit" - but outside any #implementation.
NSOperationQueue *SharedOperationQueue()
{
static NSOperationQueue * _SharedQueue = nil;
return _SharedQueue ?: ^{ _SharedQueue = NSOperationQueue.new;
_SharedQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
return _SharedQueue;
}();
}
As a little bonus.. #define it with an "alias".. and you can REALLy abuse it!
#define MY_SOQ SharedOperationQueue()
[MY_SOQ addOperationWithBlock:^{ /* GO CRAZY */ }];