Using willChangeValueForKey/didChangeValueForKey with OSSpinLockLock - objective-c

I want to issue a notification when all 4 different threads have finished their work. I'm keeping count of the total threads and have a listener that does some work when the threads have finished.
Is the following a safe way to do this?
// ivars:
NSMutableArray *list;
OSSpinLock lock;
#define MAX_ALLOWED 4
- (void)someThreadedWork
{
// Iterate thru 4 different items using gcd and update
for (int x = 0; x < MAX_ALLOWED; ++x)
{
dispatch_async(some_queue, ^{
// Do some work.. once done,
[self updateCount:ix];
});
}
}
- (void)updateCount:(NSInteger)newCount
OSSpinLockLock(&lock);
{
[list addObject:[NSNumber numberWithInt:newCount]];
if ([list count] == MAX_ALLOWED)
{
_allValuesUpdatedAt = [NSDate date];
}
}
OSSpinLockUnlock(&lock);
}
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object
change:(NSDictionary*)change context:(void*)context
{
// When I get the 'allItemsUpdatedAt' event, I will perform some other work
}
- (id)init {
if (self = [super init])
{
// there is a corresponding removeObserver in the dealloc
list = [[NSMutableArray alloc] init];
[anInstance addObserver:self
forKeyPath:#"allItemsUpdatedAt"
options:NSKeyValueObservingOptionNew
context:NULL];
}
return self;
}

HachiEthan's comment about dispatch_async is exactly correct. If you use dispatch_group_async instead, then you don't need any locking at all, nor do you have to keep track of the threads that are currently working. It'll do all of this for you.
See "Waiting on Groups of Queued Tasks" in the Concurrency Programming Guide for a faster, simpler, more robust, and less energy intensive approach to this problem. See also "Migrating Away from Threads" in the same document to learn how to convert thread-based systems to queue-based systems.

Heres a few things:
Red Flag: You change the value of _allValuesUpdatedAt inside the lock, but are potentially "reading" its value elsewhere... (e.g. whomever is observing the property allValuesUpdatedAt) so unless your allValuesUpdatedAt property is also protected by that same &lock instance, you've got a problem there. (Edit: also, your above code is not retaining the NSDate, so it will be autoreleased on you at some point.)
If you use dispatch_async and pass it a serial queue then you don't need that spin-lock for updating the values in your list, provided that the updateCount: method is only accessed by code running from that serial queue. (Note: You'd still need to protect access to allValuesUpdatedAt)
If updateCount: does need to be accessed from other code, say, the main thread, then yes you will need some sort of lock there, like you have.
EDIT: keeping most of what you have, but addressing the red-flag
//header:
#property (atomic, retain) NSDate *allValuesUpdatedAt;
//impl:
- (void)updateCount:(NSInteger)newCount
OSSpinLockLock(&lock);
{
[list addObject:[NSNumber numberWithInt:newCount]];
if ([list count] == MAX_ALLOWED)
{
//use atomic property for read/write thread-safety:
self.allValuesUpdatedAt = [NSDate date];
}
}
OSSpinLockUnlock(&lock);
}

Related

ReactiveCocoa MVVM with UITableView

I'm using ReactiveCocoa and am trying to apply MVVM. I have a fairly typical UITableView scenario with a refresh control for reloading data.
I've omitted the the UITableDataSource/Delegate methods as these are straight forward. The code below illustrates how I've designed the ViewModel and the ViewController to fit together.
ViewModel.h
#property (strong, nonatomic, readonly) RACCommand *getItemsCommand;
#property (strong, nonatomic, readonly) NSArray *items;
ViewModel.m
- (instancetype)init {
self = [super init];
if (!self) return nil;
#weakify(self);
self.getItemsCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return [[ItemsDataSource getItems]
doNext:^(NSArray *items) {
#strongify(self);
// I actually do a little extra work here such as sorting
// the items appropriately for the view.
self.items = items;
}];
}];
return self;
}
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView addSubview:self.refreshControl];
RACSignal *refreshSignals = [RACSignal merge:#[
[self.refreshControl rac_signalForControlEvents:UIControlEventValueChanged],
[RACSignal return:nil]
]];
[refreshSignals
subscribeNext:^(id x) {
[self.viewModel.getItemsCommand execute:nil];
}];
[RACObserve(self.viewModel, items)
subscribeNext:^(NSArray *items) {
[self.tableView reloadData];
} completed:^{
[self.refreshControl endRefreshing];
}];
}
Questions/Problems
The completed block where I call endRefreshing never gets executed and for the life of me I can't figure out why.
Would it be better to use a public method - (RACSignal *)getItems instead of the getItems RACCommand?
Is my usage of doNext: in the ViewModel correct in order to apply side effects (i.e. the sorting of the items array) without causing an additional subscription?
I suggest making getItemsCommand use -map: to sort and process the items array. Leave any other side effect work to be done in a separate -doNext:. Once you have your command following this pattern (which is more compositional in RAC), then you can use the RAC() macro to assign the command's finished product, the sorted array, to the items property.
RAC(self, items) = [self.getItemsCommand.executionSignals concat];
RAC has a built-in command support for UIRefreshControl that will start/stop the refresh control along with the start/stop of the command. You should find that you can reduce your UIRefreshControl code to:
self.refreshControl.rac_command = self.getItemsCommand;
For table reloading, you can do:
[RACObserve(self, items) subscribeNext:^(id _) {
#strongify(self);
[self.tableView reloadData];
}];
Hope that helps.
1) Well, let's look at the signal:
RACObserve(self.viewModel, items)
When will that complete? Only when self.viewModel or self is deallocated, just like any other RACObserve. As long as those objects are around, it'll keep on nexting any time you set self.items.
It appears that you want it to endRefreshing once the getItemsCommand finishes executing, and you have this sort of implicit expectation that, since you know that command sets self.viewModel.items, that completion will somehow propagate -- but this isn't the case. To see when the command completes, you have to subscribe to the command's returned signal.
2) The advantage of RACCommand is the auto enabling/disabling behavior, which you aren't really taking advantage of here. The more canonical thing to do would be self.refreshControl.rac_command = self.viewModel.getItemsCommand;. That'll handle the endRefreshing stuff for you, saving you the headache from part 1.
3) ...sort of. The do* family of methods injects side effects for every subscription to the signal. So if you subscribe to a signal twice, and it sends a next, any doNext block it has will be invoked twice. An explicit subscription is more clear, since you want to execute this exactly once per next, regardless of how many times it's subscribed to.
#weakify(self);
self.getItemsCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
RACSignal *itemsSignal = [ItemsDataSource getItems];
[itemsSignal subscribeNext:^(NSArray *items) {
#strongify(self);
// Do stuff...
self.items = items;
}];
return itemsSignal;
}];

Self destructing singleton design pattern iOS

I recently came across an issue in which I only wanted one instance of a particular object to exist, and exist for only the brief period of time it needed to perform a specific operation. Its operation was asynchronous so ARC would dealloc it at the end of the run loop if I didn't hold a reference to it. If I did hang onto it I would need delegate callbacks or notifications to know when it was done to release it.
The object needed to download several images and other data and cache it to disk. I didn't want it to waste memory when it wasn't caching items since the cache limit was around 24 hours. I also didn't need feedback of any kind from it; I wanted it to perform it's task and be done with itself.
I came up with a design pattern I liked quite nicely. I've used it in a few other projects since then, and was curios if it was a well known and analyzed pattern that I'm just not aware of (self-destructing singleton???). I'd like to know so I can be made aware of any potential pitfalls I'm not currently seeing.
I'm also very interested to hear any input you guys might have about why this is a bad design.
The Design Goes Like This (this is ARC, but non-arc can work too if you release the singleton through a class method):
A global static object (not really a singleton because it doesn't live the entire time)
static MySelfDestructingClass* singleton;
A single public class method
+ (void)downloadAndCacheDataIfNeeded
{
//Force synchronized access
#synchronized(singleton){
//We are already doing something, return
if(singleton){
return;
}
NSDate* lastCacheDate = [[NSUserDefaults standardDefaults] objectForKey:kKeyForLastUpdate];
if([[NSDate date] timeIntervalSinceDate:lastCacheDate] > kCacheLimit){
//Our cache is out of date, we need to update
singleton = [[self alloc] init];
[singleton downloadAndCache];
}
}
}
Now our instance methods, we need our object alive so the request can come back:
- (void)downloadAndCache
{
//This would probably be a delegate, but for simplicity of this example it's a notification
[[NSNotificationCenter defaultCenter] addObserver:self forNotificationWithName:NotificationSomeRequestDidSucceed selector:#selector(someCustomRequestDidSucceed:withData:) object:nil];
[SomeCustomRequest makeRequestWithURL:#"http://www.someURL.com"];
}
- (void)someCustomRequestDidSucceed:(SomeCustomRequest *)request withData:(NSDictionary *)dictionary
{
//Do whatever we need to in order to save our data, or fire off image download requests etc...
....
//Set our lastUpdated time in NSUserDefaults
[[NSUserDefaults standardDefaults] setObject:[NSDate date] forKey:kKeyForLastUpdate];
//Remove our observer
[NSNotificationCenter defaultCenter] removeObserver:self name:NotificationSomeRequestDidSucceed object:nil];
//Release ourselves (ok not really, but tell arc we can be released)
singleton = nil;
}
This way all I have to do anywhere else in the application is:
[MySelfDestructingClass downloadAndCacheDataIfNeeded];
Now this object will download things if it needs to and release itself when it's done, or not create itself at all. It also won't go and start downloading the data twice.
I'm aware this design has limitations with extendibility and functionality, but for an instance like this, and the other ones I've used it for, I've found it quite useful.
This pretty common using blocks. Consider something similar (though I would probably handle multiple invocations differently...)
void ExecuteWithMySingleSelfDestructingObject(void(^block)(MySelfDestructingClass *object)) {
static MySelfDestructingClass* singleton;
#synchronized(singleton) {
if (singleton) {
// To get past the synchronization primitive, this must be a recursive call.
}
// Whatever other conditions you want to have (like your date check)
singleton = [[MySelfDestructingClass] alloc] init];
#try { block(singleton); }
#finally { singleton = nil; }
}
}
Note double exception handling (try/finally plus what #synchronized does - may want to change that...
Then do whatever you want with the block...
ExecuteWithMySingleSelfDestructingObject(^(MySelfDestructingClass *object){
// Do whatever I want with the singleton instance that has
// been given to me as <object>
});
Of course, it could be a class method...
+ (void)performBlock:(void(^)(MySelfDestructingClass *object))block {
static MySelfDestructingClass* singleton;
#synchronized(singleton) {
if (singleton) {
// To get past the synchronization primitive, this must be a recursive call.
}
// Whatever other conditions you want to have (like your date check)
singleton = [[self] alloc] init];
#try { block(singleton); }
#finally { singleton = nil; }
}
}
[MySelfDestructingClass performBlock:^(MySelfDestructingClass *object){
// Do whatever I want with the singleton instance that has
// been given to me as <object>
}];
I hope that makes sense (I typed it free-hand, so syntax may vary, but you should get the idea).

Objective-c Async memory management

I've had a look around but have been unable to find a definitive answer to this question.
If I have a class that performs an async operation, when and how do I release it?
-(void)main
{
AsyncObject *async = [[AsyncObject alloc] initWithDelegate:self];
[async goDoSomething];
}
-(void)didSomething:(Result*)result
{
}
When do I release *async?
You could keep a private property to save the value, or, if you have control over the AsyncObject, pass the instance in the didSomething: selector.
I think the first option is better since you know the object will be retained until you get your delegate call.
Option 1:
ClassName.m
#interface ClassName ()
#property (nonatomic, retain) AsyncObject* async;
#end
#interface
//...
-(void)main
{
async = [[AsyncObject alloc] initWithDelegate:self];
[async goDoSomething];
}
-(void)didSomething:(Result*)result
{
[async release];
async = nil;
}
Option 2:
-(void)aysncObject:(AsyncObject*)async didSomething:(Result*)result {
[async release];
}
If your object runs its asynchronous task on a background thread, or is the target of a timer, or uses GCD and is referenced within the scope of the dispatched block (the ^ {} kerjigger) then it will be retained for you for the lifetime of that background operation.
So the normal use case would be:
AsyncObject *async = [[AsyncObject alloc] initWithDelegate:self];
[async goDoSomething];
[async release];
Now, it's possible to work in the background with an object that is not retained (e.g. by using a __block-scoped reference to the object with GCD, or by detaching your worker thread with pthreads instead of NSThread/NSOperation) but there are no typical use cases I can think of offhand where that would happen. In such a case, you should ensure that -goDoSomething internally retains and releases self for the duration of the operation.
(If somebody can think of a case where the object is not retained for you, please post in the comments and I'll update my answer.)
Thanks for the help guys, I did a bit of experimenting with NSURLConnection to see how it handled it (As you autorelease that and it will continue on with it's async operations).
Turns out at the beginning of every async step it internally bumps its retain count and at the end of every async step it internally releases itself.
This means that it can be sent autorelease/release and it won't actually be release until it has completed it's current operation.
// MAIN.M
-(void)main
{
AsyncObject *async = [[[AsyncObject alloc] initWithDelegate:self] autorelease];
[async goDoSomething];
}
-(void)didSomething:(Result*)result
{
}
// ASYNCOBJECT.M
-(void) goDoSomething
{
[self retain];
}
-(void) finishedDoingSomething
{
[delegate didSomething:result];
[self release]
}

When is an autoreleased object actually released?

I am new in objective-c and I am trying to understand memory management to get it right.
After reading the excellent
Memory Management Programming Guide for Cocoa by apple my only concern is when
actually an autoreleased object is released in an iphone/ipod application. My understanding is at the end of a run loop. But what defines a run loop in the application?
So I was wondering whether the following piece of code is right. Assume an object
#implementation Test
- (NSString *) functionA {
NSString *stringA;
stringA = [[[NSString alloc] initWithString:#"Hello"] autorelease]
return stringA;
}
- (NSString *) functionB {
NSString *stringB;
stringB = [self functionA];
return stringB;
}
- (NSString *) functionC {
NSString *stringC;
stringC = [self functionB];
return stringC;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString* p = [self functionC];
NSLog(#"string is %#",p);
}
#end
Is this code valid?
From the apple text I understand that the NSString returned from functionA is valid in the scope of functionB. I am not sure whether it is valid in functionC and in viewDidLoad.
Thanks!
Yes, your functions are valid, and return objects using correct Cocoa conventions for retain/release/autorelease/copy.
To answer your question about what the runloop is, in your application's main() function, it invokes UIApplicationMain(). You can imagine UIApplicationMain looks something like this:
void int UIApplicationMain (int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName) {
UIApplication *app = /* create app using principalClassName */;
[app setDelegate:/* create delegate using delegateClassName */];
while (![app shouldTerminate]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
event = [app getNextEvent];
[app dispatchEvent:event];
[pool drain];
}
}
That while loops is similar to what the UIKit is actually doing, and each trip through that while loop is like a trip through the runloop, where the function getNextEvent blocks waiting for some event to happen. All of your methods are typically called from within something like dispatchEvent:. You might try setting a break point in one of your methods, like an IBAction, and looking in the debugger call stack way up at the top to see the names of the UIKit methods that handle the events and runloop. Since each of your methods are called from within that while loop, each time you call autorelease on an object, that object is added to that outter pool in the run loop. When the current event is finished being dispatched, the pool is drained, and those objects are finally sent release messages.
One last note. There can be more than one autorelease pool, that aren't always at the end of the event loop. Sometimes you might allocate tens of thousands of objects in one trip thorough the event loop. When that happens, you might setup additional inner auto release pools in your own methods to keep the number of autoreleased objects in autorelease pools down. Auto release pools can stack.
There's nothing wrong with that code. It will compile and run as you expect.
The NSString object returned from functionA is still valid upon return since it's being passed down the stack to the next guy (functionB) who is now keeping track of it.

How does #synchronized lock/unlock in Objective-C?

Does #synchronized not use "lock" and "unlock" to achieve mutual exclusion? How does it do lock/unlock then?
The output of the following program is only "Hello World".
#interface MyLock: NSLock<NSLocking>
#end
#implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(#"before lock");
[super lock];
NSLog(#"after lock");
}
- (void)unlock {
NSLog(#"before unlock");
[super unlock];
NSLog(#"after unlock");
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
#synchronized(lock) {
NSLog(#"Hello World");
}
[pool drain];
}
The Objective-C language level synchronization uses the mutex, just like NSLock does. Semantically there are some small technical differences, but it is basically correct to think of them as two separate interfaces implemented on top of a common (more primitive) entity.
In particular with a NSLock you have an explicit lock whereas with #synchronized you have an implicit lock associated with the object you are using to synchronize. The benefit of the language level locking is the compiler understands it so it can deal with scoping issues, but mechanically they behave basically the same.
You can think of #synchronized as a compiler rewrite:
- (NSString *)myString {
#synchronized(self) {
return [[myString retain] autorelease];
}
}
is transformed into:
- (NSString *)myString {
NSString *retval = nil;
pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
pthread_mutex_lock(self_mutex);
retval = [[myString retain] autorelease];
pthread_mutex_unlock(self_mutex);
return retval;
}
That is not exactly correct because the actual transform is more complex and uses recursive locks, but it should get the point across.
In Objective-C, a #synchronized block handles locking and unlocking (as well as possible exceptions) automatically for you. The runtime dynamically essentially generates an NSRecursiveLock that is associated with the object you're synchronizing on. This Apple documentation explains it in more detail. This is why you're not seeing the log messages from your NSLock subclass — the object you synchronize on can be anything, not just an NSLock.
Basically, #synchronized (...) is a convenience construct that streamlines your code. Like most simplifying abstractions, it has associated overhead (think of it as a hidden cost), and it's good to be aware of that, but raw performance is probably not the supreme goal when using such constructs anyway.
Actually
{
#synchronized(self) {
return [[myString retain] autorelease];
}
}
transforms directly into:
// needs #import <objc/objc-sync.h>
{
objc_sync_enter(self)
id retVal = [[myString retain] autorelease];
objc_sync_exit(self);
return retVal;
}
This API available since iOS 2.0 and imported using...
#import <objc/objc-sync.h>
Apple's implementation of #synchronized is open source and it can be found here. Mike ash wrote two really interesting post about this subject:
Locks, Thread Safety, and Swift
Let's Build #synchronized
In a nutshell it has a table that maps object pointers (using their memory addresses as keys) to pthread_mutex_t locks, which are locked and unlocked as needed.
It just associates a semaphore with every object, and uses that.