Make rtengine::Cache build again with hashable keys

While STL containers are not guaranteed to build with incomplete types,
`rtengine::Cache` used to build with `std::map` as well as
`std::unordered_map` when I first implemented it. With GCC 6.3 I
recently realized, that this was no longer the case for hashable keys
(i.e. `std::unordered_map` as `Store`).

The recommended workaround is to use a `std::unique_ptr`.
This commit is contained in:
Flössie
2017-03-11 17:14:11 +01:00
parent 2b3279c3d7
commit ebd9e5e132

View File

@@ -19,11 +19,12 @@
#pragma once #pragma once
#include <map>
#include <unordered_map>
#include <list>
#include <type_traits>
#include <algorithm> #include <algorithm>
#include <list>
#include <map>
#include <memory>
#include <type_traits>
#include <unordered_map>
#include "../rtgui/threadutils.h" #include "../rtgui/threadutils.h"
@@ -87,9 +88,9 @@ public:
lru_list.splice( lru_list.splice(
lru_list.begin(), lru_list.begin(),
lru_list, lru_list,
store_it->second.lru_list_it store_it->second->lru_list_it
); );
value = store_it->second.value; value = store_it->second->value;
} }
mutex.unlock(); mutex.unlock();
@@ -139,7 +140,7 @@ public:
mutex.lock(); mutex.lock();
if (hook) { if (hook) {
for (const auto& entry : store) { for (const auto& entry : store) {
hook->onRemove(entry.first, entry.second.value); hook->onRemove(entry.first, entry.second->value);
} }
} }
lru_list.clear(); lru_list.clear();
@@ -152,13 +153,13 @@ private:
using Store = typename std::conditional< using Store = typename std::conditional<
cache_helper::has_hash<K>::value, cache_helper::has_hash<K>::value,
std::unordered_map<K, Value>, std::unordered_map<K, std::unique_ptr<Value>>,
std::map<K, Value> std::map<K, std::unique_ptr<Value>>
>::type; >::type;
using StoreIterator = typename Store::iterator; using StoreIterator = typename Store::iterator;
using StoreConstIterator = typename Store::const_iterator; using StoreConstIterator = typename Store::const_iterator;
typedef std::list<StoreIterator> LruList; using LruList = std::list<StoreIterator>;
using LruListIterator = typename LruList::iterator; using LruListIterator = typename LruList::iterator;
struct Value { struct Value {
@@ -176,7 +177,7 @@ private:
{ {
const StoreIterator store_it = lru_list.back(); const StoreIterator store_it = lru_list.back();
if (hook) { if (hook) {
hook->onDiscard(store_it->first, store_it->second.value); hook->onDiscard(store_it->first, store_it->second->value);
} }
store.erase(store_it); store.erase(store_it);
lru_list.pop_back(); lru_list.pop_back();
@@ -193,23 +194,25 @@ private:
discard(); discard();
} }
lru_list.push_front(store.end()); lru_list.push_front(store.end());
const Value v = { std::unique_ptr<Value> v(
value, new Value{
lru_list.begin() value,
}; lru_list.begin()
lru_list.front() = store.emplace(key, v).first; }
);
lru_list.front() = store.emplace(key, std::move(v)).first;
} }
} else { } else {
if (mode == Mode::UNCOND || mode == Mode::KNOWN) { if (mode == Mode::UNCOND || mode == Mode::KNOWN) {
if (hook) { if (hook) {
hook->onDisplace(key, store_it->second.value); hook->onDisplace(key, store_it->second->value);
} }
lru_list.splice( lru_list.splice(
lru_list.begin(), lru_list.begin(),
lru_list, lru_list,
store_it->second.lru_list_it store_it->second->lru_list_it
); );
store_it->second.value = value; store_it->second->value = value;
} }
} }
mutex.unlock(); mutex.unlock();
@@ -220,9 +223,9 @@ private:
void remove(const StoreIterator& store_it) void remove(const StoreIterator& store_it)
{ {
if (hook) { if (hook) {
hook->onRemove(store_it->first, store_it->second.value); hook->onRemove(store_it->first, store_it->second->value);
} }
lru_list.erase(store_it->second.lru_list_it); lru_list.erase(store_it->second->lru_list_it);
store.erase(store_it); store.erase(store_it);
} }