2015-04-15 20:39:58 +02:00
|
|
|
#pragma once
|
|
|
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_MAP_H_
|
|
|
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_CACHING2_MAP_H_
|
|
|
|
|
|
|
|
#include <memory>
|
2015-04-17 12:56:21 +02:00
|
|
|
#include <unordered_map>
|
2015-04-16 14:10:44 +02:00
|
|
|
#include <cassert>
|
2015-04-15 20:39:58 +02:00
|
|
|
|
|
|
|
namespace blockstore {
|
2015-04-16 14:10:44 +02:00
|
|
|
namespace caching {
|
2015-04-15 20:39:58 +02:00
|
|
|
|
|
|
|
//TODO Test
|
2015-04-15 21:46:15 +02:00
|
|
|
//TODO Move to utils
|
2015-04-15 20:39:58 +02:00
|
|
|
template<class Key, class Value>
|
|
|
|
class QueueMap {
|
|
|
|
public:
|
2015-04-17 12:59:40 +02:00
|
|
|
QueueMap(): _entries(), _sentinel(nullptr, nullptr, &_sentinel, &_sentinel) {
|
2015-04-15 20:39:58 +02:00
|
|
|
}
|
|
|
|
virtual ~QueueMap() {}
|
|
|
|
|
|
|
|
void push(const Key &key, std::unique_ptr<Value> value) {
|
2015-04-17 12:59:40 +02:00
|
|
|
auto newEntry = std::make_unique<Entry>(&key, std::move(value), _sentinel.prev, &_sentinel);
|
2015-04-15 20:39:58 +02:00
|
|
|
_sentinel.prev->next = newEntry.get();
|
|
|
|
_sentinel.prev = newEntry.get();
|
|
|
|
auto insertResult = _entries.emplace(key, std::move(newEntry));
|
|
|
|
assert(insertResult.second == true);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> pop(const Key &key) {
|
|
|
|
auto found = _entries.find(key);
|
|
|
|
if (found == _entries.end()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
_removeFromQueue(found->second.get());
|
|
|
|
auto value = std::move(found->second->value);
|
|
|
|
_entries.erase(found);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Value> pop() {
|
2015-04-17 12:59:40 +02:00
|
|
|
return pop(*_sentinel.next->key);
|
2015-04-15 20:39:58 +02:00
|
|
|
}
|
|
|
|
|
2015-04-18 16:50:19 +02:00
|
|
|
const Value &peek() {
|
|
|
|
return *_sentinel.next->value;
|
|
|
|
}
|
|
|
|
|
2015-04-15 20:39:58 +02:00
|
|
|
uint32_t size() {
|
|
|
|
return _entries.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct Entry {
|
2015-04-17 12:59:40 +02:00
|
|
|
Entry(const Key *key_, std::unique_ptr<Value> value_, Entry *prev_, Entry *next_): key(nullptr), value(std::move(value_)), prev(prev_), next(next_) {
|
|
|
|
if (key_ != nullptr) {
|
|
|
|
key = std::make_unique<Key>(*key_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::unique_ptr<Key> key;
|
2015-04-15 20:39:58 +02:00
|
|
|
std::unique_ptr<Value> value;
|
|
|
|
Entry *prev;
|
|
|
|
Entry *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
void _removeFromQueue(Entry *entry) {
|
|
|
|
entry->prev->next = entry->next;
|
|
|
|
entry->next->prev = entry->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO Double indirection unique_ptr<Entry> and Entry has unique_ptr<Value>. Necessary?
|
2015-04-17 12:56:21 +02:00
|
|
|
std::unordered_map<Key, std::unique_ptr<Entry>> _entries;
|
2015-04-15 20:39:58 +02:00
|
|
|
Entry _sentinel;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|