Permalink
Browse files

Initial commit (non persistent)

  • Loading branch information...
0 parents commit ff11655d88247c8736198cc6c0f911fa3d07b306 @thisandagain committed Jul 3, 2012
@@ -0,0 +1,12 @@
+.DS_Store
+*.swp
+*~.nib
+
+build/
+
+.xcodeproj/
+!*.xcodeproj/project.pbxproj
+*.mode1v3
+*.mode2v3
+
+xcuserdata
@@ -0,0 +1,56 @@
+//
+// EDQueue.h
+// queue
+//
+// Created by Andrew Sliwinski on 6/29/12.
+// Copyright (c) 2012 DIY, Co. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+//
+
+#define DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \
+static dispatch_once_t pred = 0; \
+__strong static id _sharedObject = nil; \
+dispatch_once(&pred, ^{ \
+_sharedObject = block(); \
+}); \
+return _sharedObject; \
+
+typedef enum {
+ kEDQueueResultSuccess,
+ kEDQueueResultFail,
+ kEDQueueResultCritical
+} EDQueueResult;
+
+//
+
+@class EDQueue;
+
+@protocol EDQueueDelegate <NSObject>
+@required
+- (EDQueueResult)queue:(EDQueue *)queue processJob:(NSDictionary *)job;
+@end
+
+//
+
+@interface EDQueue : NSObject
+{
+ @private NSMutableArray *queue;
+ @private NSTimer *timer;
+ @private NSUInteger active;
+}
+
+@property (nonatomic, assign) id<EDQueueDelegate> delegate;
+@property (nonatomic, assign) NSUInteger concurrencyLimit;
+@property (nonatomic, assign) CGFloat statusInterval;
+@property (nonatomic, assign) BOOL retryFailureImmediately;
+@property (nonatomic, assign) NSUInteger retryLimit;
+
++ (EDQueue *)sharedInstance;
+- (void)enqueueWithData:(id)data forTask:(NSString *)task;
+- (void)start;
+- (void)stop;
+
+@end
161 EDQueue.m
@@ -0,0 +1,161 @@
+//
+// EDQueue.m
+// queue
+//
+// Created by Andrew Sliwinski on 6/29/12.
+// Copyright (c) 2012 DIY, Co. All rights reserved.
+//
+
+#import "EDQueue.h"
+
+//
+
+@interface EDQueue ()
+@property (nonatomic, retain) NSMutableArray *queue;
+@property (nonatomic, retain) NSTimer *timer;
+@property (nonatomic, assign) NSUInteger active;
+@end
+
+//
+
+@implementation EDQueue
+
+@synthesize delegate = _delegate;
+@synthesize concurrencyLimit = _concurrencyLimit;
+@synthesize statusInterval = _statusInterval;
+@synthesize retryFailureImmediately = _retryFailureImmediately;
+@synthesize retryLimit = _retryLimit;
+@synthesize queue = _queue;
+@synthesize timer = _timer;
+@synthesize active = _active;
+
+#pragma mark - Init
+
++ (EDQueue *)sharedInstance
+{
+ DEFINE_SHARED_INSTANCE_USING_BLOCK(^{
+ return [[self alloc] init];
+ });
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self)
+ {
+ _concurrencyLimit = 2;
+ _statusInterval = 0.03f;
+ _retryFailureImmediately = true;
+ _retryLimit = 4;
+
+ _queue = [[NSMutableArray alloc] init];
+ _timer = [[NSTimer alloc] init];
+ _active = 0;
+ }
+ return self;
+}
+
+#pragma mark - Public methods
+
+/**
+ * Adds a new job to the queue.
+ *
+ * @param {id} Data
+ * @param {NSString} Task label
+ *
+ * @return {void}
+ */
+- (void)enqueueWithData:(id)data forTask:(NSString *)task
+{
+ [self.queue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:0], @"attempt",
+ task, @"task",
+ data, @"data",
+ nil]];
+}
+
+/**
+ * Starts the queue.
+ *
+ * @return {void}
+ */
+- (void)start
+{
+ self.timer = [NSTimer scheduledTimerWithTimeInterval:self.statusInterval target:self selector:@selector(tick) userInfo:nil repeats:true];
+}
+
+/**
+ * Stops the queue.
+ *
+ * @return {void}
+ */
+- (void)stop
+{
+ [self.timer invalidate];
+ self.timer = nil;
+}
+
+#pragma mark - Status loop
+
+- (void)tick
+{
+ dispatch_queue_t gcd = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
+ dispatch_async(gcd, ^{
+
+ if ([self.queue count] != 0 && active < self.concurrencyLimit) {
+ // Fetch job
+ id job = [self.queue objectAtIndex:0];
+ if (job != nil) {
+ [[job retain] autorelease];
+ [self.queue removeObjectAtIndex:0];
+ active++;
+ }
+
+ // Pass job to delegate
+ EDQueueResult result = [self.delegate queue:self processJob:job];
+ active--;
+
+ // Check result
+ switch (result) {
+ case kEDQueueResultSuccess:
+ NSLog(@"Win!!!!");
+ break;
+ case kEDQueueResultFail:
+ NSLog(@"FAIL!!!");
+ NSUInteger currentAttempt = [[job objectForKey:@"attempt"] intValue] + 1;
+ if (currentAttempt < self.retryLimit)
+ {
+ [job setValue:[NSNumber numberWithInt:currentAttempt] forKey:@"attempt"];
+ (self.retryFailureImmediately) ? [self.queue insertObject:job atIndex:0] : [self.queue addObject:job];
+ }
+ break;
+ case kEDQueueResultCritical:
+ [self errorWithMessage:@"Critical error. Stopping queue..."];
+ [self stop];
+ break;
+ }
+ }
+
+ });
+}
+
+#pragma mark - Private methods
+
+- (void)errorWithMessage:(NSString *)message
+{
+ NSLog(@"EDQueue Error: %@", message);
+}
+
+#pragma mark - Dealloc
+
+- (void)dealloc
+{
+ self.delegate = nil;
+
+ [_queue release]; _queue = nil;
+ [_timer release]; _timer = nil;
+
+ [super dealloc];
+}
+
+@end
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Andrew Sliwinski
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Oops, something went wrong.

0 comments on commit ff11655

Please sign in to comment.