From a41c42ab4bcad18caecebf5ad204f1699a356380 Mon Sep 17 00:00:00 2001 From: Zachary Giles Date: Mon, 21 Oct 2013 11:38:08 -0400 Subject: [PATCH] Image ratelimiting / debouncing Adding a blocking function to prevent multiple callbacks at the same time (or close together) from causing either a) a function to throw an exception because an object is busy doing something already, b) getting into code where it looked like something was available but isn't now, or c) multiple pictures within a few seconds. This blocking is simple and works by creating a synchronization group which controls a BOOL so that only one call can edit the BOOL at the same time. It also sets a timer in another thread to reset the BOOL after some time (10seconds for now) so that we have up to 10s of unlimited bad calls against the function before another one wins. The logs state when a thread tried and won or lost. An earlier commit to make the 2.0f delay standard across the board helped here. Everything including the menubar call go through to ensure nothing fights with each other. --- memoryio/memoryio/TSAppDelegate.m | 45 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/memoryio/memoryio/TSAppDelegate.m b/memoryio/memoryio/TSAppDelegate.m index aa413d1..232c98d 100755 --- a/memoryio/memoryio/TSAppDelegate.m +++ b/memoryio/memoryio/TSAppDelegate.m @@ -106,7 +106,7 @@ - (IBAction)aboutAction:(id)sender - (IBAction)forceAction:(id)sender { - [self takePhotoWithDelay:2.0f]; + [self takeBlockedImage]; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification @@ -251,6 +251,7 @@ - (void) messageReceived:(natural_t)messageType withArgument:(void *)messageArgu case kIOMessageDeviceHasPoweredOn : // mainly for when the display goesto sleep and wakes up NSLog(@"messageReceived: got a kIOMessageDeviceHasPoweredOn - device powered on"); + [self takeBlockedImage]; break; case kIOMessageSystemWillSleep: IOAllowPowerChange(root_port,(long)messageArgument); @@ -261,7 +262,7 @@ - (void) messageReceived:(natural_t)messageType withArgument:(void *)messageArgu case kIOMessageSystemHasPoweredOn: // mainly for when the system goes to sleep and wakes up NSLog(@"messageReceived: got a kIOMessageSystemHasPoweredOn - system powered on"); - [self takePhotoWithDelay:2.0f]; + [self takeBlockedImage]; break; } } @@ -323,4 +324,42 @@ - (void) takePhotoWithDelay: (float) delay { } -@end \ No newline at end of file + +// Block image taking +// F these new-school selectors and mutable associated directories. Let's do this 1997 javascript style.. +// set a timer. If it tries to call again too fast, then drop the request. Sync setting a timer. +// Timer is a thread, so the sync will unlock and all is well. +BOOL imageBlocked = NO; +NSTimer *imageBlockedTimer; + +// +-(void) takeBlockedImage +{ + NSLog(@"takeBlockedImage: Trying to take lock..."); + BOOL iWin = NO; + @synchronized(self){ + if(!imageBlocked) { + imageBlocked = YES; + iWin = YES; + NSLog(@"unblockImage: blocking.."); + imageBlockedTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(unblockImage) userInfo:nil repeats:NO]; + } // end of if blocked + } // end of sync + if(iWin) { + NSLog(@"takeBlockedImage: I won"); + [self takePhotoWithDelay:2.0f]; + } else { + NSLog(@"takeBlockedImage: I lost"); + } // end of if iWin + + +} + +-(void) unblockImage +{ + NSLog(@"unblockImage: unblocking.."); + imageBlocked = NO; +} + + +@end