-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFBLockManager.m
More file actions
145 lines (113 loc) · 2.92 KB
/
Copy pathFBLockManager.m
File metadata and controls
145 lines (113 loc) · 2.92 KB
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
//
// FBLockManager.m
// FBFileCache
//
// Created by Hiroshi Hashiguchi on 11/04/13.
//
#import "FBLockManager.h"
@interface FBLockManager ()
@property (nonatomic, retain) NSMutableDictionary* lockMap;
@property (nonatomic, retain) NSLock* wholeLock;
@property (nonatomic, retain) NSMutableSet* lockPool;
@property (nonatomic, retain) NSMutableSet* usingLockPool;
@end
#define INITIAL_LOCK_NUMBER 5
@implementation FBLockManager
@synthesize lockMap = lockMap_;
@synthesize wholeLock = wholeLock_;
@synthesize lockPool = lockPool_;
@synthesize usingLockPool = usingLockPool_;
#pragma mark -
#pragma mark Initialization and deallocation
- (id)init {
self = [super init];
if (self) {
self.lockMap = [NSMutableDictionary dictionary];
NSLock* lock;
lock = [[NSLock alloc] init];
self.wholeLock = lock;
[lock release];
self.lockPool = [NSMutableSet setWithCapacity:INITIAL_LOCK_NUMBER];
self.usingLockPool = [NSMutableSet setWithCapacity:INITIAL_LOCK_NUMBER];
int i;
for (i=0; i < INITIAL_LOCK_NUMBER; i++) {
lock = [[NSLock alloc] init];
[self.lockPool addObject:lock];
[lock release];
}
}
return self;
}
- (void)dealloc {
self.lockMap = nil;
self.wholeLock = nil;
self.lockPool = nil;
self.usingLockPool = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Manage lock pool (thread no-safe)
- (NSLock*)_getLockFromPool
{
NSLock* lock = [self.lockPool anyObject];
if (lock) {
[self.lockPool removeObject:lock];
} else {
lock = [[[NSLock alloc] init] autorelease];
}
[self.usingLockPool addObject:lock];
return lock;
}
- (void)_releaseToPoolWithLock:(NSLock*)lock
{
if ([lock tryLock]) {
[lock unlock];
}
[self.usingLockPool removeObject:lock];
[self.lockPool addObject:lock];
}
#pragma mark -
#pragma mark API
- (void)lockForKey:(NSString*)key
{
// implemetation of shared lock
[self.wholeLock lock];
[self.wholeLock unlock];
NSLock* currentLock = nil;
@synchronized (self) {
currentLock = [self.lockMap objectForKey:key];
if (currentLock == nil) {
currentLock = [self _getLockFromPool];
[self.lockMap setObject:currentLock forKey:key];
}
}
[currentLock lock];
}
- (void)unlockForKey:(NSString*)key
{
@synchronized (self) {
NSLock* currentLock = [self.lockMap objectForKey:key];
if (currentLock) {
[currentLock unlock];
[self.lockMap removeObjectForKey:key];
[self _releaseToPoolWithLock:currentLock];
}
}
}
- (void)lockForURL:(NSURL*)url
{
[self lockForKey:[url absoluteString]];
}
- (void)unlockForURL:(NSURL*)url
{
[self unlockForKey:[url absoluteString]];
}
- (void)lock
{
[self.wholeLock lock];
}
- (void)unlock
{
[self.wholeLock unlock];
}
@end