1 #ifndef LSST_UTILS_CACHE_H 2 #define LSST_UTILS_CACHE_H 7 #include "boost/multi_index_container.hpp" 8 #include "boost/multi_index/sequenced_index.hpp" 9 #include "boost/multi_index/hashed_index.hpp" 10 #include "boost/multi_index/composite_key.hpp" 11 #include "boost/multi_index/member.hpp" 12 #include "boost/format.hpp" 20 #ifdef LSST_CACHE_DEBUG 52 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
64 _container.template get<Hash>().
reserve(maxElements);
65 #ifdef LSST_CACHE_DEBUG 66 _debuggingEnabled =
false;
69 _requests.reserve(maxElements);
80 #ifdef LSST_CACHE_DEBUG 108 template <
typename Generator>
132 void add(Key
const& key, Value
const& value);
156 bool contains(Key
const& key) {
return _lookup(key).second; }
178 #ifdef LSST_CACHE_DEBUG 179 void enableDebugging() { _debuggingEnabled =
true; }
188 _container.template get<Sequence>().pop_back();
200 typedef boost::multi_index_container<
202 boost::multi_index::indexed_by<
203 boost::multi_index::sequenced<boost::multi_index::tag<Sequence>>,
204 boost::multi_index::hashed_unique<
205 boost::multi_index::tag<Hash>,
206 boost::multi_index::member<Element, Key, &Element::first>,
207 KeyHash>>> Container;
215 auto const& hashContainer = _container.template get<Hash>();
216 auto it = hashContainer.find(key);
217 bool found = (it != hashContainer.end());
219 _container.relocate(_container.template get<Sequence>().begin(),
220 _container.template project<Sequence>(it));
222 #ifdef LSST_CACHE_DEBUG 223 if (_debuggingEnabled) {
224 _requests.push_back(key);
233 void _addNew(Key
const& key, Value
const& value) {
234 _container.template get<Sequence>().emplace_front(key, value);
239 Container _container;
240 #ifdef LSST_CACHE_DEBUG 241 bool _debuggingEnabled;
253 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
254 template <
typename Generator>
259 auto result = _lookup(key);
261 return result.first->second;
263 Value value = func(key);
268 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
270 auto result = _lookup(key);
272 return result.first->second;
275 (boost::format(
"Unable to find key: %s") % key).str());
278 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
280 auto result = _lookup(key);
281 if (!result.second) {
286 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
290 for (
auto & keyValue : _container.template get<Sequence>()) {
296 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
299 _container.template get<Sequence>().pop_back();
303 #ifdef LSST_CACHE_DEBUG 304 template <
typename Key,
typename Value,
typename KeyHash,
typename KeyPred>
306 if (!_debuggingEnabled) {
309 std::string filename = (boost::format(
"lsst-cache-%s-%d.dat") %
312 for (
auto const&
key : _requests) {
316 std::cerr <<
"Wrote cache requests to " << filename <<
": " << _hits <<
"/" << _total <<
" hits";
324 #endif // ifndef LSST_UTILS_CACHE_H std::string demangleType(std::string const _typeName)
Value operator[](Key const &key)
void reserve(std::size_t maxElements)
Change the capacity of the cache.
Cache & operator=(Cache const &)=default
void flush()
Empty the cache.
void add(Key const &key, Value const &value)
Add a value to the cache.
Forward declarations for lsst::utils::Cache.
std::size_t capacity() const
Return the capacity of the cache.
std::size_t size() const
Return the number of values in the cache.
bool contains(Key const &key)
Does the cache contain the key?
#define LSST_EXCEPT(type,...)
Cache of most recently used values.
Value operator()(Key const &key, Generator func)
Lookup or generate a value.
Cache(std::size_t maxElements=0)
Ctor.
std::vector< Key > keys() const
Return all keys in the cache, most recent first.