Skip to content

Instantly share code, notes, and snippets.

@sukima
Created October 3, 2009 07:39
Show Gist options
  • Save sukima/200469 to your computer and use it in GitHub Desktop.
Save sukima/200469 to your computer and use it in GitHub Desktop.
How to make a simple error reporter that is thread safe
/**
* What I'm attempting to do is to init an object. I want that object to
* default to a value if there was an error. In other words because the object
* is a model it should not attempt to send a message to the user as this is
* the responsability of the view (or controller to decide what to do). So it
* needs a mechinism to commiunicate an error to the caller without ever
* throwing an exception. I'm using the errorString and weather it is nil or
* not. However it is possible that more than one thread accesses errorString
* and there for causing false positives.
*
* After carefull self review it dawned on me that the init method was thread
* safe. Because errorString is encapsulated as an instance variable and it is
* readonly there is no way for another thread to mutate this. If it were not
* readonly or if there was a mechinism to reset it then were would be worried
* about threads.
*
* Case in point the saveToFile: selector does just that. It resets the
* errorString. Now any thread could attempt to save and mutate errorString.
*/
#import <Foundation/Foundation.h>
#import "SomeObject.h"
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
SomeObject *myNewObject = [[SomeObject alloc] initWithFile:@"test.plist"];
if (myNewObject.errorString != nil)
{
// Warn the user
}
// Continue on with default values.
// Not thread safe
if ( [myNewObject saveToFile:@"foo.plist"] )
{
// We're good to go
}
else
{
// There was an error
NSLog(@"Error Message: %@", myNewObject.errorString);
}
// Thread safe
NSString *errMsg = nil;
[myNewObject saveToFile:@"bar.plist" withErrorString:&errMsg];
if ( errMsg != nil )
{
// We're good to go
}
else
{
// There was an error
NSLog(@"Error Message: %@", errMsg);
}
[myNewObject release];
[pool release];
return 0;
}
#import <Foundation/Foundation.h>
@interface SomeObject : NSObject {
NSString *errorString;
NSArray *testArray;
}
@property (nonatomic, readonly) NSString *errorString;
@property (nonatomic, readonly) NSArray *testArray;
- (id)initWithFile:(NSString *)filename;
- (BOOL)saveToFile:(NSString *)filename;
- (void)saveTofile:(NSString *)filename withErrorString:(NSString **)errMsg;
@end
#import "SomeObject.h"
@implementation SomeObject
@synthesize errorString;
@synthesize testArray;
- (id)initWithFile:(NSString *)filename {
if (self = [super init])
{
// Do some file IO thing.
if ( YES ) // There was an error
{
errorString = @"There was an error.";
// Set testArray to an empty array. (Fresh start)
testArray = [[[NSArray alloc] init] retain];
}
else // All is good
{
// Set testArray to something usefull based on file IO.
}
}
return self;
}
- (BOOL)saveToFile:(NSString *)filename {
// Clear errorString
[errorString release];
errorString = nil;
// Attempt to save
if (YES) // Some thing went wrong
{
errorString = @"There was an error.";
return NO;
}
// everything worked
return YES;
}
- (void)saveTofile:(NSString *)filename withErrorString:(NSString **)errMsg {
// Attempt to save file
if (YES) // Something went wrong
{
*errMsg = @"There was an error";
}
else
{
*errMsg = nil;
}
}
- (void)dealloc {
[errorString release];
[super dealloc];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment