Mercurial > hg > orthanc
comparison UnitTests/MemoryCache.cpp @ 283:c9977db00e1d
caching
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 12 Dec 2012 15:32:15 +0100 |
parents | 915ed24547ea |
children | 06aa7b7b6723 |
comparison
equal
deleted
inserted
replaced
282:915ed24547ea | 283:c9977db00e1d |
---|---|
1 #include "gtest/gtest.h" | 1 #include "gtest/gtest.h" |
2 | 2 |
3 #include <glog/logging.h> | |
3 #include <memory> | 4 #include <memory> |
5 #include <boost/thread.hpp> | |
6 #include <boost/lexical_cast.hpp> | |
4 #include "../Core/IDynamicObject.h" | 7 #include "../Core/IDynamicObject.h" |
5 #include "../Core/MultiThreading/CacheIndex.h" | 8 #include "../Core/MultiThreading/CacheIndex.h" |
6 | 9 |
7 | 10 |
8 TEST(CacheIndex, Basic) | 11 TEST(CacheIndex, Basic) |
49 ASSERT_TRUE(r.Contains("b")); | 52 ASSERT_TRUE(r.Contains("b")); |
50 ASSERT_EQ(421, r.Invalidate("b")); | 53 ASSERT_EQ(421, r.Invalidate("b")); |
51 ASSERT_FALSE(r.Contains("b")); | 54 ASSERT_FALSE(r.Contains("b")); |
52 | 55 |
53 int p; | 56 int p; |
57 ASSERT_TRUE(r.Contains("a", p)); ASSERT_EQ(420, p); | |
58 ASSERT_TRUE(r.Contains("c", p)); ASSERT_EQ(422, p); | |
59 ASSERT_TRUE(r.Contains("d", p)); ASSERT_EQ(423, p); | |
60 | |
54 ASSERT_EQ("a", r.RemoveOldest(p)); ASSERT_EQ(420, p); | 61 ASSERT_EQ("a", r.RemoveOldest(p)); ASSERT_EQ(420, p); |
55 ASSERT_EQ("d", r.RemoveOldest(p)); ASSERT_EQ(423, p); | 62 ASSERT_EQ("d", r.RemoveOldest(p)); ASSERT_EQ(423, p); |
56 ASSERT_EQ("c", r.RemoveOldest(p)); ASSERT_EQ(422, p); | 63 ASSERT_EQ("c", r.RemoveOldest(p)); ASSERT_EQ(422, p); |
57 | 64 |
58 ASSERT_TRUE(r.IsEmpty()); | 65 ASSERT_TRUE(r.IsEmpty()); |
59 } | 66 } |
60 | 67 |
61 | 68 |
62 namespace Orthanc | 69 namespace Orthanc |
63 { | 70 { |
71 | |
72 class ICacheProvider | |
73 { | |
74 public: | |
75 virtual ~ICacheProvider() | |
76 { | |
77 } | |
78 | |
79 virtual IDynamicObject* Provide(const std::string& id) = 0; | |
80 }; | |
81 | |
64 class MemoryCache | 82 class MemoryCache |
65 { | 83 { |
66 private: | 84 private: |
67 struct CacheElement | 85 struct Page |
68 { | 86 { |
69 std::string id_; | 87 std::string id_; |
70 std::auto_ptr<IDynamicObject> object_; | 88 std::auto_ptr<IDynamicObject> content_; |
71 }; | 89 }; |
72 | 90 |
73 //typedef std::map<CacheElement | 91 ICacheProvider& provider_; |
74 | 92 size_t cacheSize_; |
75 size_t places_; | 93 CacheIndex<std::string, Page*> index_; |
76 CacheIndex<const char*> index_; | 94 |
77 | 95 Page& Load(const std::string& id) |
78 public: | 96 { |
79 | 97 // Reuse the cache entry if it already exists |
80 }; | 98 Page* p = NULL; |
81 } | 99 if (index_.Contains(id, p)) |
100 { | |
101 assert(p != NULL); | |
102 index_.TagAsMostRecent(id); | |
103 return *p; | |
104 } | |
105 | |
106 // The id is not in the cache yet. Make some room if the cache | |
107 // is full. | |
108 if (index_.GetSize() == cacheSize_) | |
109 { | |
110 index_.RemoveOldest(p); | |
111 delete p; | |
112 } | |
113 | |
114 // Create a new cache page | |
115 std::auto_ptr<Page> result(new Page); | |
116 result->id_ = id; | |
117 result->content_.reset(provider_.Provide(id)); | |
118 | |
119 // Add the newly create page to the cache | |
120 p = result.release(); | |
121 index_.Add(id, p); | |
122 return *p; | |
123 } | |
124 | |
125 public: | |
126 class Accessor | |
127 { | |
128 friend class MemoryCache; | |
129 | |
130 private: | |
131 Page& element_; | |
132 | |
133 Accessor(Page& element) : | |
134 element_(element) | |
135 { | |
136 } | |
137 | |
138 public: | |
139 const std::string GetId() const | |
140 { | |
141 return element_.id_; | |
142 } | |
143 | |
144 IDynamicObject& GetContent() | |
145 { | |
146 return *element_.content_; | |
147 } | |
148 | |
149 const IDynamicObject& GetContent() const | |
150 { | |
151 return *element_.content_; | |
152 } | |
153 }; | |
154 | |
155 MemoryCache(ICacheProvider& provider, | |
156 size_t cacheSize) : | |
157 provider_(provider), | |
158 cacheSize_(cacheSize) | |
159 { | |
160 } | |
161 | |
162 ~MemoryCache() | |
163 { | |
164 while (!index_.IsEmpty()) | |
165 { | |
166 Page* element = NULL; | |
167 index_.RemoveOldest(element); | |
168 assert(element != NULL); | |
169 delete element; | |
170 } | |
171 } | |
172 | |
173 Accessor* Access(const std::string& id) | |
174 { | |
175 Page& element = Load(id); | |
176 return new Accessor(element); | |
177 } | |
178 }; | |
179 } | |
180 | |
181 | |
182 | |
183 namespace | |
184 { | |
185 class Integer : public Orthanc::IDynamicObject | |
186 { | |
187 private: | |
188 std::string& log_; | |
189 int value_; | |
190 | |
191 public: | |
192 Integer(std::string& log, int v) : log_(log), value_(v) | |
193 { | |
194 } | |
195 | |
196 virtual ~Integer() | |
197 { | |
198 LOG(INFO) << "Removing cache entry for " << value_; | |
199 log_ += boost::lexical_cast<std::string>(value_) + " "; | |
200 } | |
201 | |
202 int GetValue() const | |
203 { | |
204 return value_; | |
205 } | |
206 }; | |
207 | |
208 class IntegerProvider : public Orthanc::ICacheProvider | |
209 { | |
210 public: | |
211 std::string log_; | |
212 | |
213 Orthanc::IDynamicObject* Provide(const std::string& s) | |
214 { | |
215 LOG(INFO) << "Providing " << s; | |
216 return new Integer(log_, boost::lexical_cast<int>(s)); | |
217 } | |
218 }; | |
219 } | |
220 | |
221 | |
222 TEST(MemoryCache, Basic) | |
223 { | |
224 IntegerProvider provider; | |
225 | |
226 { | |
227 Orthanc::MemoryCache cache(provider, 3); | |
228 std::auto_ptr<Orthanc::MemoryCache::Accessor> a; | |
229 a.reset(cache.Access("42")); // 42 -> exit | |
230 a.reset(cache.Access("43")); // 43, 42 -> exit | |
231 a.reset(cache.Access("45")); // 45, 43, 42 -> exit | |
232 a.reset(cache.Access("42")); // 42, 45, 43 -> exit | |
233 a.reset(cache.Access("43")); // 43, 42, 45 -> exit | |
234 a.reset(cache.Access("47")); // 45 is removed; 47, 43, 42 -> exit | |
235 a.reset(cache.Access("44")); // 42 is removed; 44, 47, 43 -> exit | |
236 a.reset(cache.Access("42")); // 43 is removed; 42, 44, 47 -> exit | |
237 // Closing the cache: 47, 44, 42 are successively removed | |
238 } | |
239 | |
240 ASSERT_EQ("45 42 43 47 44 42 ", provider.log_); | |
241 } |