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
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/snapshots/lru_cache.h"
#include <stddef.h>
#include "base/containers/hash_tables.h"
#include "base/containers/mru_cache.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
namespace {
class MRUCacheNSObjectDelegate {
public:
MRUCacheNSObjectDelegate(id<LRUCacheDelegate> delegate)
: delegate_(delegate) {}
MRUCacheNSObjectDelegate(const MRUCacheNSObjectDelegate& other) = default;
void operator()(const base::scoped_nsprotocol<id<NSObject>>& payload) const {
[delegate_ lruCacheWillEvictObject:payload.get()];
}
private:
id<LRUCacheDelegate> delegate_; // Weak.
};
struct NSObjectEqualTo {
bool operator()(const base::scoped_nsprotocol<id<NSObject>>& obj1,
const base::scoped_nsprotocol<id<NSObject>>& obj2) const {
return [obj1 isEqual:obj2];
}
};
struct NSObjectHash {
std::size_t operator()(
const base::scoped_nsprotocol<id<NSObject>>& obj) const {
return [obj hash];
}
};
template <class KeyType, class ValueType, class HashType>
struct MRUCacheNSObjectHashMap {
typedef base::hash_map<KeyType, ValueType, HashType, NSObjectEqualTo> Type;
};
class NSObjectMRUCache
: public base::MRUCacheBase<base::scoped_nsprotocol<id<NSObject>>,
base::scoped_nsprotocol<id<NSObject>>,
NSObjectHash,
MRUCacheNSObjectDelegate,
MRUCacheNSObjectHashMap> {
private:
typedef base::MRUCacheBase<base::scoped_nsprotocol<id<NSObject>>,
base::scoped_nsprotocol<id<NSObject>>,
NSObjectHash,
MRUCacheNSObjectDelegate,
MRUCacheNSObjectHashMap>
ParentType;
public:
NSObjectMRUCache(typename ParentType::size_type max_size,
const MRUCacheNSObjectDelegate& deletor)
: ParentType(max_size, deletor) {}
private:
DISALLOW_COPY_AND_ASSIGN(NSObjectMRUCache);
};
} // namespace
@interface LRUCache ()<LRUCacheDelegate>
@end
@implementation LRUCache {
scoped_ptr<NSObjectMRUCache> _cache;
}
@synthesize delegate = _delegate;
@synthesize maxCacheSize = _maxCacheSize;
- (instancetype)init {
NOTREACHED(); // Use initWithCacheSize: instead.
return nil;
}
- (instancetype)initWithCacheSize:(NSUInteger)maxCacheSize {
self = [super init];
if (self) {
_maxCacheSize = maxCacheSize;
MRUCacheNSObjectDelegate cacheDelegateDeletor(self);
_cache.reset(new NSObjectMRUCache(self.maxCacheSize, cacheDelegateDeletor));
}
return self;
}
- (id)objectForKey:(id<NSObject>)key {
base::scoped_nsprotocol<id<NSObject>> keyObj([key retain]);
auto it = _cache->Get(keyObj);
if (it == _cache->end())
return nil;
return it->second.get();
}
- (void)setObject:(id<NSObject>)value forKey:(NSObject*)key {
base::scoped_nsprotocol<id<NSObject>> keyObj([key copy]);
base::scoped_nsprotocol<id<NSObject>> valueObj([value retain]);
_cache->Put(keyObj, valueObj);
}
- (void)removeObjectForKey:(id<NSObject>)key {
base::scoped_nsprotocol<id<NSObject>> keyObj([key retain]);
auto it = _cache->Peek(keyObj);
if (it != _cache->end())
_cache->Erase(it);
}
- (void)removeAllObjects {
_cache->Clear();
}
- (NSUInteger)count {
return _cache->size();
}
- (BOOL)isEmpty {
return _cache->empty();
}
#pragma mark - Private
- (void)lruCacheWillEvictObject:(id<NSObject>)obj {
[self.delegate lruCacheWillEvictObject:obj];
}
@end
|