forked from profmaad/librabbitmq-objc
-
Notifications
You must be signed in to change notification settings - Fork 8
/
AMQPTTLManager.m
147 lines (118 loc) · 3.69 KB
/
AMQPTTLManager.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// AMQPTTLManager.m
// librabbitmq-objc
//
// Created by Pedro Gomes on 29/11/2012.
// Copyright (c) 2012 EF Education First. All rights reserved.
//
#import "AMQPTTLManager.h"
@interface AMQPTTLManager()
@property (nonatomic, strong) NSMutableArray *objects;
@property (nonatomic, strong) NSMutableArray *timers;
@end
@implementation AMQPTTLManager
{
dispatch_queue_t _lockQueue;
}
#pragma mark - Dealloc and Initialization
- (void)dealloc
{
[_timers enumerateObjectsUsingBlock:^(NSTimer *timer, NSUInteger idx, BOOL *stop) {
[timer invalidate];
}];
[_timers removeAllObjects];
[_objects removeAllObjects];
#if !OS_OBJECT_USE_OBJC
dispatch_release(_lockQueue);
#endif
}
- (id)initWithDelegate:(id<AMQPTTLManagerDelegate>)delegate
{
if ((self = [self init])) {
_delegate = delegate;
}
return self;
}
- (id)init
{
if ((self = [super init])) {
_objects = [[NSMutableArray alloc] init];
_timers = [[NSMutableArray alloc] init];
_lockQueue = dispatch_queue_create("com.librabbitmq-objc.ttlmanager.lock", NULL);
#if !OS_OBJECT_USE_OBJC
dispatch_retain(_lockQueue);
#endif
}
return self;
}
#pragma mark - Public Methods
- (void)addObject:(id)object ttl:(NSTimeInterval)ttl
{
dispatch_sync(_lockQueue, ^{
if ([_objects indexOfObject:object] != NSNotFound) {
return;
}
[_objects addObject:object];
NSTimer *timer = [NSTimer timerWithTimeInterval:ttl target:self selector:@selector(onTick:) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
[_timers addObject:timer];
});
}
- (void)onTick:(NSTimer *)timer
{
dispatch_sync(_lockQueue, ^{
NSUInteger indexOfTimer = [_timers indexOfObject:timer];
if (indexOfTimer == NSNotFound) {
return;
}
id object = [_objects objectAtIndex:indexOfTimer];
[self _cancelTimerForObject:object];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate ttlForObjectExpired:object];
});
});
}
- (BOOL)updateObject:(id)object ttl:(NSTimeInterval)ttl
{
__block BOOL updated = NO;
dispatch_sync(_lockQueue, ^{
NSUInteger indexOfObject = [_objects indexOfObject:object];
if (indexOfObject != NSNotFound) {
NSTimer *timerToUpdate = [_timers objectAtIndex:indexOfObject];
[timerToUpdate invalidate];
NSTimer *replacementTimer = [NSTimer timerWithTimeInterval:ttl target:self selector:@selector(onTick:) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:replacementTimer forMode:NSRunLoopCommonModes];
[_timers replaceObjectAtIndex:indexOfObject withObject:replacementTimer];
updated = YES;
}
});
return updated;
}
- (void)removeObject:(id)object
{
dispatch_sync(_lockQueue, ^{
[self _cancelTimerForObject:object];
});
}
- (void)removeAllObjects
{
dispatch_sync(_lockQueue, ^{
NSArray *objectsToRemove = [NSArray arrayWithArray:_objects];
__weak typeof(self) weakSelf = self;
[objectsToRemove enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
[weakSelf _cancelTimerForObject:object];
}];
});
}
- (void)_cancelTimerForObject:(id)object
{
NSUInteger indexOfObject = [_objects indexOfObject:object];
if (indexOfObject == NSNotFound) {
return;
}
NSTimer *timer = [_timers objectAtIndex:indexOfObject];
[timer invalidate];
[self.timers removeObject:timer];
[self.objects removeObjectAtIndex:indexOfObject];
}
@end