Mercurial > hg > orthanc
comparison UnitTests/MemoryCache.cpp @ 284:06aa7b7b6723
implementation of a single-threaded cache mechanism
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 12 Dec 2012 15:40:18 +0100 |
parents | c9977db00e1d |
children | 4031f73fe0e4 |
comparison
equal
deleted
inserted
replaced
283:c9977db00e1d | 284:06aa7b7b6723 |
---|---|
3 #include <glog/logging.h> | 3 #include <glog/logging.h> |
4 #include <memory> | 4 #include <memory> |
5 #include <boost/thread.hpp> | 5 #include <boost/thread.hpp> |
6 #include <boost/lexical_cast.hpp> | 6 #include <boost/lexical_cast.hpp> |
7 #include "../Core/IDynamicObject.h" | 7 #include "../Core/IDynamicObject.h" |
8 #include "../Core/MultiThreading/CacheIndex.h" | 8 #include "../Core/Cache/MemoryCache.h" |
9 | 9 |
10 | 10 |
11 TEST(CacheIndex, Basic) | 11 TEST(CacheIndex, Basic) |
12 { | 12 { |
13 Orthanc::CacheIndex<std::string> r; | 13 Orthanc::CacheIndex<std::string> r; |
64 | 64 |
65 ASSERT_TRUE(r.IsEmpty()); | 65 ASSERT_TRUE(r.IsEmpty()); |
66 } | 66 } |
67 | 67 |
68 | 68 |
69 namespace Orthanc | |
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 | |
82 class MemoryCache | |
83 { | |
84 private: | |
85 struct Page | |
86 { | |
87 std::string id_; | |
88 std::auto_ptr<IDynamicObject> content_; | |
89 }; | |
90 | |
91 ICacheProvider& provider_; | |
92 size_t cacheSize_; | |
93 CacheIndex<std::string, Page*> index_; | |
94 | |
95 Page& Load(const std::string& id) | |
96 { | |
97 // Reuse the cache entry if it already exists | |
98 Page* p = NULL; | |
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 | 69 |
182 | 70 |
183 namespace | 71 namespace |
184 { | 72 { |
185 class Integer : public Orthanc::IDynamicObject | 73 class Integer : public Orthanc::IDynamicObject |
203 { | 91 { |
204 return value_; | 92 return value_; |
205 } | 93 } |
206 }; | 94 }; |
207 | 95 |
208 class IntegerProvider : public Orthanc::ICacheProvider | 96 class IntegerProvider : public Orthanc::ICachePageProvider |
209 { | 97 { |
210 public: | 98 public: |
211 std::string log_; | 99 std::string log_; |
212 | 100 |
213 Orthanc::IDynamicObject* Provide(const std::string& s) | 101 Orthanc::IDynamicObject* Provide(const std::string& s) |