From 76c7aff835f97b92026002a4bf0c3d564443392d Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Fri, 4 Nov 2011 15:16:50 +0800 Subject: [PATCH 1/9] Initial stash --- .gitignore | 85 +++++++ IRRecurrenceMachine.xcodeproj/project.pbxproj | 228 ++++++++++++++++++ .../IRRecurrenceMachine-Prefix.pch | 7 + IRRecurrenceMachine/IRRecurrenceMachine.h | 83 +++++++ IRRecurrenceMachine/IRRecurrenceMachine.m | 174 +++++++++++++ 5 files changed, 577 insertions(+) create mode 100644 .gitignore create mode 100644 IRRecurrenceMachine.xcodeproj/project.pbxproj create mode 100644 IRRecurrenceMachine/IRRecurrenceMachine-Prefix.pch create mode 100644 IRRecurrenceMachine/IRRecurrenceMachine.h create mode 100644 IRRecurrenceMachine/IRRecurrenceMachine.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8800512 --- /dev/null +++ b/.gitignore @@ -0,0 +1,85 @@ +# Finder + +.DS_Store + + + + + +# Sparkle + +dsa_priv.pem + + + + + +# Xcode Config + +*.mode1 +*.mode1v3 +*.mode2v3 +*.perspective +*.perspectivev3 +*.pbxuser +*.xcworkspace +*.xcuserdatad + + + + + +# Generated files + +VersionX-revision.h + + + + + +# Builds + +build/ +Build/ +*.[oa] + + + + + +# Other SCMs + +.hg +.svn +CVS + + + + + +# Backups + +*~.nib +*.swp +*~ +*(Autosaved).rtfd/ + +Backup[ ]of[ ]*.pages/ +Backup[ ]of[ ]*.key/ +Backup[ ]of[ ]*.numbers/ + + + + + +# Time Machine + +*.timemachine.supported + +.sass-cache/* +*/.sass-cache/* + +package/* +script/testflightCredentials + + diff --git a/IRRecurrenceMachine.xcodeproj/project.pbxproj b/IRRecurrenceMachine.xcodeproj/project.pbxproj new file mode 100644 index 0000000..99c9c3a --- /dev/null +++ b/IRRecurrenceMachine.xcodeproj/project.pbxproj @@ -0,0 +1,228 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + FF22282D1463C77300541E31 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF22282C1463C77300541E31 /* Foundation.framework */; }; + FF2228331463C77300541E31 /* IRRecurrenceMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2228321463C77300541E31 /* IRRecurrenceMachine.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + FF2228291463C77300541E31 /* libIRRecurrenceMachine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIRRecurrenceMachine.a; sourceTree = BUILT_PRODUCTS_DIR; }; + FF22282C1463C77300541E31 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + FF2228301463C77300541E31 /* IRRecurrenceMachine-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IRRecurrenceMachine-Prefix.pch"; sourceTree = ""; }; + FF2228311463C77300541E31 /* IRRecurrenceMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IRRecurrenceMachine.h; sourceTree = ""; }; + FF2228321463C77300541E31 /* IRRecurrenceMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IRRecurrenceMachine.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FF2228261463C77300541E31 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FF22282D1463C77300541E31 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FF22281E1463C77300541E31 = { + isa = PBXGroup; + children = ( + FF22282E1463C77300541E31 /* IRRecurrenceMachine */, + FF22282B1463C77300541E31 /* Frameworks */, + FF22282A1463C77300541E31 /* Products */, + ); + sourceTree = ""; + }; + FF22282A1463C77300541E31 /* Products */ = { + isa = PBXGroup; + children = ( + FF2228291463C77300541E31 /* libIRRecurrenceMachine.a */, + ); + name = Products; + sourceTree = ""; + }; + FF22282B1463C77300541E31 /* Frameworks */ = { + isa = PBXGroup; + children = ( + FF22282C1463C77300541E31 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + FF22282E1463C77300541E31 /* IRRecurrenceMachine */ = { + isa = PBXGroup; + children = ( + FF2228311463C77300541E31 /* IRRecurrenceMachine.h */, + FF2228321463C77300541E31 /* IRRecurrenceMachine.m */, + FF22282F1463C77300541E31 /* Supporting Files */, + ); + path = IRRecurrenceMachine; + sourceTree = ""; + }; + FF22282F1463C77300541E31 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + FF2228301463C77300541E31 /* IRRecurrenceMachine-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + FF2228271463C77300541E31 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + FF2228281463C77300541E31 /* IRRecurrenceMachine */ = { + isa = PBXNativeTarget; + buildConfigurationList = FF2228361463C77300541E31 /* Build configuration list for PBXNativeTarget "IRRecurrenceMachine" */; + buildPhases = ( + FF2228251463C77300541E31 /* Sources */, + FF2228261463C77300541E31 /* Frameworks */, + FF2228271463C77300541E31 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = IRRecurrenceMachine; + productName = IRRecurrenceMachine; + productReference = FF2228291463C77300541E31 /* libIRRecurrenceMachine.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FF2228201463C77300541E31 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = FF2228231463C77300541E31 /* Build configuration list for PBXProject "IRRecurrenceMachine" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FF22281E1463C77300541E31; + productRefGroup = FF22282A1463C77300541E31 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FF2228281463C77300541E31 /* IRRecurrenceMachine */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + FF2228251463C77300541E31 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FF2228331463C77300541E31 /* IRRecurrenceMachine.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + FF2228341463C77300541E31 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + SDKROOT = iphoneos; + }; + name = Debug; + }; + FF2228351463C77300541E31 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FF2228371463C77300541E31 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/IRRecurrenceMachine.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "IRRecurrenceMachine/IRRecurrenceMachine-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + FF2228381463C77300541E31 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/IRRecurrenceMachine.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "IRRecurrenceMachine/IRRecurrenceMachine-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FF2228231463C77300541E31 /* Build configuration list for PBXProject "IRRecurrenceMachine" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FF2228341463C77300541E31 /* Debug */, + FF2228351463C77300541E31 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FF2228361463C77300541E31 /* Build configuration list for PBXNativeTarget "IRRecurrenceMachine" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FF2228371463C77300541E31 /* Debug */, + FF2228381463C77300541E31 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = FF2228201463C77300541E31 /* Project object */; +} diff --git a/IRRecurrenceMachine/IRRecurrenceMachine-Prefix.pch b/IRRecurrenceMachine/IRRecurrenceMachine-Prefix.pch new file mode 100644 index 0000000..8871354 --- /dev/null +++ b/IRRecurrenceMachine/IRRecurrenceMachine-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'IRRecurrenceMachine' target in the 'IRRecurrenceMachine' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.h b/IRRecurrenceMachine/IRRecurrenceMachine.h new file mode 100644 index 0000000..44d2d4f --- /dev/null +++ b/IRRecurrenceMachine/IRRecurrenceMachine.h @@ -0,0 +1,83 @@ +// +// IRRecurrenceMachine.h +// IRRecurrenceMachine +// +// Created by Evadne Wu on 11/4/11. +// Copyright (c) 2011 __MyCompanyName__. All rights reserved. +// + +#import + +@interface IRRecurrenceMachine : NSObject + +- (id) initWithQueue:(NSOperationQueue *)aQueue; +@property (nonatomic, readonly, retain) NSOperationQueue *queue; + +// Designated initializer. If a queue is not provided, or if the method was invoked +// implicitly, the recurrence machine will create a queue on its own. + +// It is generally recommended to let the recurrence machine use its own queue. +// Although the machine is conscious not to interfere with the queue, exotic queues +// with unknown or unexpected attributes might be troublesome. + + +@property (nonatomic, readwrite, assign) NSTimeInterval recurrenceInterval; + +// The default interval is 30 seconds. Changing the interval invalidates the timer. + + +- (void) addRecurringOperation:(NSOperation *)anOperation; +@property (nonatomic, readonly, retain) NSArray *recurringOperations; + +// All the operations sent to the recurrence machine should be considered as prototypes. +// That means whenever the recurrence machine needs to do stuff, it copies all the operations +// and enqueues the copied instances. This prevents stale state, +// and avoids resetting them too. + +// The recurring operations array is available for KVO. If you need to remove stuff, +// or if you have to reorder stuff, you can invoke -mutableArrayValueForKey: +// before a more proper API is introduced. + + +- (void) beginPostponingOperations; +- (void) endPostponingOperations; +- (BOOL) isPostponingOperations; +@property (nonatomic, readonly, assign) NSUInteger postponingRequestCount; + +// Instead of locking and unlocking the operation queue, which might not always be an option, +// this set of methods simply work on the internal timer held by the recurrence machine. +// Whenever operations are postponed, the timer is invalidated and destroyed; +// the timer is re-created whenever operations cease to be postponed. + +// That means if the recurrence machine has an interval of 30 seconds, +// the recreated timer will not fire right after the operations are not postponed; +// the timer will fire 30 seconds after that. + +// If you need to immediately resume all the operations, call -scheduleOperationsNow. + +// The postponing request count is only exposed for debugging purposes; +// do not rely on its value for anything; it is not considered to conform to KVO +// and its accuracy is not vetted at all. + + +- (BOOL) scheduleOperationsNow; + +// If the operations were still running, this method returns NO; it’ll do nothing. +// Otherwise, if the queue is empty, it starts a new interval +// where things will happen again after `recurrenceInterval` seconds. + +// If operations are rescheduled properly, the internal timer will also be reset. + + +- (NSOperation *) newPostponingWrapperPrefix NS_RETURNS_RETAINED; +- (NSOperation *) newPostponingWrapperSuffix NS_RETURNS_RETAINED; + +// They call -beginPostponingOperations and -endPostponingOperations on self +// and are sent to the operation queue in this order: +// +// { Prefix } - { Real Operation } - { Suffix } +// +// where the real operation is dependent on the prefix, and +// the suffix is dependent on the real operation. + +@end diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m new file mode 100644 index 0000000..0c8b696 --- /dev/null +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -0,0 +1,174 @@ +// +// IRRecurrenceMachine.m +// IRRecurrenceMachine +// +// Created by Evadne Wu on 11/4/11. +// Copyright (c) 2011 __MyCompanyName__. All rights reserved. +// + +#import "IRRecurrenceMachine.h" + +@interface IRRecurrenceMachine () + +@property (nonatomic, readwrite, retain) NSOperationQueue *queue; +@property (nonatomic, readwrite, retain) NSArray *recurringOperations; +@property (nonatomic, readwrite, retain) NSTimer *timer; +@property (nonatomic, readwrite, assign) NSUInteger postponingRequestCount; + +@end + + +@implementation IRRecurrenceMachine + +@synthesize queue, recurrenceInterval, recurringOperations, postponingRequestCount; +@synthesize timer; + +- (id) init { + + return [self initWithQueue:nil]; + +} + +- (id) initWithQueue:(NSOperationQueue *)aQueue { + + self = [super init]; + if (!self) + return nil; + + if (!aQueue) + aQueue = [[[NSOperationQueue alloc] init] autorelease]; + + self.queue = aQueue; + self.recurrenceInterval = 30; + + [self timer]; + + return self; + +} + +- (void) addRecurringOperation:(NSOperation *)anOperation { + + NSParameterAssert(![self.recurringOperations containsObject:anOperation]); + + [[self mutableArrayValueForKey:@"recurringOperations"] addObject:anOperation]; + +} + +- (void) setRecurrenceInterval:(NSTimeInterval)newInterval { + + if (recurrenceInterval == newInterval) + return; + + [self willChangeValueForKey:@"recurrenceInterval"]; + + recurrenceInterval = newInterval; + + [self didChangeValueForKey:@"recurrenceInterval"]; + + [self.timer invalidate]; + + if (![self isPostponingOperations]) + [self timer]; + +} + +- (NSTimer *) timer { + + if (timer) + return timer; + + timer = [[NSTimer scheduledTimerWithTimeInterval:self.recurrenceInterval target:self selector:@selector(handleTimerFire:) userInfo:nil repeats:YES] retain]; + + return timer; + +} + +- (void) handleTimerFire:(NSTimer *)aTimer { + + BOOL didSchedule = [self scheduleOperationsNow]; + NSParameterAssert(didSchedule); + +} + +- (BOOL) scheduleOperationsNow { + + if (self.queue.operationCount) + return NO; + + [self beginPostponingOperations]; + + [recurringOperations enumerateObjectsUsingBlock: ^ (NSOperation *operationPrototype, NSUInteger idx, BOOL *stop) { + + NSOperation *prefix = [[self newPostponingWrapperPrefix] autorelease]; + NSOperation *operation = [[operationPrototype copy] autorelease]; + NSOperation *suffix = [[self newPostponingWrapperPrefix] autorelease]; + + [operation addDependency:prefix]; + [suffix addDependency:operation]; + + [queue addOperation:prefix]; + [queue addOperation:operation]; + [queue addOperation:suffix]; + + }]; + + [self endPostponingOperations]; + + return YES; + +} + +- (NSOperation *) newPostponingWrapperPrefix { + + __block typeof(self) nrSelf = self; + + return [NSBlockOperation blockOperationWithBlock: ^ { + [nrSelf beginPostponingOperations]; + }]; + +} + +- (NSOperation *) newPostponingWrapperSuffix { + + __block typeof(self) nrSelf = self; + + return [NSBlockOperation blockOperationWithBlock: ^ { + [nrSelf endPostponingOperations]; + }]; + +} + +- (void) beginPostponingOperations { + + self.postponingRequestCount += 1; + + if (postponingRequestCount == 1) { + + [self.timer invalidate]; + self.timer = nil; + + } + +} + +- (void) endPostponingOperations { + + NSParameterAssert(postponingRequestCount > 0); + self.postponingRequestCount -= 1; + + if (!postponingRequestCount) { + + [self timer]; + + } + +} + +- (BOOL) isPostponingOperations { + + return !!(self.postponingRequestCount); + +} + +@end From 038566c3d81fad2a1b03c1dde10aceeed58bab5a Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Fri, 25 Nov 2011 17:30:42 +0800 Subject: [PATCH 2/9] fixes bugs --- IRRecurrenceMachine/IRRecurrenceMachine.m | 27 +++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m index 0c8b696..caf185e 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.m +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -23,6 +23,16 @@ @implementation IRRecurrenceMachine @synthesize queue, recurrenceInterval, recurringOperations, postponingRequestCount; @synthesize timer; +- (void) dealloc { + + [queue release]; + [recurringOperations release]; + [timer invalidate]; + [timer release]; + [super dealloc]; + +} + - (id) init { return [self initWithQueue:nil]; @@ -40,6 +50,7 @@ - (id) initWithQueue:(NSOperationQueue *)aQueue { self.queue = aQueue; self.recurrenceInterval = 30; + self.recurringOperations = [NSArray array]; [self timer]; @@ -66,7 +77,9 @@ - (void) setRecurrenceInterval:(NSTimeInterval)newInterval { [self didChangeValueForKey:@"recurrenceInterval"]; - [self.timer invalidate]; + [timer invalidate]; + [timer release]; + timer = nil; if (![self isPostponingOperations]) [self timer]; @@ -98,12 +111,12 @@ - (BOOL) scheduleOperationsNow { [self beginPostponingOperations]; - [recurringOperations enumerateObjectsUsingBlock: ^ (NSOperation *operationPrototype, NSUInteger idx, BOOL *stop) { + [self.recurringOperations enumerateObjectsUsingBlock: ^ (NSOperation *operationPrototype, NSUInteger idx, BOOL *stop) { NSOperation *prefix = [[self newPostponingWrapperPrefix] autorelease]; NSOperation *operation = [[operationPrototype copy] autorelease]; NSOperation *suffix = [[self newPostponingWrapperPrefix] autorelease]; - + [operation addDependency:prefix]; [suffix addDependency:operation]; @@ -123,9 +136,9 @@ - (NSOperation *) newPostponingWrapperPrefix { __block typeof(self) nrSelf = self; - return [NSBlockOperation blockOperationWithBlock: ^ { + return [[NSBlockOperation blockOperationWithBlock: ^ { [nrSelf beginPostponingOperations]; - }]; + }] retain]; } @@ -133,9 +146,9 @@ - (NSOperation *) newPostponingWrapperSuffix { __block typeof(self) nrSelf = self; - return [NSBlockOperation blockOperationWithBlock: ^ { + return [[NSBlockOperation blockOperationWithBlock: ^ { [nrSelf endPostponingOperations]; - }]; + }] retain]; } From f01d73024f6675d0bd0b94432f4dd9ddab19f94a Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Tue, 6 Dec 2011 20:00:33 +0800 Subject: [PATCH 3/9] fixes several bugs --- IRRecurrenceMachine/IRRecurrenceMachine.h | 2 +- IRRecurrenceMachine/IRRecurrenceMachine.m | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.h b/IRRecurrenceMachine/IRRecurrenceMachine.h index 44d2d4f..82ef7b2 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.h +++ b/IRRecurrenceMachine/IRRecurrenceMachine.h @@ -42,7 +42,7 @@ - (void) beginPostponingOperations; - (void) endPostponingOperations; - (BOOL) isPostponingOperations; -@property (nonatomic, readonly, assign) NSUInteger postponingRequestCount; +@property (nonatomic, readonly, assign) NSInteger postponingRequestCount; // Instead of locking and unlocking the operation queue, which might not always be an option, // this set of methods simply work on the internal timer held by the recurrence machine. diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m index caf185e..5a2ba35 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.m +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -13,7 +13,7 @@ @interface IRRecurrenceMachine () @property (nonatomic, readwrite, retain) NSOperationQueue *queue; @property (nonatomic, readwrite, retain) NSArray *recurringOperations; @property (nonatomic, readwrite, retain) NSTimer *timer; -@property (nonatomic, readwrite, assign) NSUInteger postponingRequestCount; +@property (nonatomic, readwrite, assign) NSInteger postponingRequestCount; @end @@ -115,7 +115,7 @@ - (BOOL) scheduleOperationsNow { NSOperation *prefix = [[self newPostponingWrapperPrefix] autorelease]; NSOperation *operation = [[operationPrototype copy] autorelease]; - NSOperation *suffix = [[self newPostponingWrapperPrefix] autorelease]; + NSOperation *suffix = [[self newPostponingWrapperSuffix] autorelease]; [operation addDependency:prefix]; [suffix addDependency:operation]; @@ -153,6 +153,13 @@ - (NSOperation *) newPostponingWrapperSuffix { } - (void) beginPostponingOperations { + + if (![NSThread isMainThread]) { + [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:YES]; + return; + } + + NSParameterAssert([NSThread isMainThread]); self.postponingRequestCount += 1; @@ -166,6 +173,13 @@ - (void) beginPostponingOperations { } - (void) endPostponingOperations { + + if (![NSThread isMainThread]) { + [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:YES]; + return; + } + + NSParameterAssert([NSThread isMainThread]); NSParameterAssert(postponingRequestCount > 0); self.postponingRequestCount -= 1; From b26ba7566fd4566120db508fe13bf15a94abb16f Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Wed, 14 Dec 2011 18:19:00 +0800 Subject: [PATCH 4/9] =?UTF-8?q?don=E2=80=99t=20assume=20that=20reschedulin?= =?UTF-8?q?g=20will=20always=20finish=20in-time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IRRecurrenceMachine/IRRecurrenceMachine.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m index 5a2ba35..ba194be 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.m +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -99,8 +99,11 @@ - (NSTimer *) timer { - (void) handleTimerFire:(NSTimer *)aTimer { - BOOL didSchedule = [self scheduleOperationsNow]; - NSParameterAssert(didSchedule); + // BOOL didSchedule = + [self scheduleOperationsNow]; + + + // NSParameterAssert(didSchedule); } From b75187dc0f42b4e483855899bd13deb86a023192 Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Sun, 18 Dec 2011 00:21:49 +0800 Subject: [PATCH 5/9] OS X target --- IRRecurrenceMachine.xcodeproj/project.pbxproj | 172 ++++++++++++++++++ .../IRRecurrenceMachineX-Info.plist | 30 +++ .../IRRecurrenceMachineX-Prefix.pch | 7 + IRRecurrenceMachineX/IRRecurrenceMachineX.h | 10 + IRRecurrenceMachineX/IRRecurrenceMachineX.m | 9 + .../en.lproj/InfoPlist.strings | 2 + 6 files changed, 230 insertions(+) create mode 100644 IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist create mode 100644 IRRecurrenceMachineX/IRRecurrenceMachineX-Prefix.pch create mode 100644 IRRecurrenceMachineX/IRRecurrenceMachineX.h create mode 100644 IRRecurrenceMachineX/IRRecurrenceMachineX.m create mode 100644 IRRecurrenceMachineX/en.lproj/InfoPlist.strings diff --git a/IRRecurrenceMachine.xcodeproj/project.pbxproj b/IRRecurrenceMachine.xcodeproj/project.pbxproj index 99c9c3a..a55e9b8 100644 --- a/IRRecurrenceMachine.xcodeproj/project.pbxproj +++ b/IRRecurrenceMachine.xcodeproj/project.pbxproj @@ -9,6 +9,10 @@ /* Begin PBXBuildFile section */ FF22282D1463C77300541E31 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF22282C1463C77300541E31 /* Foundation.framework */; }; FF2228331463C77300541E31 /* IRRecurrenceMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2228321463C77300541E31 /* IRRecurrenceMachine.m */; }; + FF460D16149CF8B800DB7F0B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF460D15149CF8B800DB7F0B /* Cocoa.framework */; }; + FF460D20149CF8B800DB7F0B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FF460D1E149CF8B800DB7F0B /* InfoPlist.strings */; }; + FF460D24149CF8B800DB7F0B /* IRRecurrenceMachineX.m in Sources */ = {isa = PBXBuildFile; fileRef = FF460D23149CF8B800DB7F0B /* IRRecurrenceMachineX.m */; }; + FF460D29149CF8CE00DB7F0B /* IRRecurrenceMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2228321463C77300541E31 /* IRRecurrenceMachine.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -17,6 +21,16 @@ FF2228301463C77300541E31 /* IRRecurrenceMachine-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IRRecurrenceMachine-Prefix.pch"; sourceTree = ""; }; FF2228311463C77300541E31 /* IRRecurrenceMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IRRecurrenceMachine.h; sourceTree = ""; }; FF2228321463C77300541E31 /* IRRecurrenceMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IRRecurrenceMachine.m; sourceTree = ""; }; + FF460D14149CF8B800DB7F0B /* IRRecurrenceMachineX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IRRecurrenceMachineX.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FF460D15149CF8B800DB7F0B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; + FF460D18149CF8B800DB7F0B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + FF460D19149CF8B800DB7F0B /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + FF460D1A149CF8B800DB7F0B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + FF460D1D149CF8B800DB7F0B /* IRRecurrenceMachineX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "IRRecurrenceMachineX-Info.plist"; sourceTree = ""; }; + FF460D1F149CF8B800DB7F0B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + FF460D21149CF8B800DB7F0B /* IRRecurrenceMachineX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IRRecurrenceMachineX-Prefix.pch"; sourceTree = ""; }; + FF460D22149CF8B800DB7F0B /* IRRecurrenceMachineX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IRRecurrenceMachineX.h; sourceTree = ""; }; + FF460D23149CF8B800DB7F0B /* IRRecurrenceMachineX.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IRRecurrenceMachineX.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -28,6 +42,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FF460D10149CF8B800DB7F0B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FF460D16149CF8B800DB7F0B /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -35,6 +57,7 @@ isa = PBXGroup; children = ( FF22282E1463C77300541E31 /* IRRecurrenceMachine */, + FF460D1B149CF8B800DB7F0B /* IRRecurrenceMachineX */, FF22282B1463C77300541E31 /* Frameworks */, FF22282A1463C77300541E31 /* Products */, ); @@ -44,6 +67,7 @@ isa = PBXGroup; children = ( FF2228291463C77300541E31 /* libIRRecurrenceMachine.a */, + FF460D14149CF8B800DB7F0B /* IRRecurrenceMachineX.framework */, ); name = Products; sourceTree = ""; @@ -52,6 +76,8 @@ isa = PBXGroup; children = ( FF22282C1463C77300541E31 /* Foundation.framework */, + FF460D15149CF8B800DB7F0B /* Cocoa.framework */, + FF460D17149CF8B800DB7F0B /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; @@ -74,6 +100,36 @@ name = "Supporting Files"; sourceTree = ""; }; + FF460D17149CF8B800DB7F0B /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + FF460D18149CF8B800DB7F0B /* AppKit.framework */, + FF460D19149CF8B800DB7F0B /* CoreData.framework */, + FF460D1A149CF8B800DB7F0B /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + FF460D1B149CF8B800DB7F0B /* IRRecurrenceMachineX */ = { + isa = PBXGroup; + children = ( + FF460D22149CF8B800DB7F0B /* IRRecurrenceMachineX.h */, + FF460D23149CF8B800DB7F0B /* IRRecurrenceMachineX.m */, + FF460D1C149CF8B800DB7F0B /* Supporting Files */, + ); + path = IRRecurrenceMachineX; + sourceTree = ""; + }; + FF460D1C149CF8B800DB7F0B /* Supporting Files */ = { + isa = PBXGroup; + children = ( + FF460D1D149CF8B800DB7F0B /* IRRecurrenceMachineX-Info.plist */, + FF460D1E149CF8B800DB7F0B /* InfoPlist.strings */, + FF460D21149CF8B800DB7F0B /* IRRecurrenceMachineX-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -84,6 +140,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FF460D11149CF8B800DB7F0B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -104,6 +167,24 @@ productReference = FF2228291463C77300541E31 /* libIRRecurrenceMachine.a */; productType = "com.apple.product-type.library.static"; }; + FF460D13149CF8B800DB7F0B /* IRRecurrenceMachineX */ = { + isa = PBXNativeTarget; + buildConfigurationList = FF460D27149CF8B800DB7F0B /* Build configuration list for PBXNativeTarget "IRRecurrenceMachineX" */; + buildPhases = ( + FF460D0F149CF8B800DB7F0B /* Sources */, + FF460D10149CF8B800DB7F0B /* Frameworks */, + FF460D11149CF8B800DB7F0B /* Headers */, + FF460D12149CF8B800DB7F0B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = IRRecurrenceMachineX; + productName = IRRecurrenceMachineX; + productReference = FF460D14149CF8B800DB7F0B /* IRRecurrenceMachineX.framework */; + productType = "com.apple.product-type.framework"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -122,10 +203,22 @@ projectRoot = ""; targets = ( FF2228281463C77300541E31 /* IRRecurrenceMachine */, + FF460D13149CF8B800DB7F0B /* IRRecurrenceMachineX */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + FF460D12149CF8B800DB7F0B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FF460D20149CF8B800DB7F0B /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ FF2228251463C77300541E31 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -135,8 +228,28 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FF460D0F149CF8B800DB7F0B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FF460D24149CF8B800DB7F0B /* IRRecurrenceMachineX.m in Sources */, + FF460D29149CF8CE00DB7F0B /* IRRecurrenceMachine.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXVariantGroup section */ + FF460D1E149CF8B800DB7F0B /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + FF460D1F149CF8B800DB7F0B /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ FF2228341463C77300541E31 /* Debug */ = { isa = XCBuildConfiguration; @@ -202,6 +315,56 @@ }; name = Release; }; + FF460D25149CF8B800DB7F0B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", + ); + FRAMEWORK_VERSION = A; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "IRRecurrenceMachineX/IRRecurrenceMachineX-Prefix.pch"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + WRAPPER_EXTENSION = framework; + }; + name = Debug; + }; + FF460D26149CF8B800DB7F0B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", + ); + FRAMEWORK_VERSION = A; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "IRRecurrenceMachineX/IRRecurrenceMachineX-Prefix.pch"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -221,6 +384,15 @@ FF2228381463C77300541E31 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FF460D27149CF8B800DB7F0B /* Build configuration list for PBXNativeTarget "IRRecurrenceMachineX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FF460D25149CF8B800DB7F0B /* Debug */, + FF460D26149CF8B800DB7F0B /* Release */, + ); + defaultConfigurationIsVisible = 0; }; /* End XCConfigurationList section */ }; diff --git a/IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist b/IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist new file mode 100644 index 0000000..de2911e --- /dev/null +++ b/IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.iridia.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2011 Iridia Productions. All rights reserved. + NSPrincipalClass + + + diff --git a/IRRecurrenceMachineX/IRRecurrenceMachineX-Prefix.pch b/IRRecurrenceMachineX/IRRecurrenceMachineX-Prefix.pch new file mode 100644 index 0000000..365013a --- /dev/null +++ b/IRRecurrenceMachineX/IRRecurrenceMachineX-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'IRRecurrenceMachineX' target in the 'IRRecurrenceMachineX' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/IRRecurrenceMachineX/IRRecurrenceMachineX.h b/IRRecurrenceMachineX/IRRecurrenceMachineX.h new file mode 100644 index 0000000..040435b --- /dev/null +++ b/IRRecurrenceMachineX/IRRecurrenceMachineX.h @@ -0,0 +1,10 @@ +// +// IRRecurrenceMachineX.h +// IRRecurrenceMachineX +// +// Created by Evadne Wu on 12/18/11. +// Copyright (c) 2011 Iridia Productions. All rights reserved. +// + +#import +#import "IRRecurrenceMachine.h" diff --git a/IRRecurrenceMachineX/IRRecurrenceMachineX.m b/IRRecurrenceMachineX/IRRecurrenceMachineX.m new file mode 100644 index 0000000..f4ab855 --- /dev/null +++ b/IRRecurrenceMachineX/IRRecurrenceMachineX.m @@ -0,0 +1,9 @@ +// +// IRRecurrenceMachineX.m +// IRRecurrenceMachineX +// +// Created by Evadne Wu on 12/18/11. +// Copyright (c) 2011 Iridia Productions. All rights reserved. +// + +#import "IRRecurrenceMachineX.h" diff --git a/IRRecurrenceMachineX/en.lproj/InfoPlist.strings b/IRRecurrenceMachineX/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/IRRecurrenceMachineX/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + From 8ae0d8412a49c166e7fa8d86fe9e4427287ce0e1 Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Mon, 19 Dec 2011 01:35:47 +0800 Subject: [PATCH 6/9] Builds as an OS X private framework --- IRRecurrenceMachine.xcodeproj/project.pbxproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/IRRecurrenceMachine.xcodeproj/project.pbxproj b/IRRecurrenceMachine.xcodeproj/project.pbxproj index a55e9b8..43ac68b 100644 --- a/IRRecurrenceMachine.xcodeproj/project.pbxproj +++ b/IRRecurrenceMachine.xcodeproj/project.pbxproj @@ -332,6 +332,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; INFOPLIST_FILE = "IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist"; + INSTALL_PATH = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -358,6 +359,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; INFOPLIST_FILE = "IRRecurrenceMachineX/IRRecurrenceMachineX-Info.plist"; + INSTALL_PATH = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; @@ -393,6 +395,7 @@ FF460D26149CF8B800DB7F0B /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; From 4425069eac1f7610926dc1c1a37c3effc8f41a24 Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Sat, 28 Jan 2012 21:00:54 +0800 Subject: [PATCH 7/9] adds code that checks for thread safety --- IRRecurrenceMachine/IRRecurrenceMachine.h | 2 +- IRRecurrenceMachine/IRRecurrenceMachine.m | 48 +++++++++++------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.h b/IRRecurrenceMachine/IRRecurrenceMachine.h index 82ef7b2..bea76dc 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.h +++ b/IRRecurrenceMachine/IRRecurrenceMachine.h @@ -3,7 +3,7 @@ // IRRecurrenceMachine // // Created by Evadne Wu on 11/4/11. -// Copyright (c) 2011 __MyCompanyName__. All rights reserved. +// Copyright (c) 2011 Iridia Productions. All rights reserved. // #import diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m index ba194be..4f9319d 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.m +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -3,7 +3,7 @@ // IRRecurrenceMachine // // Created by Evadne Wu on 11/4/11. -// Copyright (c) 2011 __MyCompanyName__. All rights reserved. +// Copyright (c) 2011 Iridia Productions. All rights reserved. // #import "IRRecurrenceMachine.h" @@ -15,6 +15,9 @@ @interface IRRecurrenceMachine () @property (nonatomic, readwrite, retain) NSTimer *timer; @property (nonatomic, readwrite, assign) NSInteger postponingRequestCount; +@property (nonatomic, readwrite, assign) void *debugInitThreadPtr; +- (void) debugAssertThreadSafety; + @end @@ -22,6 +25,7 @@ @implementation IRRecurrenceMachine @synthesize queue, recurrenceInterval, recurringOperations, postponingRequestCount; @synthesize timer; +@synthesize debugInitThreadPtr; - (void) dealloc { @@ -45,12 +49,11 @@ - (id) initWithQueue:(NSOperationQueue *)aQueue { if (!self) return nil; - if (!aQueue) - aQueue = [[[NSOperationQueue alloc] init] autorelease]; + queue = aQueue ? aQueue : [[NSOperationQueue alloc] init]; + recurrenceInterval = 30; + recurringOperations = [[NSArray array] retain]; - self.queue = aQueue; - self.recurrenceInterval = 30; - self.recurringOperations = [NSArray array]; + debugInitThreadPtr = [NSThread currentThread]; [self timer]; @@ -99,12 +102,8 @@ - (NSTimer *) timer { - (void) handleTimerFire:(NSTimer *)aTimer { - // BOOL didSchedule = [self scheduleOperationsNow]; - - // NSParameterAssert(didSchedule); - } - (BOOL) scheduleOperationsNow { @@ -140,7 +139,9 @@ - (NSOperation *) newPostponingWrapperPrefix { __block typeof(self) nrSelf = self; return [[NSBlockOperation blockOperationWithBlock: ^ { - [nrSelf beginPostponingOperations]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [nrSelf beginPostponingOperations]; + }); }] retain]; } @@ -150,19 +151,16 @@ - (NSOperation *) newPostponingWrapperSuffix { __block typeof(self) nrSelf = self; return [[NSBlockOperation blockOperationWithBlock: ^ { - [nrSelf endPostponingOperations]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [nrSelf endPostponingOperations]; + }); }] retain]; } - (void) beginPostponingOperations { - if (![NSThread isMainThread]) { - [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:YES]; - return; - } - - NSParameterAssert([NSThread isMainThread]); + [self debugAssertThreadSafety]; self.postponingRequestCount += 1; @@ -177,14 +175,10 @@ - (void) beginPostponingOperations { - (void) endPostponingOperations { - if (![NSThread isMainThread]) { - [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:YES]; - return; - } - - NSParameterAssert([NSThread isMainThread]); + [self debugAssertThreadSafety]; NSParameterAssert(postponingRequestCount > 0); + self.postponingRequestCount -= 1; if (!postponingRequestCount) { @@ -201,4 +195,10 @@ - (BOOL) isPostponingOperations { } +- (void) debugAssertThreadSafety { + + NSAssert2([NSThread currentThread] == debugInitThreadPtr, @"Current Thread %@ differents from 0x%x", [NSThread currentThread], debugInitThreadPtr); + +} + @end From 1fadf7b37e088316d4e9af4984bd3e923df4a2f6 Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Mon, 19 Mar 2012 13:54:12 +0800 Subject: [PATCH 8/9] fixes a semantic issue --- IRRecurrenceMachine/IRRecurrenceMachine.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m index 4f9319d..96441ac 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.m +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -197,7 +197,7 @@ - (BOOL) isPostponingOperations { - (void) debugAssertThreadSafety { - NSAssert2([NSThread currentThread] == debugInitThreadPtr, @"Current Thread %@ differents from 0x%x", [NSThread currentThread], debugInitThreadPtr); + NSAssert2([NSThread currentThread] == debugInitThreadPtr, @"Current Thread %@ differents from 0x%x", [NSThread currentThread], (unsigned int)debugInitThreadPtr); } From 88d81d178db33a0e7ab6a9f8224b0878625163d7 Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Fri, 20 Apr 2012 14:13:36 +0800 Subject: [PATCH 9/9] adds safety assertion --- IRRecurrenceMachine/IRRecurrenceMachine.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IRRecurrenceMachine/IRRecurrenceMachine.m b/IRRecurrenceMachine/IRRecurrenceMachine.m index 96441ac..762e3b9 100644 --- a/IRRecurrenceMachine/IRRecurrenceMachine.m +++ b/IRRecurrenceMachine/IRRecurrenceMachine.m @@ -101,6 +101,8 @@ - (NSTimer *) timer { } - (void) handleTimerFire:(NSTimer *)aTimer { + + NSParameterAssert(![self isPostponingOperations]); [self scheduleOperationsNow];