Dependencies: Add lru-cache library
Adds a generic C++ based caching library to support material external modules. This is a template based library which means there is nothing to build or link. The only modification is to the CMakeLists.txt file to enable integration with FreeCAD, Original source: https://github.com/goldsborough/lru-cache
This commit is contained in:
committed by
Chris Hennes
parent
393ab112e5
commit
09f71cb40d
40
src/3rdParty/lru-cache/include/lru/cache-tags.hpp
vendored
Normal file
40
src/3rdParty/lru-cache/include/lru/cache-tags.hpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_CACHE_TAGS_HPP
|
||||
#define LRU_CACHE_TAGS_HPP
|
||||
|
||||
namespace LRU {
|
||||
namespace Tag {
|
||||
struct BasicCache {};
|
||||
struct TimedCache {};
|
||||
} // namespace Tag
|
||||
|
||||
namespace Lowercase {
|
||||
namespace tag {
|
||||
using basic_cache = ::LRU::Tag::BasicCache;
|
||||
using timed_cache = ::LRU::Tag::TimedCache;
|
||||
} // namespace tag
|
||||
} // namespace Lowercase
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_CACHE_TAGS_HPP
|
||||
207
src/3rdParty/lru-cache/include/lru/cache.hpp
vendored
Normal file
207
src/3rdParty/lru-cache/include/lru/cache.hpp
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_CACHE_HPP
|
||||
#define LRU_CACHE_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <lru/cache-tags.hpp>
|
||||
#include <lru/error.hpp>
|
||||
#include <lru/internal/base-cache.hpp>
|
||||
#include <lru/internal/information.hpp>
|
||||
#include <lru/internal/last-accessed.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
template <typename Key,
|
||||
typename Value,
|
||||
typename HashFunction,
|
||||
typename KeyEqual>
|
||||
using UntimedCacheBase = Internal::BaseCache<Key,
|
||||
Value,
|
||||
Internal::Information,
|
||||
HashFunction,
|
||||
KeyEqual,
|
||||
Tag::BasicCache>;
|
||||
} // namespace Internal
|
||||
|
||||
/// A basic LRU cache implementation.
|
||||
///
|
||||
/// An LRU cache is a fixed-size cache that remembers the order in which
|
||||
/// elements were inserted into it. When the size of the cache exceeds its
|
||||
/// capacity, the "least-recently-used" (LRU) element is erased. In our
|
||||
/// implementation, usage is defined as insertion, but not lookup. That is,
|
||||
/// looking up an element does not move it to the "front" of the cache (making
|
||||
/// the operation faster). Only insertions (and erasures) can change the order
|
||||
/// of elements. The capacity of the cache can be modified at any time.
|
||||
///
|
||||
/// \see LRU::TimedCache
|
||||
template <typename Key,
|
||||
typename Value,
|
||||
typename HashFunction = std::hash<Key>,
|
||||
typename KeyEqual = std::equal_to<Key>>
|
||||
class Cache
|
||||
: public Internal::UntimedCacheBase<Key, Value, HashFunction, KeyEqual> {
|
||||
private:
|
||||
using super = Internal::UntimedCacheBase<Key, Value, HashFunction, KeyEqual>;
|
||||
using PRIVATE_BASE_CACHE_MEMBERS;
|
||||
|
||||
public:
|
||||
using PUBLIC_BASE_CACHE_MEMBERS;
|
||||
using typename super::size_t;
|
||||
|
||||
/// \copydoc BaseCache::BaseCache(size_t,const HashFunction&,const KeyEqual&)
|
||||
/// \detailss The capacity defaults to an internal constant, currently 128.
|
||||
explicit Cache(size_t capacity = Internal::DEFAULT_CAPACITY,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(capacity, hash, equal) {
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache(size_t,Iterator,Iterator,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename Iterator>
|
||||
Cache(size_t capacity,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(capacity, begin, end, hash, equal) {
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache(Iterator,Iterator,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename Iterator>
|
||||
Cache(Iterator begin,
|
||||
Iterator end,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(begin, end, hash, equal) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param capacity The capacity of the cache.
|
||||
/// \param range A range to construct the cache with.
|
||||
/// \param hash The hash function to use for the internal map.
|
||||
/// \param key_equal The key equality function to use for the internal map.
|
||||
template <typename Range, typename = Internal::enable_if_range<Range>>
|
||||
Cache(size_t capacity,
|
||||
Range&& range,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(capacity, std::forward<Range>(range), hash, equal) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param range A range to construct the cache with.
|
||||
/// \param hash The hash function to use for the internal map.
|
||||
/// \param key_equal The key equality function to use for the internal map.
|
||||
template <typename Range, typename = Internal::enable_if_range<Range>>
|
||||
explicit Cache(Range&& range,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(std::forward<Range>(range), hash, equal) {
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache(InitializerList,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
Cache(InitializerList list,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual()) // NOLINT(runtime/explicit)
|
||||
: super(list, hash, equal) {
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache(size_t,InitializerList,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
Cache(size_t capacity,
|
||||
InitializerList list,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual()) // NOLINT(runtime/explicit)
|
||||
: super(capacity, list, hash, equal) {
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::find(const Key&)
|
||||
UnorderedIterator find(const Key& key) override {
|
||||
auto iterator = _map.find(key);
|
||||
if (iterator != _map.end()) {
|
||||
_register_hit(key, iterator->second.value);
|
||||
_move_to_front(iterator->second.order);
|
||||
_last_accessed = iterator;
|
||||
} else {
|
||||
_register_miss(key);
|
||||
}
|
||||
|
||||
return {*this, iterator};
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::find(const Key&) const
|
||||
UnorderedConstIterator find(const Key& key) const override {
|
||||
auto iterator = _map.find(key);
|
||||
if (iterator != _map.end()) {
|
||||
_register_hit(key, iterator->second.value);
|
||||
_move_to_front(iterator->second.order);
|
||||
_last_accessed = iterator;
|
||||
} else {
|
||||
_register_miss(key);
|
||||
}
|
||||
|
||||
return {*this, iterator};
|
||||
}
|
||||
|
||||
/// \returns The most-recently inserted element.
|
||||
const Key& front() const noexcept {
|
||||
if (is_empty()) {
|
||||
throw LRU::Error::EmptyCache("front");
|
||||
} else {
|
||||
// The queue is reversed for natural order of iteration.
|
||||
return _order.back();
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns The least-recently inserted element.
|
||||
const Key& back() const noexcept {
|
||||
if (is_empty()) {
|
||||
throw LRU::Error::EmptyCache("back");
|
||||
} else {
|
||||
// The queue is reversed for natural order of iteration.
|
||||
return _order.front();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace Lowercase {
|
||||
template <typename... Ts>
|
||||
using cache = Cache<Ts...>;
|
||||
} // namespace Lowercase
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_CACHE_HPP
|
||||
134
src/3rdParty/lru-cache/include/lru/entry.hpp
vendored
Normal file
134
src/3rdParty/lru-cache/include/lru/entry.hpp
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_PAIR_HPP
|
||||
#define LRU_PAIR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace LRU {
|
||||
|
||||
/// A entry of references to the key and value of an entry in a cache.
|
||||
///
|
||||
/// Instances of this class are usually the result of dereferencing an iterator.
|
||||
///
|
||||
/// \tparam Key The key type of the pair.
|
||||
/// \tparam Value The value type of the pair.
|
||||
template <typename Key, typename Value>
|
||||
struct Entry final {
|
||||
using KeyType = Key;
|
||||
using ValueType = Value;
|
||||
using first_type = Key;
|
||||
using second_type = Value;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param key The key of the entry.
|
||||
/// \param value The value of the entry.
|
||||
Entry(const Key& key, Value& value) : first(key), second(value) {
|
||||
}
|
||||
|
||||
/// Generalized copy constructor.
|
||||
///
|
||||
/// Mainly for conversion from non-const values to const values.
|
||||
///
|
||||
/// \param other The entry to construct from.
|
||||
template <typename AnyKey,
|
||||
typename AnyValue,
|
||||
typename =
|
||||
std::enable_if_t<(std::is_convertible<AnyKey, Key>::value &&
|
||||
std::is_convertible<AnyValue, Value>::value)>>
|
||||
Entry(const Entry<AnyKey, AnyValue>& other)
|
||||
: first(other.first), second(other.second) {
|
||||
}
|
||||
|
||||
/// Compares two entrys for equality.
|
||||
///
|
||||
/// \param first The first entry to compare.
|
||||
/// \param second The second entry to compare.
|
||||
/// \returns True if the firest entry equals the second, else false.
|
||||
template <typename Pair, typename = typename Pair::first_type>
|
||||
friend bool operator==(const Entry& first, const Pair& second) noexcept {
|
||||
return first.first == second.first && first.second == second.second;
|
||||
}
|
||||
|
||||
/// Compares two entrys for equality.
|
||||
///
|
||||
/// \param first The first entry to compare.
|
||||
/// \param second The second entry to compare.
|
||||
/// \returns True if the first entry equals the second, else false.
|
||||
template <typename Pair, typename = typename Pair::first_type>
|
||||
friend bool operator==(const Pair& first, const Entry& second) noexcept {
|
||||
return second == first;
|
||||
}
|
||||
|
||||
/// Compares two entrys for inequality.
|
||||
///
|
||||
/// \param first The first entry to compare.
|
||||
/// \param second The second entry to compare.
|
||||
/// \returns True if the first entry does not equal the second, else false.
|
||||
template <typename Pair, typename = typename Pair::first_type>
|
||||
friend bool operator!=(const Entry& first, const Pair& second) noexcept {
|
||||
return !(first == second);
|
||||
}
|
||||
|
||||
/// Compares two entrys for inequality.
|
||||
///
|
||||
/// \param first The first entry to compare.
|
||||
/// \param second The second entry to compare.fdas
|
||||
/// \returns True if the first entry does not equal the second, else false.
|
||||
template <typename Pair, typename = typename Pair::first_type>
|
||||
friend bool operator!=(const Pair& first, const Entry& second) noexcept {
|
||||
return second != first;
|
||||
}
|
||||
|
||||
/// \returns A `std::pair` instance with the key and value of this entry.
|
||||
operator std::pair<const Key&, Value&>() noexcept {
|
||||
return {first, second};
|
||||
}
|
||||
|
||||
/// \returns The key of the entry (`first`).
|
||||
const Key& key() const noexcept {
|
||||
return first;
|
||||
}
|
||||
|
||||
/// \returns The value of the entry (`second`).
|
||||
Value& value() noexcept {
|
||||
return second;
|
||||
}
|
||||
|
||||
/// \returns The value of the entry (`second`).
|
||||
const Value& value() const noexcept {
|
||||
return second;
|
||||
}
|
||||
|
||||
/// The key of the entry.
|
||||
const Key& first;
|
||||
|
||||
/// The value of the entry.
|
||||
Value& second;
|
||||
};
|
||||
} // namespace LRU
|
||||
|
||||
|
||||
#endif // LRU_PAIR_HPP
|
||||
107
src/3rdParty/lru-cache/include/lru/error.hpp
vendored
Normal file
107
src/3rdParty/lru-cache/include/lru/error.hpp
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_ERRORS_HPP
|
||||
#define LRU_INTERNAL_ERRORS_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace LRU {
|
||||
namespace Error {
|
||||
|
||||
/// Exception thrown when the value of an invalid key was requested.
|
||||
struct KeyNotFound : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
|
||||
KeyNotFound() : super("Failed to find key") {
|
||||
}
|
||||
|
||||
explicit KeyNotFound(const std::string& key)
|
||||
: super("Failed to find key: " + key) {
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception thrown when the value of an expired key was requested.
|
||||
struct KeyExpired : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
|
||||
explicit KeyExpired(const std::string& key)
|
||||
: super("Key found, but expired: " + key) {
|
||||
}
|
||||
|
||||
KeyExpired() : super("Key found, but expired") {
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception thrown when requesting the front or end key of an empty cache.
|
||||
struct EmptyCache : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
explicit EmptyCache(const std::string& what_was_expected)
|
||||
: super("Requested " + what_was_expected + " of empty cache") {
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception thrown when attempting to convert an invalid unordered iterator to
|
||||
/// an ordered iterator.
|
||||
struct InvalidIteratorConversion : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
InvalidIteratorConversion()
|
||||
: super("Cannot convert past-the-end unordered to ordered iterator") {
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception thrown when attempting to erase the past-the-end iterator.
|
||||
struct InvalidIterator : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
InvalidIterator() : super("Past-the-end iterator is invalid here") {
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception thrown when requesting statistics about an unmonitored key.
|
||||
struct UnmonitoredKey : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
UnmonitoredKey() : super("Requested statistics for unmonitored key") {
|
||||
}
|
||||
};
|
||||
|
||||
/// Exception thrown when requesting the statistics object of a cache when none
|
||||
/// was registered.
|
||||
struct NotMonitoring : public std::runtime_error {
|
||||
using super = std::runtime_error;
|
||||
NotMonitoring() : super("Statistics monitoring not enabled for this cache") {
|
||||
}
|
||||
};
|
||||
|
||||
namespace Lowercase {
|
||||
using key_not_found = KeyNotFound;
|
||||
using key_expired = KeyExpired;
|
||||
using empty_cache = EmptyCache;
|
||||
using invalid_iterator_conversion = InvalidIteratorConversion;
|
||||
using invalid_iterator = InvalidIterator;
|
||||
using unmonitored_key = UnmonitoredKey;
|
||||
using not_monitoring = NotMonitoring;
|
||||
} // namespace Lowercase
|
||||
|
||||
} // namespace Error
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_INTERNAL_ERRORS_HPP
|
||||
76
src/3rdParty/lru-cache/include/lru/insertion-result.hpp
vendored
Normal file
76
src/3rdParty/lru-cache/include/lru/insertion-result.hpp
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INSERTION_RESULT_HPP
|
||||
#define LRU_INSERTION_RESULT_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace LRU {
|
||||
|
||||
/// The result of an insertion into a cache.
|
||||
///
|
||||
/// This is a semantically nicer alternative to a generic `std::pair`, as is
|
||||
/// returned by `std::unordered_map` or so. It still has the same static
|
||||
/// interface as the `std::pair` (with `first` and `second` members), but adds
|
||||
/// nicer `was_inserted()` and `iterator()` accessors.
|
||||
///
|
||||
/// \tparam Iterator The class of the iterator contained in the result.
|
||||
template <typename Iterator>
|
||||
struct InsertionResult final {
|
||||
using IteratorType = Iterator;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param result Whether the result was successful.
|
||||
/// \param iterator The iterator pointing to the inserted or updated key.
|
||||
InsertionResult(bool result, Iterator iterator)
|
||||
: first(result), second(iterator) {
|
||||
}
|
||||
|
||||
/// \returns True if the key was newly inserted, false if it was only updated.
|
||||
bool was_inserted() const noexcept {
|
||||
return first;
|
||||
}
|
||||
|
||||
/// \returns The iterator pointing to the inserted or updated key.
|
||||
Iterator iterator() const noexcept {
|
||||
return second;
|
||||
}
|
||||
|
||||
/// \copydoc was_inserted
|
||||
explicit operator bool() const noexcept {
|
||||
return was_inserted();
|
||||
}
|
||||
|
||||
/// Whether the result was successful.
|
||||
bool first;
|
||||
|
||||
/// The iterator pointing to the inserted or updated key.
|
||||
Iterator second;
|
||||
};
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
|
||||
#endif // LRU_INSERTION_RESULT_HPP
|
||||
1588
src/3rdParty/lru-cache/include/lru/internal/base-cache.hpp
vendored
Normal file
1588
src/3rdParty/lru-cache/include/lru/internal/base-cache.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
216
src/3rdParty/lru-cache/include/lru/internal/base-iterator.hpp
vendored
Normal file
216
src/3rdParty/lru-cache/include/lru/internal/base-iterator.hpp
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_BASE_ITERATOR_HPP
|
||||
#define LRU_INTERNAL_BASE_ITERATOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <lru/entry.hpp>
|
||||
#include <lru/internal/optional.hpp>
|
||||
|
||||
#define PUBLIC_BASE_ITERATOR_MEMBERS \
|
||||
typename super::Entry; \
|
||||
using typename super::KeyType; \
|
||||
using typename super::ValueType;
|
||||
|
||||
#define PRIVATE_BASE_ITERATOR_MEMBERS \
|
||||
super::_iterator; \
|
||||
using super::_entry; \
|
||||
using super::_cache;
|
||||
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// The base class for all (ordered and unordered) iterators.
|
||||
///
|
||||
/// All iterators over our LRU caches store a reference to the cache they point
|
||||
/// into, an underlying iterator they adapt (e.g. a map iterator or list
|
||||
/// iterator) as well as a entry, a reference to which is returned when
|
||||
/// dereferencing the iterator.
|
||||
///
|
||||
/// \tparam IteratorTag A standard iterator category tag.
|
||||
/// \tparam Key The key type over which instances of the iterator iterate.
|
||||
/// \tparam Value The value type over which instances of the iterator iterate.
|
||||
/// \tparam Cache The type of the cache instances of the iterator point into.
|
||||
/// \tparam UnderlyingIterator The underlying iterator class used to implement
|
||||
/// the iterator.
|
||||
template <typename IteratorTag,
|
||||
typename Key,
|
||||
typename Value,
|
||||
typename Cache,
|
||||
typename UnderlyingIterator>
|
||||
class BaseIterator : public std::iterator<IteratorTag, LRU::Entry<Key, Value>> {
|
||||
public:
|
||||
using KeyType = Key;
|
||||
using ValueType =
|
||||
std::conditional_t<std::is_const<Cache>::value, const Value, Value>;
|
||||
using Entry = LRU::Entry<KeyType, ValueType>;
|
||||
|
||||
/// Default constructor.
|
||||
BaseIterator() noexcept : _cache(nullptr) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param cache The cache this iterator points into.
|
||||
/// \param iterator The underlying iterator to adapt.
|
||||
BaseIterator(Cache& cache, const UnderlyingIterator& iterator) noexcept
|
||||
: _iterator(iterator), _cache(&cache) {
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
///
|
||||
/// Differs from the default copy constructor in that it does not copy the
|
||||
/// entry.
|
||||
///
|
||||
/// \param other The base iterator to copy.
|
||||
BaseIterator(const BaseIterator& other) noexcept
|
||||
: _iterator(other._iterator), _cache(other._cache) {
|
||||
// Note: we do not copy the entry, as it would require a new allocation.
|
||||
// Since iterators are often taken by value, this may incur a high cost.
|
||||
// As such we delay the retrieval of the entry to the first call to entry().
|
||||
}
|
||||
|
||||
/// Copy assignment operator.
|
||||
///
|
||||
/// Differs from the default copy assignment
|
||||
/// operator in that it does not copy the entry.
|
||||
///
|
||||
/// \param other The base iterator to copy.
|
||||
/// \return The base iterator instance.
|
||||
BaseIterator& operator=(const BaseIterator& other) noexcept {
|
||||
if (this != &other) {
|
||||
_iterator = other._iterator;
|
||||
_cache = other._cache;
|
||||
_entry.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move constructor.
|
||||
BaseIterator(BaseIterator&& other) noexcept = default;
|
||||
|
||||
/// Move assignment operator.
|
||||
BaseIterator& operator=(BaseIterator&& other) noexcept = default;
|
||||
|
||||
/// Generalized copy constructor.
|
||||
///
|
||||
/// Mainly necessary for non-const to const conversion.
|
||||
///
|
||||
/// \param other The base iterator to copy from.
|
||||
template <typename AnyIteratorTag,
|
||||
typename AnyKeyType,
|
||||
typename AnyValueType,
|
||||
typename AnyCacheType,
|
||||
typename AnyUnderlyingIteratorType>
|
||||
BaseIterator(const BaseIterator<AnyIteratorTag,
|
||||
AnyKeyType,
|
||||
AnyValueType,
|
||||
AnyCacheType,
|
||||
AnyUnderlyingIteratorType>& other)
|
||||
: _iterator(other._iterator), _entry(other._entry), _cache(other._cache) {
|
||||
}
|
||||
|
||||
/// Generalized move constructor.
|
||||
///
|
||||
/// Mainly necessary for non-const to const conversion.
|
||||
///
|
||||
/// \param other The base iterator to move into this one.
|
||||
template <typename AnyIteratorTag,
|
||||
typename AnyKeyType,
|
||||
typename AnyValueType,
|
||||
typename AnyCacheType,
|
||||
typename AnyUnderlyingIteratorType>
|
||||
BaseIterator(BaseIterator<AnyIteratorTag,
|
||||
AnyKeyType,
|
||||
AnyValueType,
|
||||
AnyCacheType,
|
||||
AnyUnderlyingIteratorType>&& other) noexcept
|
||||
: _iterator(std::move(other._iterator))
|
||||
, _entry(std::move(other._entry))
|
||||
, _cache(std::move(other._cache)) {
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~BaseIterator() = default;
|
||||
|
||||
/// Swaps this base iterator with another one.
|
||||
///
|
||||
/// \param other The other iterator to swap with.
|
||||
void swap(BaseIterator& other) noexcept {
|
||||
// Enable ADL
|
||||
using std::swap;
|
||||
|
||||
swap(_iterator, other._iterator);
|
||||
swap(_entry, other._entry);
|
||||
swap(_cache, other._cache);
|
||||
}
|
||||
|
||||
/// Swaps two base iterator.
|
||||
///
|
||||
/// \param first The first iterator to swap.
|
||||
/// \param second The second iterator to swap.
|
||||
friend void swap(BaseIterator& first, BaseIterator& second) noexcept {
|
||||
first.swap(second);
|
||||
}
|
||||
|
||||
/// \returns A reference to the current entry pointed to by the iterator.
|
||||
virtual Entry& operator*() noexcept = 0;
|
||||
|
||||
/// \returns A pointer to the current entry pointed to by the iterator.
|
||||
Entry* operator->() noexcept {
|
||||
return &(**this);
|
||||
}
|
||||
|
||||
/// \copydoc operator*()
|
||||
virtual Entry& entry() = 0;
|
||||
|
||||
/// \returns A reference to the value of the entry currently pointed to by the
|
||||
/// iterator.
|
||||
virtual ValueType& value() = 0;
|
||||
|
||||
/// \returns A reference to the key of the entry currently pointed to by the
|
||||
/// iterator.
|
||||
virtual const Key& key() = 0;
|
||||
|
||||
protected:
|
||||
template <typename, typename, typename, typename, typename>
|
||||
friend class BaseIterator;
|
||||
|
||||
/// The underlying iterator this iterator class adapts.
|
||||
UnderlyingIterator _iterator;
|
||||
|
||||
/// The entry optionally being stored.
|
||||
Optional<Entry> _entry;
|
||||
|
||||
/// A pointer to the cache this iterator points into.
|
||||
/// Pointer and not reference because it's cheap to copy.
|
||||
/// Pointer and not `std::reference_wrapper` because the class needs to be
|
||||
/// default-constructible.
|
||||
Cache* _cache;
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_INTERNAL_BASE_ITERATOR_HPP
|
||||
338
src/3rdParty/lru-cache/include/lru/internal/base-ordered-iterator.hpp
vendored
Normal file
338
src/3rdParty/lru-cache/include/lru/internal/base-ordered-iterator.hpp
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef BASE_ORDERED_ITERATOR_HPP
|
||||
#define BASE_ORDERED_ITERATOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <lru/entry.hpp>
|
||||
#include <lru/error.hpp>
|
||||
#include <lru/internal/base-iterator.hpp>
|
||||
#include <lru/internal/base-unordered-iterator.hpp>
|
||||
#include <lru/internal/definitions.hpp>
|
||||
#include <lru/internal/optional.hpp>
|
||||
#include <lru/iterator-tags.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
template <typename Key, typename Value, typename Cache>
|
||||
using BaseForBaseOrderedIterator =
|
||||
BaseIterator<std::bidirectional_iterator_tag,
|
||||
Key,
|
||||
Value,
|
||||
Cache,
|
||||
typename Queue<Key>::const_iterator>;
|
||||
|
||||
/// The base class for all const and non-const ordered iterators.
|
||||
///
|
||||
/// Ordered iterators are bidirectional iterators that iterate over the keys of
|
||||
/// a cache in the order in which they were inserted into the cache. As they
|
||||
/// only iterate over the keys, they must perform hash lookups to retrieve the
|
||||
/// value the first time they are dereferenced. This makes them slightly less
|
||||
/// efficient than unordered iterators. However, they also have the additional
|
||||
/// property that they may be constructed from unordered iterators, and that
|
||||
/// they can be decremented.
|
||||
///
|
||||
/// \tparam Key The key type over which instances of the iterator iterate.
|
||||
/// \tparam Value The value type over which instances of the iterator iterate.
|
||||
/// \tparam Cache The type of the cache instances of the iterator point into.
|
||||
template <typename Key, typename Value, typename Cache>
|
||||
class BaseOrderedIterator
|
||||
: public BaseForBaseOrderedIterator<Key, Value, Cache> {
|
||||
protected:
|
||||
using super = BaseForBaseOrderedIterator<Key, Value, Cache>;
|
||||
using PRIVATE_BASE_ITERATOR_MEMBERS;
|
||||
using UnderlyingIterator = typename Queue<Key>::const_iterator;
|
||||
|
||||
public:
|
||||
using Tag = LRU::Tag::OrderedIterator;
|
||||
using PUBLIC_BASE_ITERATOR_MEMBERS;
|
||||
|
||||
/// Constructor.
|
||||
BaseOrderedIterator() noexcept = default;
|
||||
|
||||
/// \copydoc BaseIterator::BaseIterator(Cache,UnderlyingIterator)
|
||||
BaseOrderedIterator(Cache& cache, UnderlyingIterator iterator)
|
||||
: super(cache, iterator) {
|
||||
}
|
||||
|
||||
/// Generalized copy constructor.
|
||||
///
|
||||
/// \param other The ordered iterator to contruct from.
|
||||
template <typename AnyKey, typename AnyValue, typename AnyCache>
|
||||
BaseOrderedIterator(
|
||||
const BaseOrderedIterator<AnyKey, AnyValue, AnyCache>& other)
|
||||
: super(other) {
|
||||
}
|
||||
|
||||
/// Generalized move constructor.
|
||||
///
|
||||
/// \param other The ordered iterator to move into this one.
|
||||
template <typename AnyKey, typename AnyValue, typename AnyCache>
|
||||
BaseOrderedIterator(BaseOrderedIterator<AnyKey, AnyValue, AnyCache>&& other)
|
||||
: super(std::move(other)) {
|
||||
}
|
||||
|
||||
/// Generalized conversion copy constructor.
|
||||
///
|
||||
/// \param unordered_iterator The unordered iterator to construct from.
|
||||
template <
|
||||
typename AnyCache,
|
||||
typename UnderlyingIterator,
|
||||
typename = std::enable_if_t<
|
||||
std::is_same<std::decay_t<AnyCache>, std::decay_t<Cache>>::value>>
|
||||
BaseOrderedIterator(const BaseUnorderedIterator<AnyCache, UnderlyingIterator>&
|
||||
unordered_iterator) {
|
||||
// Atomicity
|
||||
_throw_if_at_invalid(unordered_iterator);
|
||||
_cache = unordered_iterator._cache;
|
||||
_iterator = unordered_iterator._iterator->second.order;
|
||||
}
|
||||
|
||||
/// Generalized conversion move constructor.
|
||||
///
|
||||
/// \param unordered_iterator The unordered iterator to move-construct from.
|
||||
template <
|
||||
typename AnyCache,
|
||||
typename UnderlyingIterator,
|
||||
typename = std::enable_if_t<
|
||||
std::is_same<std::decay_t<AnyCache>, std::decay_t<Cache>>::value>>
|
||||
BaseOrderedIterator(BaseUnorderedIterator<AnyCache, UnderlyingIterator>&&
|
||||
unordered_iterator) {
|
||||
// Atomicity
|
||||
_throw_if_at_invalid(unordered_iterator);
|
||||
_cache = std::move(unordered_iterator._cache);
|
||||
_entry = std::move(unordered_iterator._entry);
|
||||
_iterator = std::move(unordered_iterator._iterator->second.order);
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
BaseOrderedIterator(const BaseOrderedIterator& other) = default;
|
||||
|
||||
/// Move constructor.
|
||||
BaseOrderedIterator(BaseOrderedIterator&& other) = default;
|
||||
|
||||
/// Copy assignment operator.
|
||||
BaseOrderedIterator& operator=(const BaseOrderedIterator& other) = default;
|
||||
|
||||
/// Move assignment operator.
|
||||
BaseOrderedIterator& operator=(BaseOrderedIterator&& other) = default;
|
||||
|
||||
/// Destructor.
|
||||
virtual ~BaseOrderedIterator() = default;
|
||||
|
||||
/// Checks for equality between this iterator and another ordered iterator.
|
||||
///
|
||||
/// \param other The other ordered iterator.
|
||||
/// \returns True if both iterators point to the same entry, else false.
|
||||
bool operator==(const BaseOrderedIterator& other) const noexcept {
|
||||
return this->_iterator == other._iterator;
|
||||
}
|
||||
|
||||
/// Checks for inequality between this iterator another ordered iterator.
|
||||
///
|
||||
/// \param other The other ordered iterator.
|
||||
/// \returns True if the iterators point to different entries, else false.
|
||||
bool operator!=(const BaseOrderedIterator& other) const noexcept {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/// Checks for inequality between this iterator and another unordered
|
||||
/// iterator.
|
||||
///
|
||||
/// \param other The other unordered iterator.
|
||||
/// \returns True if both iterators point to the end of the same cache, else
|
||||
/// the result of comparing with the unordered iterator, converted to an
|
||||
/// ordered iterator.
|
||||
template <typename AnyCache, typename AnyUnderlyingIterator>
|
||||
bool operator==(
|
||||
const BaseUnorderedIterator<AnyCache, AnyUnderlyingIterator>& other) const
|
||||
noexcept {
|
||||
if (this->_cache != other._cache) return false;
|
||||
|
||||
// The past-the-end iterators of the same cache should compare equal.
|
||||
// This is an exceptional guarantee we make. This is also the reason
|
||||
// why we can't rely on the conversion from unordered to ordered iterators
|
||||
// because construction of an ordered iterator from the past-the-end
|
||||
// unordered iterator will fail (with an InvalidIteratorConversion error)
|
||||
if (other == other._cache->unordered_end()) {
|
||||
return *this == this->_cache->ordered_end();
|
||||
}
|
||||
|
||||
// Will call the other overload
|
||||
return *this == static_cast<BaseOrderedIterator>(other);
|
||||
}
|
||||
|
||||
/// Checks for equality between an unordered iterator and an ordered iterator.
|
||||
///
|
||||
/// \param first The unordered iterator.
|
||||
/// \param second The ordered iterator.
|
||||
/// \returns True if both iterators point to the end of the same cache, else
|
||||
/// the result of comparing with the unordered iterator, converted to an
|
||||
/// ordered iterator.
|
||||
template <typename AnyCache, typename AnyUnderlyingIterator>
|
||||
friend bool operator==(
|
||||
const BaseUnorderedIterator<AnyCache, AnyUnderlyingIterator>& first,
|
||||
const BaseOrderedIterator& second) noexcept {
|
||||
return second == first;
|
||||
}
|
||||
|
||||
/// Checks for inequality between an unordered
|
||||
/// iterator and an ordered iterator.
|
||||
///
|
||||
/// \param first The ordered iterator.
|
||||
/// \param second The unordered iterator.
|
||||
/// \returns True if the iterators point to different entries, else false.
|
||||
template <typename AnyCache, typename AnyUnderlyingIterator>
|
||||
friend bool
|
||||
operator!=(const BaseOrderedIterator& first,
|
||||
const BaseUnorderedIterator<AnyCache, AnyUnderlyingIterator>&
|
||||
second) noexcept {
|
||||
return !(first == second);
|
||||
}
|
||||
|
||||
/// Checks for inequality between an unordered
|
||||
/// iterator and an ordered iterator.
|
||||
///
|
||||
/// \param first The unordered iterator.
|
||||
/// \param second The ordered iterator.
|
||||
/// \returns True if the iterators point to different entries, else false.
|
||||
template <typename AnyCache, typename AnyUnderlyingIterator>
|
||||
friend bool operator!=(
|
||||
const BaseUnorderedIterator<AnyCache, AnyUnderlyingIterator>& first,
|
||||
const BaseOrderedIterator& second) noexcept {
|
||||
return second != first;
|
||||
}
|
||||
|
||||
/// Increments the iterator to the next entry.
|
||||
///
|
||||
/// If the iterator already pointed to the end any number of increments
|
||||
/// before, behavior is undefined.
|
||||
///
|
||||
/// \returns The resulting iterator.
|
||||
BaseOrderedIterator& operator++() {
|
||||
++_iterator;
|
||||
_entry.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Increments the iterator and returns a copy of the previous one.
|
||||
///
|
||||
/// If the iterator already pointed to the end any number of increments
|
||||
/// before, behavior is undefined.
|
||||
///
|
||||
/// \returns A copy of the previous iterator.
|
||||
BaseOrderedIterator operator++(int) {
|
||||
auto previous = *this;
|
||||
++*this;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/// Decrements the iterator to the previous entry.
|
||||
///
|
||||
/// \returns The resulting iterator.
|
||||
BaseOrderedIterator& operator--() {
|
||||
--_iterator;
|
||||
_entry.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Decrements the iterator and returns a copy of the previous entry.
|
||||
///
|
||||
/// \returns The previous iterator.
|
||||
BaseOrderedIterator operator--(int) {
|
||||
auto previous = *this;
|
||||
--*this;
|
||||
return previous;
|
||||
}
|
||||
|
||||
Entry& operator*() noexcept override {
|
||||
return _maybe_lookup();
|
||||
}
|
||||
|
||||
/// \returns A reference to the entry the iterator points to.
|
||||
/// \details If the iterator is invalid, behavior is undefined.
|
||||
Entry& entry() override {
|
||||
_cache->throw_if_invalid(*this);
|
||||
return _maybe_lookup();
|
||||
}
|
||||
|
||||
/// \returns A reference to the value the iterator points to.
|
||||
/// \details If the iterator is invalid, behavior is undefined.
|
||||
Value& value() override {
|
||||
return entry().value();
|
||||
}
|
||||
|
||||
/// \returns A reference to the key the iterator points to.
|
||||
/// \details If the iterator is invalid, behavior is undefined.
|
||||
const Key& key() override {
|
||||
// No lookup required
|
||||
_cache->throw_if_invalid(*this);
|
||||
return *_iterator;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename, typename, typename>
|
||||
friend class BaseOrderedIterator;
|
||||
|
||||
/// Looks up the entry for a key if this was not done already.
|
||||
///
|
||||
/// \returns The entry, which was possibly newly looked up.
|
||||
Entry& _maybe_lookup() {
|
||||
if (!_entry.has_value()) {
|
||||
_lookup();
|
||||
}
|
||||
|
||||
return *_entry;
|
||||
}
|
||||
|
||||
/// Looks up the entry for a key and sets the internal entry member.
|
||||
void _lookup() {
|
||||
auto iterator = _cache->_map.find(*_iterator);
|
||||
_entry.emplace(iterator->first, iterator->second.value);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Throws an exception if the given unordered iterator is invalid.
|
||||
///
|
||||
/// \param unordered_iterator The iterator to check.
|
||||
/// \throws LRU::Error::InvalidIteratorConversion if the iterator is invalid.
|
||||
template <typename UnorderedIterator>
|
||||
void _throw_if_at_invalid(const UnorderedIterator& unordered_iterator) {
|
||||
// For atomicity of the copy assignment, we assign the cache pointer only
|
||||
// after this check in the copy/move constructor and use the iterator's
|
||||
// cache. If an exception is thrown, the state of the ordered iterator is
|
||||
// unchanged compared to before the assignment.
|
||||
if (unordered_iterator == unordered_iterator._cache->unordered_end()) {
|
||||
throw LRU::Error::InvalidIteratorConversion();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // BASE_ORDERED_ITERATOR_HPP
|
||||
216
src/3rdParty/lru-cache/include/lru/internal/base-unordered-iterator.hpp
vendored
Normal file
216
src/3rdParty/lru-cache/include/lru/internal/base-unordered-iterator.hpp
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef BASE_UNORDERED_ITERATOR_HPP
|
||||
#define BASE_UNORDERED_ITERATOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <lru/entry.hpp>
|
||||
#include <lru/internal/base-iterator.hpp>
|
||||
#include <lru/internal/definitions.hpp>
|
||||
#include <lru/internal/optional.hpp>
|
||||
#include <lru/iterator-tags.hpp>
|
||||
|
||||
|
||||
namespace LRU {
|
||||
|
||||
// Forward declaration.
|
||||
template <typename, typename, typename, typename, typename>
|
||||
class TimedCache;
|
||||
|
||||
namespace Internal {
|
||||
template <typename Cache, typename UnderlyingIterator>
|
||||
using BaseForBaseUnorderedIterator =
|
||||
BaseIterator<std::forward_iterator_tag,
|
||||
decltype(UnderlyingIterator()->first),
|
||||
decltype(UnderlyingIterator()->second.value),
|
||||
Cache,
|
||||
UnderlyingIterator>;
|
||||
|
||||
/// The base class for all const and non-const unordered iterators.
|
||||
///
|
||||
/// An unordered iterator is a wrapper around an `unordered_map` iterator with
|
||||
/// ForwardIterator category. As such, it is (nearly) as fast to access the pair
|
||||
/// as through the unordered iterator as through the map iterator directly.
|
||||
/// However, the order of keys is unspecified. For this reason, unordered
|
||||
/// iterators have the special property that they may be used to construct
|
||||
/// ordered iterators, after which the order of insertion is respected.
|
||||
///
|
||||
/// \tparam Cache The type of the cache instances of the iterator point into.
|
||||
/// \tparam UnderlyingIterator The underlying iterator class used to implement
|
||||
/// the iterator.
|
||||
template <typename Cache, typename UnderlyingIterator>
|
||||
class BaseUnorderedIterator
|
||||
: public BaseForBaseUnorderedIterator<Cache, UnderlyingIterator> {
|
||||
protected:
|
||||
using super = BaseForBaseUnorderedIterator<Cache, UnderlyingIterator>;
|
||||
using PRIVATE_BASE_ITERATOR_MEMBERS;
|
||||
// These are the key and value types the BaseIterator extracts
|
||||
using Key = typename super::KeyType;
|
||||
using Value = typename super::ValueType;
|
||||
|
||||
public:
|
||||
using Tag = LRU::Tag::UnorderedIterator;
|
||||
using PUBLIC_BASE_ITERATOR_MEMBERS;
|
||||
|
||||
/// Constructor.
|
||||
BaseUnorderedIterator() noexcept = default;
|
||||
|
||||
/// \copydoc BaseIterator::BaseIterator(Cache,UnderlyingIterator)
|
||||
explicit BaseUnorderedIterator(Cache& cache,
|
||||
const UnderlyingIterator& iterator) noexcept
|
||||
: super(cache, iterator) {
|
||||
}
|
||||
|
||||
/// Generalized copy constructor.
|
||||
///
|
||||
/// Useful mainly for non-const to const conversion.
|
||||
///
|
||||
/// \param other The iterator to copy from.
|
||||
template <typename AnyCache, typename AnyUnderlyingIterator>
|
||||
BaseUnorderedIterator(
|
||||
const BaseUnorderedIterator<AnyCache, AnyUnderlyingIterator>&
|
||||
other) noexcept
|
||||
: super(other) {
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
BaseUnorderedIterator(const BaseUnorderedIterator& other) noexcept = default;
|
||||
|
||||
/// Move constructor.
|
||||
BaseUnorderedIterator(BaseUnorderedIterator&& other) noexcept = default;
|
||||
|
||||
/// Copy assignment operator.
|
||||
BaseUnorderedIterator&
|
||||
operator=(const BaseUnorderedIterator& other) noexcept = default;
|
||||
|
||||
/// Move assignment operator.
|
||||
template <typename AnyCache, typename AnyUnderlyingIterator>
|
||||
BaseUnorderedIterator&
|
||||
operator=(BaseUnorderedIterator<AnyCache, AnyUnderlyingIterator>
|
||||
unordered_iterator) noexcept {
|
||||
swap(unordered_iterator);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~BaseUnorderedIterator() = default;
|
||||
|
||||
/// Compares this iterator for equality with another unordered iterator.
|
||||
///
|
||||
/// \param other Another unordered iterator.
|
||||
/// \returns True if both iterators point to the same entry, else false.
|
||||
template <typename AnyCache, typename AnyIterator>
|
||||
bool
|
||||
operator==(const BaseUnorderedIterator<AnyCache, AnyIterator>& other) const
|
||||
noexcept {
|
||||
return this->_iterator == other._iterator;
|
||||
}
|
||||
|
||||
/// Compares this iterator for inequality with another unordered iterator.
|
||||
///
|
||||
/// \param other Another unordered iterator.
|
||||
/// \returns True if the iterators point to different entries, else false.
|
||||
template <typename AnyCache, typename AnyIterator>
|
||||
bool
|
||||
operator!=(const BaseUnorderedIterator<AnyCache, AnyIterator>& other) const
|
||||
noexcept {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/// Increments the iterator to the next entry.
|
||||
///
|
||||
/// If the iterator already pointed to the end any number of increments
|
||||
/// before, behavior is undefined.
|
||||
///
|
||||
/// \returns The resulting iterator.
|
||||
BaseUnorderedIterator& operator++() {
|
||||
++_iterator;
|
||||
_entry.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Increments the iterator and returns a copy of the previous one.
|
||||
///
|
||||
/// If the iterator already pointed to the end any number of increments
|
||||
/// before, behavior is undefined.
|
||||
///
|
||||
/// \returns A copy of the previous iterator.
|
||||
BaseUnorderedIterator operator++(int) {
|
||||
auto previous = *this;
|
||||
++*this;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/// \copydoc BaseIterator::operator*
|
||||
/// \details If the iterator is invalid, behavior is undefined. No exception
|
||||
/// handling is performed.
|
||||
Entry& operator*() noexcept override {
|
||||
if (!_entry.has_value()) {
|
||||
_entry.emplace(_iterator->first, _iterator->second.value);
|
||||
}
|
||||
|
||||
return *_entry;
|
||||
}
|
||||
|
||||
/// \returns A reference to the entry the iterator points to.
|
||||
/// \throws LRU::Error::InvalidIterator if the iterator is the end iterator.
|
||||
/// \throws LRU::Error::KeyExpired if the key pointed to by the iterator has
|
||||
/// expired.
|
||||
Entry& entry() override {
|
||||
if (!_entry.has_value()) {
|
||||
_entry.emplace(_iterator->first, _iterator->second.value);
|
||||
}
|
||||
|
||||
_cache->throw_if_invalid(*this);
|
||||
return *_entry;
|
||||
}
|
||||
|
||||
/// \returns A reference to the key the iterator points to.
|
||||
/// \throws LRU::Error::InvalidIterator if the iterator is the end iterator.
|
||||
/// \throws LRU::Error::KeyExpired if the key pointed to by the iterator has
|
||||
/// expired.
|
||||
const Key& key() override {
|
||||
return entry().key();
|
||||
}
|
||||
|
||||
/// \returns A reference to the value the iterator points to.
|
||||
/// \throws LRU::Error::InvalidIterator if the iterator is the end iterator.
|
||||
/// \throws LRU::Error::KeyExpired if the key pointed to by the iterator has
|
||||
/// expired.
|
||||
Value& value() override {
|
||||
return entry().value();
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename, typename, typename>
|
||||
friend class BaseOrderedIterator;
|
||||
|
||||
template <typename, typename, typename, typename, typename>
|
||||
friend class LRU::TimedCache;
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // BASE_UNORDERED_ITERATOR_HPP
|
||||
159
src/3rdParty/lru-cache/include/lru/internal/callback-manager.hpp
vendored
Normal file
159
src/3rdParty/lru-cache/include/lru/internal/callback-manager.hpp
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_CALLBACK_MANAGER_HPP
|
||||
#define LRU_INTERNAL_CALLBACK_MANAGER_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <lru/entry.hpp>
|
||||
#include <lru/internal/optional.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// Manages hit, miss and access callbacks for a cache.
|
||||
///
|
||||
/// The callback manager implements the "publisher" of the observer pattern we
|
||||
/// implement. It stores and calls three kinds of callbacks:
|
||||
/// 1. Hit callbacks, taking a key and value after a cache hit.
|
||||
/// 2. Miss callbacks, taking only a key, that was not found in a cache.
|
||||
/// 3. Access callbacks, taking a key and a boolean indicating a hit or a miss.
|
||||
///
|
||||
/// Callbacks can be added, accessed and cleared.
|
||||
template <typename Key, typename Value>
|
||||
class CallbackManager {
|
||||
public:
|
||||
using HitCallback = std::function<void(const Key&, const Value&)>;
|
||||
using MissCallback = std::function<void(const Key&)>;
|
||||
using AccessCallback = std::function<void(const Key&, bool)>;
|
||||
|
||||
using HitCallbackContainer = std::vector<HitCallback>;
|
||||
using MissCallbackContainer = std::vector<MissCallback>;
|
||||
using AccessCallbackContainer = std::vector<AccessCallback>;
|
||||
|
||||
/// Calls all callbacks registered for a hit, with the given key and value.
|
||||
///
|
||||
/// \param key The key for which a cache hit ocurred.
|
||||
/// \param value The value that was found for the key.
|
||||
void hit(const Key& key, const Value& value) {
|
||||
_call_each(_hit_callbacks, key, value);
|
||||
_call_each(_access_callbacks, key, true);
|
||||
}
|
||||
|
||||
/// Calls all callbacks registered for a miss, with the given key.
|
||||
///
|
||||
/// \param key The key for which a cache miss ocurred.
|
||||
void miss(const Key& key) {
|
||||
_call_each(_miss_callbacks, key);
|
||||
_call_each(_access_callbacks, key, false);
|
||||
}
|
||||
|
||||
/// Registers a new hit callback.
|
||||
///
|
||||
/// \param hit_callback The hit callback function to register with the
|
||||
/// manager.
|
||||
template <typename Callback>
|
||||
void hit_callback(Callback&& hit_callback) {
|
||||
_hit_callbacks.emplace_back(std::forward<Callback>(hit_callback));
|
||||
}
|
||||
|
||||
/// Registers a new miss callback.
|
||||
///
|
||||
/// \param miss_callback The miss callback function to register with the
|
||||
/// manager.
|
||||
template <typename Callback>
|
||||
void miss_callback(Callback&& miss_callback) {
|
||||
_miss_callbacks.emplace_back(std::forward<Callback>(miss_callback));
|
||||
}
|
||||
|
||||
/// Registers a new access callback.
|
||||
///
|
||||
/// \param access_callback The access callback function to register with the
|
||||
/// manager.
|
||||
template <typename Callback>
|
||||
void access_callback(Callback&& access_callback) {
|
||||
_access_callbacks.emplace_back(std::forward<Callback>(access_callback));
|
||||
}
|
||||
|
||||
/// Clears all hit callbacks.
|
||||
void clear_hit_callbacks() {
|
||||
_hit_callbacks.clear();
|
||||
}
|
||||
|
||||
/// Clears all miss callbacks.
|
||||
void clear_miss_callbacks() {
|
||||
_miss_callbacks.clear();
|
||||
}
|
||||
|
||||
/// Clears all access callbacks.
|
||||
void clear_access_callbacks() {
|
||||
_access_callbacks.clear();
|
||||
}
|
||||
|
||||
/// Clears all callbacks.
|
||||
void clear() {
|
||||
clear_hit_callbacks();
|
||||
clear_miss_callbacks();
|
||||
clear_access_callbacks();
|
||||
}
|
||||
|
||||
/// \returns All hit callbacks.
|
||||
const HitCallbackContainer& hit_callbacks() const noexcept {
|
||||
return _hit_callbacks;
|
||||
}
|
||||
|
||||
/// \returns All miss callbacks.
|
||||
const MissCallbackContainer& miss_callbacks() const noexcept {
|
||||
return _miss_callbacks;
|
||||
}
|
||||
|
||||
/// \returns All access callbacks.
|
||||
const AccessCallbackContainer& access_callbacks() const noexcept {
|
||||
return _access_callbacks;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Calls each function in the given container with the given arguments.
|
||||
///
|
||||
/// \param callbacks The container of callbacks to call.
|
||||
/// \param args The arguments to call the callbacks with.
|
||||
template <typename CallbackContainer, typename... Args>
|
||||
void _call_each(const CallbackContainer& callbacks, Args&&... args) {
|
||||
for (const auto& callback : callbacks) {
|
||||
callback(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
/// The container of hit callbacks registered.
|
||||
HitCallbackContainer _hit_callbacks;
|
||||
|
||||
/// The container of miss callbacks registered.
|
||||
MissCallbackContainer _miss_callbacks;
|
||||
|
||||
/// The container of access callbacks registered.
|
||||
AccessCallbackContainer _access_callbacks;
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_INTERNAL_CALLBACK_MANAGER_HPP
|
||||
88
src/3rdParty/lru-cache/include/lru/internal/definitions.hpp
vendored
Normal file
88
src/3rdParty/lru-cache/include/lru/internal/definitions.hpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_DEFINITIONS_HPP
|
||||
#define LRU_INTERNAL_DEFINITIONS_HPP
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// The default capacity for all caches.
|
||||
const std::size_t DEFAULT_CAPACITY = 128;
|
||||
|
||||
/// The reference type use to store keys in the order queue.
|
||||
template <typename T>
|
||||
using Reference = std::reference_wrapper<T>;
|
||||
|
||||
/// Compares two References for equality.
|
||||
///
|
||||
/// This is necessary because `std::reference_wrapper` does not define any
|
||||
/// operator overloads. We do need them, however (e.g. for container
|
||||
/// comparison).
|
||||
///
|
||||
/// \param first The first reference to compare.
|
||||
/// \param second The second reference to compare.
|
||||
template <typename T, typename U>
|
||||
bool operator==(const Reference<T>& first, const Reference<U>& second) {
|
||||
return first.get() == second.get();
|
||||
}
|
||||
|
||||
/// Compares two References for inequality.
|
||||
///
|
||||
/// This is necessary because `std::reference_wrapper` does not define any
|
||||
/// operator overloads. We do need them, however (e.g. for container
|
||||
/// comparison).
|
||||
///
|
||||
/// \param first The first reference to compare.
|
||||
/// \param second The second reference to compare.
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const Reference<T>& first, const Reference<U>& second) {
|
||||
return !(first == second);
|
||||
}
|
||||
|
||||
/// The default queue type used internally.
|
||||
template <typename T>
|
||||
using Queue = std::list<Reference<T>>;
|
||||
|
||||
/// The default map type used internally.
|
||||
template <typename Key,
|
||||
typename Information,
|
||||
typename HashFunction,
|
||||
typename KeyEqual>
|
||||
using Map = std::unordered_map<Key, Information, HashFunction, KeyEqual>;
|
||||
|
||||
/// The default clock used internally.
|
||||
using Clock = std::chrono::steady_clock;
|
||||
|
||||
/// The default timestamp (time point) used internally.
|
||||
using Timestamp = Clock::time_point;
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
|
||||
#endif // LRU_INTERNAL_DEFINITIONS_HPP
|
||||
62
src/3rdParty/lru-cache/include/lru/internal/hash.hpp
vendored
Normal file
62
src/3rdParty/lru-cache/include/lru/internal/hash.hpp
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_HASH_HPP
|
||||
#define LRU_INTERNAL_HASH_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
/// `std::hash` specialization to allow storing tuples as keys
|
||||
/// in `std::unordered_map`.
|
||||
///
|
||||
/// Essentially hashes all tuple elements and jumbles the
|
||||
/// individual hashes together.
|
||||
namespace std {
|
||||
template <typename... Ts>
|
||||
struct hash<std::tuple<Ts...>> {
|
||||
using argument_type = std::tuple<Ts...>;
|
||||
using result_type = std::size_t;
|
||||
|
||||
result_type operator()(const argument_type& argument) const {
|
||||
return hash_tuple(argument, std::make_index_sequence<sizeof...(Ts)>());
|
||||
}
|
||||
|
||||
private:
|
||||
template <std::size_t I, std::size_t... Is>
|
||||
result_type
|
||||
hash_tuple(const argument_type& tuple, std::index_sequence<I, Is...>) const {
|
||||
auto value = std::get<I>(tuple);
|
||||
auto current = std::hash<decltype(value)>{}(value);
|
||||
auto seed = hash_tuple(tuple, std::index_sequence<Is...>());
|
||||
|
||||
// http://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html
|
||||
return current + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
result_type hash_tuple(const argument_type&, std::index_sequence<>) const {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif // LRU_INTERNAL_HASH_HPP
|
||||
145
src/3rdParty/lru-cache/include/lru/internal/information.hpp
vendored
Normal file
145
src/3rdParty/lru-cache/include/lru/internal/information.hpp
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_INFORMATION_HPP
|
||||
#define LRU_INTERNAL_INFORMATION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <lru/internal/definitions.hpp>
|
||||
#include <lru/internal/utility.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// The value type of internal maps, used to store a value and iterator.
|
||||
///
|
||||
/// This information object is the basis of an LRU cache, which must associated
|
||||
/// a value and such an order iterator with a key, such that the iterator may be
|
||||
/// moved to the front of the order when the key is updated with a new value.
|
||||
///
|
||||
/// \tparam Key The key type of the information.
|
||||
/// \tparam Value The value type of the information.
|
||||
template <typename Key, typename Value>
|
||||
struct Information {
|
||||
using KeyType = Key;
|
||||
using ValueType = Value;
|
||||
using QueueIterator = typename Internal::Queue<const Key>::const_iterator;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param value_ The value for the information.
|
||||
/// \param order_ The order iterator for the information.
|
||||
explicit Information(const Value& value_,
|
||||
QueueIterator order_ = QueueIterator())
|
||||
: value(value_), order(order_) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param order_ The order iterator for the information.
|
||||
/// \param value_arguments Any number of arguments to perfectly forward to the
|
||||
/// value type's constructor.
|
||||
// template <typename... ValueArguments>
|
||||
// Information(QueueIterator order_, ValueArguments&&... value_arguments)
|
||||
// : value(std::forward<ValueArguments>(value_arguments)...), order(order_) {
|
||||
// }
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param order_ The order iterator for the information.
|
||||
/// \param value_arguments A tuple of arguments to perfectly forward to the
|
||||
/// value type's constructor.
|
||||
///
|
||||
template <typename... ValueArguments>
|
||||
explicit Information(const std::tuple<ValueArguments...>& value_arguments,
|
||||
QueueIterator order_ = QueueIterator())
|
||||
: Information(
|
||||
order_, value_arguments, Internal::tuple_indices(value_arguments)) {
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
Information(const Information& other) = default;
|
||||
|
||||
/// Move constructor.
|
||||
Information(Information&& other) = default;
|
||||
|
||||
/// Copy assignment operator.
|
||||
Information& operator=(const Information& other) = default;
|
||||
|
||||
/// Move assignment operator.
|
||||
Information& operator=(Information&& other) = default;
|
||||
|
||||
/// Destructor.
|
||||
virtual ~Information() = default;
|
||||
|
||||
/// Compares the information for equality with another information object.
|
||||
///
|
||||
/// \param other The other information object to compare to.
|
||||
/// \returns True if key and value (not the iterator itself) of the two
|
||||
/// information objects are equal, else false.
|
||||
virtual bool operator==(const Information& other) const noexcept {
|
||||
if (this == &other) return true;
|
||||
if (this->value != other.value) return false;
|
||||
// We do not compare the iterator (because otherwise two containers
|
||||
// holding information would never be equal). We also do not compare
|
||||
// the key stored in the iterator, because keys will always have been
|
||||
// compared before this operator is called.
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Compares the information for inequality with another information object.
|
||||
///
|
||||
/// \param other The other information object to compare for.
|
||||
/// \returns True if key and value (not the iterator itself) of the two
|
||||
/// information objects are unequal, else false.
|
||||
virtual bool operator!=(const Information& other) const noexcept {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/// The value of the information.
|
||||
Value value;
|
||||
|
||||
/// The order iterator of the information.
|
||||
QueueIterator order;
|
||||
|
||||
private:
|
||||
/// Implementation for the constructor taking a tuple of arguments for the
|
||||
/// value.
|
||||
///
|
||||
/// \param order_ The order iterator for the information.
|
||||
/// \param value_argument The tuple of arguments to perfectly forward to the
|
||||
/// value type's constructor.
|
||||
/// \param _ An index sequence to access the elements of the tuple
|
||||
template <typename... ValueArguments, std::size_t... Indices>
|
||||
Information(const QueueIterator& order_,
|
||||
const std::tuple<ValueArguments...>& value_argument,
|
||||
std::index_sequence<Indices...> _)
|
||||
: value(std::forward<ValueArguments>(std::get<Indices>(value_argument))...)
|
||||
, order(order_) {
|
||||
}
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_INTERNAL_INFORMATION_HPP
|
||||
254
src/3rdParty/lru-cache/include/lru/internal/last-accessed.hpp
vendored
Normal file
254
src/3rdParty/lru-cache/include/lru/internal/last-accessed.hpp
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_LAST_ACCESSED_HPP
|
||||
#define LRU_INTERNAL_LAST_ACCESSED_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
#include <lru/internal/utility.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// Provides a simple iterator-compatible pointer object for a key and
|
||||
/// information.
|
||||
///
|
||||
/// The easisest idea for this class, theoretically, would be to just store an s
|
||||
/// iterator to the internal cache map (i.e. template the class on the iterator
|
||||
/// type). However, the major trouble with that approach is that this class
|
||||
/// should be 100% *mutable*, as in "always non-const", so that keys and
|
||||
/// informations
|
||||
/// we store for fast access can be (quickly) retrieved as either const or
|
||||
/// non-const (iterators for example). This is not possible, since the
|
||||
/// const-ness of `const_iterators` are not the usual idea of const in C++,
|
||||
/// meaning especially it cannot be cast away with a `const_cast` as is required
|
||||
/// for the mutability. As such, we *must* store the plain keys and
|
||||
/// informations.
|
||||
/// This, however, means that iterators cannot be stored efficiently, since a
|
||||
/// new hash table lookup would be required to go from a key to its iterator.
|
||||
/// However, since the main use case of this class is to avoid a second lookup
|
||||
/// in the usual `if (cache.contains(key)) return cache.lookup(key)`, which is
|
||||
/// not an issue for iterators since they can be compared to the `end` iterator
|
||||
/// in constant time (equivalent to the call to `contains()`).
|
||||
///
|
||||
/// WARNING: This class stores *pointers* to keys and informations. As such
|
||||
/// lifetime
|
||||
/// of the pointed-to objects must be cared for by the user of this class.
|
||||
///
|
||||
/// \tparam Key The type of key being accessed.
|
||||
/// \tparam InformationType The type of information being accessed.
|
||||
/// \tparam KeyEqual The type of the key comparison function.
|
||||
template <typename Key,
|
||||
typename InformationType,
|
||||
typename KeyEqual = std::equal_to<Key>>
|
||||
class LastAccessed {
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param key_equal The function to compare keys with.
|
||||
explicit LastAccessed(const KeyEqual& key_equal = KeyEqual())
|
||||
: _key(nullptr)
|
||||
, _information(nullptr)
|
||||
, _is_valid(false)
|
||||
, _key_equal(key_equal) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param key The key to store a reference to.
|
||||
/// \param information The information to store a reference to.
|
||||
/// \param key_equal The function to compare keys with.
|
||||
LastAccessed(const Key& key,
|
||||
const InformationType& information,
|
||||
const KeyEqual& key_equal = KeyEqual())
|
||||
: _key(const_cast<Key*>(&key))
|
||||
, _information(const_cast<InformationType*>(&information))
|
||||
, _is_valid(true)
|
||||
, _key_equal(key_equal) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param iterator An iterator pointing to a key and information to use for
|
||||
/// constructing the instance.
|
||||
/// \param key_equal The function to compare keys with.
|
||||
template <typename Iterator>
|
||||
explicit LastAccessed(Iterator iterator,
|
||||
const KeyEqual& key_equal = KeyEqual())
|
||||
: LastAccessed(iterator->first, iterator->second, key_equal) {
|
||||
}
|
||||
|
||||
/// Copy assignment operator for iterators.
|
||||
///
|
||||
/// \param iterator An iterator pointing to a key and value to use for the
|
||||
/// `LastAccessed` instance.
|
||||
/// \return The resulting `LastAccessed` instance.
|
||||
template <typename Iterator>
|
||||
LastAccessed& operator=(Iterator iterator) {
|
||||
_key = const_cast<Key*>(&(iterator->first));
|
||||
_information = const_cast<InformationType*>(&(iterator->second));
|
||||
_is_valid = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Compares a `LastAccessed` object for equality with a key.
|
||||
///
|
||||
/// \param last_accessed The `LastAccessed` instance to compare.
|
||||
/// \param key The key instance to compare.
|
||||
/// \returns True if the key of the `LastAccessed` object's key equals the
|
||||
/// given key, else false.
|
||||
friend bool
|
||||
operator==(const LastAccessed& last_accessed, const Key& key) noexcept {
|
||||
if (!last_accessed._is_valid) return false;
|
||||
return last_accessed._key_equal(key, last_accessed.key());
|
||||
}
|
||||
|
||||
/// \copydoc operator==(const LastAccessed&,const Key&)
|
||||
friend bool
|
||||
operator==(const Key& key, const LastAccessed& last_accessed) noexcept {
|
||||
return last_accessed == key;
|
||||
}
|
||||
|
||||
/// Compares a `LastAccessed` object for equality with an iterator.
|
||||
///
|
||||
/// \param last_accessed The `LastAccessed` instance to compare.
|
||||
/// \param iterator The iterator to compare with.
|
||||
/// \returns True if the `LastAccessed` object's key equals that of the
|
||||
/// iterator, else false.
|
||||
template <typename Iterator, typename = enable_if_iterator<Iterator>>
|
||||
friend bool
|
||||
operator==(const LastAccessed& last_accessed, Iterator iterator) noexcept {
|
||||
/// Fast comparisons to an iterator (not relying on implicit conversion)
|
||||
return last_accessed == iterator->first;
|
||||
}
|
||||
|
||||
/// \copydoc operator==(const LastAccessed&,Iterator)
|
||||
template <typename Iterator, typename = enable_if_iterator<Iterator>>
|
||||
friend bool
|
||||
operator==(Iterator iterator, const LastAccessed& last_accessed) noexcept {
|
||||
return last_accessed == iterator;
|
||||
}
|
||||
|
||||
/// Compares a `LastAccessed` object for inequality with something.
|
||||
///
|
||||
/// \param last_accessed The `LastAccessed` instance to compare.
|
||||
/// \param other Something else to compare to.
|
||||
/// \returns True if the key of the `LastAccessed` object's key does not equal
|
||||
/// the given other object's key, else false.
|
||||
template <typename T>
|
||||
friend bool
|
||||
operator!=(const LastAccessed& last_accessed, const T& other) noexcept {
|
||||
return !(last_accessed == other);
|
||||
}
|
||||
|
||||
/// \copydoc operator!=(const LastAccessed&,const T&)
|
||||
template <typename T>
|
||||
friend bool
|
||||
operator!=(const T& other, const LastAccessed& last_accessed) noexcept {
|
||||
return !(other == last_accessed);
|
||||
}
|
||||
|
||||
/// \returns The last accessed key.
|
||||
Key& key() noexcept {
|
||||
assert(is_valid());
|
||||
return *_key;
|
||||
}
|
||||
|
||||
/// \returns The last accessed key.
|
||||
const Key& key() const noexcept {
|
||||
assert(is_valid());
|
||||
return *_key;
|
||||
}
|
||||
|
||||
/// \returns The last accessed information.
|
||||
InformationType& information() noexcept {
|
||||
assert(is_valid());
|
||||
return *_information;
|
||||
}
|
||||
|
||||
/// \returns The last accessed information.
|
||||
const InformationType& information() const noexcept {
|
||||
assert(is_valid());
|
||||
return *_information;
|
||||
}
|
||||
|
||||
/// \returns The last accessed information.
|
||||
auto& iterator() noexcept {
|
||||
assert(is_valid());
|
||||
return _information->order;
|
||||
}
|
||||
|
||||
/// \returns The last accessed value.
|
||||
auto& value() noexcept {
|
||||
assert(is_valid());
|
||||
return _information->value;
|
||||
}
|
||||
|
||||
/// \returns The last accessed value.
|
||||
const auto& value() const noexcept {
|
||||
assert(is_valid());
|
||||
return _information->value;
|
||||
}
|
||||
|
||||
/// \returns True if the key and information of the instance may be accessed,
|
||||
/// else false.
|
||||
bool is_valid() const noexcept {
|
||||
return _is_valid;
|
||||
}
|
||||
|
||||
/// \copydoc is_valid()
|
||||
explicit operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
/// Invalidates the instance.
|
||||
void invalidate() noexcept {
|
||||
_is_valid = false;
|
||||
_key = nullptr;
|
||||
_information = nullptr;
|
||||
}
|
||||
|
||||
/// \returns The key comparison function used.
|
||||
const KeyEqual& key_equal() const noexcept {
|
||||
return _key_equal;
|
||||
}
|
||||
|
||||
private:
|
||||
/// A pointer to the key that was last accessed (if any).
|
||||
Key* _key;
|
||||
|
||||
/// A pointer to the information that was last accessed (if any).
|
||||
InformationType* _information;
|
||||
|
||||
/// True if the key and information pointers are valid, else false.
|
||||
bool _is_valid;
|
||||
|
||||
/// The function used to compare keys.
|
||||
KeyEqual _key_equal;
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_INTERNAL_LAST_ACCESSED_HPP
|
||||
207
src/3rdParty/lru-cache/include/lru/internal/optional.hpp
vendored
Normal file
207
src/3rdParty/lru-cache/include/lru/internal/optional.hpp
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_OPTIONAL_HPP
|
||||
#define LRU_INTERNAL_OPTIONAL_HPP
|
||||
|
||||
#ifndef __has_include
|
||||
#define USE_LRU_OPTIONAL
|
||||
#elif __has_include(<optional>)
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
template <typename T>
|
||||
using Optional = std::optional<T>;
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#else
|
||||
#define USE_LRU_OPTIONAL
|
||||
#endif
|
||||
|
||||
#ifdef USE_LRU_OPTIONAL
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
// A roll-your-own replacement of `std::optional`.
|
||||
//
|
||||
// This class is only to be used if `std::optional` is unavailable. It
|
||||
// implements an optional type simply on top of a `unique_ptr`. It is
|
||||
// API-compatible with `std::optional`, as required for our purposes.
|
||||
template <typename T>
|
||||
class Optional {
|
||||
public:
|
||||
/// Constructor.
|
||||
Optional() = default;
|
||||
|
||||
/// Copy constructor.
|
||||
///
|
||||
/// \param other The other optional object to copy from.
|
||||
Optional(const Optional& other) {
|
||||
if (other) emplace(*other);
|
||||
}
|
||||
|
||||
/// Generalized copy constructor.
|
||||
///
|
||||
/// \param other The other optional object to copy from.
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible<T, U>::value>>
|
||||
Optional(const Optional<U>& other) {
|
||||
if (other) emplace(*other);
|
||||
}
|
||||
|
||||
/// Move constructor.
|
||||
///
|
||||
/// \param other The other optional object to move into this one.
|
||||
Optional(Optional&& other) noexcept {
|
||||
swap(other);
|
||||
}
|
||||
|
||||
/// Generalized move constructor.
|
||||
///
|
||||
/// \param other The other optional object to move into this one.
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_convertible<T, U>::value>>
|
||||
Optional(Optional<U>&& other) noexcept {
|
||||
if (other) {
|
||||
_value = std::make_unique<T>(std::move(*other));
|
||||
}
|
||||
}
|
||||
|
||||
/// Assignment operator.
|
||||
///
|
||||
/// \param other The other object to assign from.
|
||||
/// \returns The resulting optional instance.
|
||||
Optional& operator=(Optional other) noexcept {
|
||||
swap(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Swaps the contents of this optional with another one.
|
||||
///
|
||||
/// \param other The other optional to swap with.
|
||||
void swap(Optional& other) {
|
||||
_value.swap(other._value);
|
||||
}
|
||||
|
||||
/// Swaps the contents of two optionals.
|
||||
///
|
||||
/// \param first The first optional to swap.
|
||||
/// \param second The second optional to swap.
|
||||
friend void swap(Optional& first, Optional& second) /* NOLINT */ {
|
||||
first.swap(second);
|
||||
}
|
||||
|
||||
/// \returns True if the `Optional` has a value, else false.
|
||||
bool has_value() const noexcept {
|
||||
return static_cast<bool>(_value);
|
||||
}
|
||||
|
||||
/// \copydoc has_value()
|
||||
explicit operator bool() const noexcept {
|
||||
return has_value();
|
||||
}
|
||||
|
||||
/// \returns A pointer to the current value. Behavior is undefined if the
|
||||
/// optional has no value.
|
||||
T* operator->() {
|
||||
return _value.get();
|
||||
}
|
||||
|
||||
/// \returns A const pointer to the current value. Behavior is undefined if
|
||||
/// the `Optional` has no value.
|
||||
const T* operator->() const {
|
||||
return _value.get();
|
||||
}
|
||||
|
||||
/// \returns A const reference to the current value. Behavior is undefined if
|
||||
/// the `Optional` has no value.
|
||||
const T& operator*() const {
|
||||
return *_value;
|
||||
}
|
||||
|
||||
/// \returns A reference to the current value. Behavior is undefined if
|
||||
/// the `Optional` has no value.
|
||||
T& operator*() {
|
||||
return *_value;
|
||||
}
|
||||
|
||||
/// \returns A reference to the current value.
|
||||
/// \throws std::runtime_error If the `Optional` currently has no value.
|
||||
T& value() {
|
||||
if (!has_value()) {
|
||||
// Actually std::bad_optional_access
|
||||
throw std::runtime_error("optional has no value");
|
||||
}
|
||||
|
||||
return *_value;
|
||||
}
|
||||
|
||||
/// \returns A const reference to the current value.
|
||||
/// \throws std::runtime_error If the `Optional` currently has no value.
|
||||
const T& value() const {
|
||||
if (!has_value()) {
|
||||
// Actually std::bad_optional_access
|
||||
throw std::runtime_error("optional has no value");
|
||||
}
|
||||
|
||||
return *_value;
|
||||
}
|
||||
|
||||
/// \returns The current value, or the given argument if there is no value.
|
||||
/// \param default_value The value to return if this `Optional` currently has
|
||||
/// no value.
|
||||
template <class U>
|
||||
T value_or(U&& default_value) const {
|
||||
return *this ? **this : static_cast<T>(std::forward<U>(default_value));
|
||||
}
|
||||
|
||||
/// Resets the `Optional` to have no value.
|
||||
void reset() noexcept {
|
||||
_value.reset();
|
||||
}
|
||||
|
||||
/// Constructs the `Optional`'s value with the given arguments.
|
||||
///
|
||||
/// \param args Arguments to perfeclty forward to the value's constructor.
|
||||
template <typename... Args>
|
||||
void emplace(Args&&... args) {
|
||||
_value = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend class Optional;
|
||||
|
||||
/// The value, as we implement it.
|
||||
std::unique_ptr<T> _value;
|
||||
};
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LRU_INTERNAL_OPTIONAL_HPP
|
||||
150
src/3rdParty/lru-cache/include/lru/internal/statistics-mutator.hpp
vendored
Normal file
150
src/3rdParty/lru-cache/include/lru/internal/statistics-mutator.hpp
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_STATISTICS_MUTATOR_HPP
|
||||
#define LRU_STATISTICS_MUTATOR_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <lru/internal/optional.hpp>
|
||||
#include <lru/statistics.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// A mutable proxy interface to a statistics object.
|
||||
///
|
||||
/// The `StatisticsMutator` allows modification of the members of a statistics
|
||||
/// object via a narrow interface, available only to internal classes. The point
|
||||
/// of this is that while we don't want the user to be able to modify the hit or
|
||||
/// miss count on a statistics object (it is "getter-only" in that sense), it's
|
||||
/// also not ideal, from an encapsulation standpoint, to make the cache classes
|
||||
/// (which do need to access and modify the hit and miss counts) friends of the
|
||||
/// statistics. This is especially true since the caches should only need to
|
||||
/// register hits or misses and not have to increment the count of total
|
||||
/// accesses. As such, we really require a "package-level" interface that is not
|
||||
/// visible to the end user, while at the same time providing an interface to
|
||||
/// internal classes. The `StatisticsMutator` is a proxy/adapter class that
|
||||
/// serves exactly this purpose. It is friends with the `Statistics` and can
|
||||
/// thus access its members. At the same time the interface it defines is narrow
|
||||
/// and provides only the necessary interface for the cache classes to register
|
||||
/// hits and misses.
|
||||
template <typename Key>
|
||||
class StatisticsMutator {
|
||||
public:
|
||||
using StatisticsPointer = std::shared_ptr<Statistics<Key>>;
|
||||
|
||||
/// Constructor.
|
||||
StatisticsMutator() noexcept = default;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param stats A shared pointer lvalue reference.
|
||||
StatisticsMutator(const StatisticsPointer& stats) // NOLINT(runtime/explicit)
|
||||
: _stats(stats) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param stats A shared pointer rvalue reference to move into the
|
||||
/// mutator.
|
||||
StatisticsMutator(StatisticsPointer&& stats) // NOLINT(runtime/explicit)
|
||||
: _stats(std::move(stats)) {
|
||||
}
|
||||
|
||||
/// Registers a hit for the given key with the internal statistics.
|
||||
///
|
||||
/// \param key The key to register a hit for.
|
||||
void register_hit(const Key& key) {
|
||||
assert(has_stats());
|
||||
|
||||
_stats->_total_accesses += 1;
|
||||
_stats->_total_hits += 1;
|
||||
|
||||
auto iterator = _stats->_key_map.find(key);
|
||||
if (iterator != _stats->_key_map.end()) {
|
||||
iterator->second.hits += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers a miss for the given key with the internal statistics.
|
||||
///
|
||||
/// \param key The key to register a miss for.
|
||||
void register_miss(const Key& key) {
|
||||
assert(has_stats());
|
||||
|
||||
_stats->_total_accesses += 1;
|
||||
|
||||
auto iterator = _stats->_key_map.find(key);
|
||||
if (iterator != _stats->_key_map.end()) {
|
||||
iterator->second.misses += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns A reference to the statistics object.
|
||||
Statistics<Key>& get() noexcept {
|
||||
assert(has_stats());
|
||||
return *_stats;
|
||||
}
|
||||
|
||||
/// \returns A const reference to the statistics object.
|
||||
const Statistics<Key>& get() const noexcept {
|
||||
assert(has_stats());
|
||||
return *_stats;
|
||||
}
|
||||
|
||||
/// \returns A `shared_ptr` to the statistics object.
|
||||
StatisticsPointer& shared() noexcept {
|
||||
return _stats;
|
||||
}
|
||||
|
||||
/// \returns A const `shared_ptr` to the statistics object.
|
||||
const StatisticsPointer& shared() const noexcept {
|
||||
return _stats;
|
||||
}
|
||||
|
||||
/// \returns True if the mutator has a statistics object, else false.
|
||||
bool has_stats() const noexcept {
|
||||
return _stats != nullptr;
|
||||
}
|
||||
|
||||
/// \copydoc has_stats()
|
||||
explicit operator bool() const noexcept {
|
||||
return has_stats();
|
||||
}
|
||||
|
||||
/// Resets the internal statistics pointer.
|
||||
void reset() {
|
||||
_stats.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
/// A shared pointer to a statistics object.
|
||||
std::shared_ptr<Statistics<Key>> _stats;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_STATISTICS_MUTATOR_HPP
|
||||
116
src/3rdParty/lru-cache/include/lru/internal/timed-information.hpp
vendored
Normal file
116
src/3rdParty/lru-cache/include/lru/internal/timed-information.hpp
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_INTERNAL_TIMED_INFORMATION_HPP
|
||||
#define LRU_INTERNAL_TIMED_INFORMATION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <lru/internal/definitions.hpp>
|
||||
#include <lru/internal/information.hpp>
|
||||
#include <lru/internal/utility.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// The information object for timed caches.
|
||||
///
|
||||
/// TimedInformation differs from plain information only in that it stores the
|
||||
/// creation time, to know when a key has expired.
|
||||
///
|
||||
/// \tparam Key The key type of the information.
|
||||
/// \tparam Value The value type of the information.
|
||||
template <typename Key, typename Value>
|
||||
struct TimedInformation : public Information<Key, Value> {
|
||||
using super = Information<Key, Value>;
|
||||
using typename super::QueueIterator;
|
||||
using Timestamp = Internal::Timestamp;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param value_ The value for the information.
|
||||
/// \param insertion_time_ The insertion timestamp of the key.
|
||||
/// \param order_ The order iterator for the information.
|
||||
TimedInformation(const Value& value_,
|
||||
const Timestamp& insertion_time_,
|
||||
QueueIterator order_ = QueueIterator())
|
||||
: super(value_, order_), insertion_time(insertion_time_) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// Uses the current time as the insertion timestamp.
|
||||
///
|
||||
/// \param value_ The value for the information.
|
||||
/// \param order_ The order iterator for the information.
|
||||
explicit TimedInformation(const Value& value_,
|
||||
QueueIterator order_ = QueueIterator())
|
||||
: TimedInformation(value_, Internal::Clock::now(), order_) {
|
||||
}
|
||||
|
||||
/// \copydoc Information::Information(QueueIterator,ValueArguments&&)
|
||||
template <typename... ValueArguments>
|
||||
TimedInformation(QueueIterator order_, ValueArguments&&... value_argument)
|
||||
: super(std::forward<ValueArguments>(value_argument)..., order_)
|
||||
, insertion_time(Internal::Clock::now()) {
|
||||
}
|
||||
|
||||
/// \copydoc Information::Information(QueueIterator,const
|
||||
/// std::tuple<ValueArguments...>&)
|
||||
template <typename... ValueArguments>
|
||||
explicit TimedInformation(
|
||||
const std::tuple<ValueArguments...>& value_arguments,
|
||||
QueueIterator order_ = QueueIterator())
|
||||
: super(value_arguments, order_), insertion_time(Internal::Clock::now()) {
|
||||
}
|
||||
|
||||
/// Compares this timed information for equality with another one.
|
||||
///
|
||||
/// Additionally to key and value equality, the timed information requires
|
||||
/// that the insertion timestamps be equal.
|
||||
///
|
||||
/// \param other The other timed information.
|
||||
/// \returns True if this information equals the other one, else false.
|
||||
bool operator==(const TimedInformation& other) const noexcept {
|
||||
if (super::operator!=(other)) return false;
|
||||
return this->insertion_time == other.insertion_time;
|
||||
}
|
||||
|
||||
/// Compares this timed information for inequality with another one.
|
||||
///
|
||||
/// \param other The other timed information.
|
||||
/// \returns True if this information does not equal the other one, else
|
||||
/// false.
|
||||
/// \see operator==()
|
||||
bool operator!=(const TimedInformation& other) const noexcept {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/// The time at which the key of the information was insterted into a cache.
|
||||
const Timestamp insertion_time;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_INTERNAL_TIMED_INFORMATION_HPP
|
||||
178
src/3rdParty/lru-cache/include/lru/internal/utility.hpp
vendored
Normal file
178
src/3rdParty/lru-cache/include/lru/internal/utility.hpp
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_UTILITY_HPP
|
||||
#define LRU_UTILITY_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
|
||||
/// Generates an index sequence for a tuple.
|
||||
///
|
||||
/// \tparam Ts The types of the tuple (to deduce the size).
|
||||
template <typename... Ts>
|
||||
constexpr auto tuple_indices(const std::tuple<Ts...>&) {
|
||||
return std::make_index_sequence<sizeof...(Ts)>();
|
||||
}
|
||||
|
||||
/// Applies (in the functional sense) a tuple to the constructor of a class.
|
||||
///
|
||||
/// \tparam T The type to construct.
|
||||
/// \tparam Indices The indices into the tuple (generated from an index
|
||||
/// sequence).
|
||||
/// \param args The tuple of arguments to construct the object with.
|
||||
template <typename T, typename... Args, std::size_t... Indices>
|
||||
constexpr T construct_from_tuple(const std::tuple<Args...>& arguments,
|
||||
std::index_sequence<Indices...>) {
|
||||
return T(std::forward<Args>(std::get<Indices>(arguments))...);
|
||||
}
|
||||
|
||||
/// Applies (in the functional sense) a tuple to the constructor of a class.
|
||||
///
|
||||
/// \tparam T The type to construct.
|
||||
/// \param args The tuple of arguments to construct the object with.
|
||||
template <typename T, typename... Args>
|
||||
constexpr T construct_from_tuple(const std::tuple<Args...>& args) {
|
||||
return construct_from_tuple<T>(args, tuple_indices(args));
|
||||
}
|
||||
|
||||
/// Applies (in the functional sense) a tuple to the constructor of a class.
|
||||
///
|
||||
/// \tparam T The type to construct.
|
||||
/// \param args The tuple of arguments to construct the object with.
|
||||
template <typename T, typename... Args>
|
||||
constexpr T construct_from_tuple(std::tuple<Args...>&& args) {
|
||||
return construct_from_tuple<T>(std::move(args), tuple_indices(args));
|
||||
}
|
||||
|
||||
/// A type trait that disables a template overload if a type is not an iterator.
|
||||
///
|
||||
/// \tparam T the type to check.
|
||||
template <typename T>
|
||||
using enable_if_iterator = typename std::iterator_traits<T>::value_type;
|
||||
|
||||
/// A type trait that disables a template overload if a type is not a range.
|
||||
///
|
||||
/// \tparam T the type to check.
|
||||
template <typename T>
|
||||
using enable_if_range = std::pair<decltype(std::declval<T>().begin()),
|
||||
decltype(std::declval<T>().end())>;
|
||||
|
||||
/// A type trait that disables a template overload if a type is not an iterator
|
||||
/// over a pair.
|
||||
///
|
||||
/// \tparam T the type to check.
|
||||
template <typename T>
|
||||
using enable_if_iterator_over_pair =
|
||||
std::pair<typename std::iterator_traits<T>::value_type::first_type,
|
||||
typename std::iterator_traits<T>::value_type::first_type>;
|
||||
|
||||
|
||||
/// A type trait that disables a template overload if a type is not convertible
|
||||
/// to a target type.
|
||||
///
|
||||
/// \tparam Target The type one wants to check against.
|
||||
/// \tparam T The type to check.
|
||||
template <typename Target, typename T>
|
||||
using enable_if_same = std::enable_if_t<std::is_convertible<T, Target>::value>;
|
||||
|
||||
/// Base case for `static_all_of` (the neutral element of AND is true).
|
||||
constexpr bool static_all_of() noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Checks if all the given parameters evaluate to true.
|
||||
///
|
||||
/// \param head The first expression to check.
|
||||
/// \param tail The remaining expression to check.
|
||||
template <typename Head, typename... Tail>
|
||||
constexpr bool static_all_of(Head&& head, Tail&&... tail) {
|
||||
// Replace with (ts && ...) when the time is right
|
||||
return std::forward<Head>(head) && static_all_of(std::forward<Tail>(tail)...);
|
||||
}
|
||||
|
||||
/// Base case for `static_any_of` (the neutral element of OR is false).
|
||||
constexpr bool static_any_of() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Checks if any the given parameters evaluate to true.
|
||||
///
|
||||
/// \param head The first expression to check.
|
||||
/// \param tail The remaining expression to check.
|
||||
/// \returns True if any of the given parameters evaluate to true.
|
||||
template <typename Head, typename... Tail>
|
||||
constexpr bool static_any_of(Head&& head, Tail&&... tail) {
|
||||
// Replace with (ts || ...) when the time is right
|
||||
return std::forward<Head>(head) || static_any_of(std::forward<Tail>(tail)...);
|
||||
}
|
||||
|
||||
/// Checks if none the given parameters evaluate to true.
|
||||
///
|
||||
/// \param ts The expressions to check.
|
||||
/// \returns True if any of the given parameters evaluate to true.
|
||||
template <typename... Ts>
|
||||
constexpr bool static_none_of(Ts&&... ts) {
|
||||
// Replace with (!ts && ...) when the time is right
|
||||
return !static_any_of(std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
/// Checks if all the given types are convertible to the first type.
|
||||
///
|
||||
/// \tparam T the first type.
|
||||
/// \tparam Ts The types to check against the first.
|
||||
template <typename T, typename... Ts>
|
||||
constexpr bool
|
||||
all_of_type = static_all_of(std::is_convertible<Ts, T>::value...);
|
||||
|
||||
/// Checks if none of the given types are convertible to the first type.
|
||||
///
|
||||
/// \tparam T the first type.
|
||||
/// \tparam Ts The types to check against the first.
|
||||
template <typename T, typename... Ts>
|
||||
constexpr bool
|
||||
none_of_type = static_none_of(std::is_convertible<Ts, T>::value...);
|
||||
|
||||
/// Base case for `for_each`.
|
||||
template <typename Function>
|
||||
void for_each(Function) noexcept {
|
||||
}
|
||||
|
||||
/// Calls a function for each of the given variadic arguments.
|
||||
///
|
||||
/// \param function The function to call for each argument.
|
||||
/// \param head The first value to call the function with.
|
||||
/// \param tail The remaining values to call the function with.
|
||||
template <typename Function, typename Head, typename... Tail>
|
||||
void for_each(Function function, Head&& head, Tail&&... tail) {
|
||||
function(std::forward<Head>(head));
|
||||
for_each(function, std::forward<Tail>(tail)...);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_UTILITY_HPP
|
||||
40
src/3rdParty/lru-cache/include/lru/iterator-tags.hpp
vendored
Normal file
40
src/3rdParty/lru-cache/include/lru/iterator-tags.hpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_ITERATOR_TAGS_HPP
|
||||
#define LRU_ITERATOR_TAGS_HPP
|
||||
|
||||
namespace LRU {
|
||||
namespace Tag {
|
||||
struct OrderedIterator {};
|
||||
struct UnorderedIterator {};
|
||||
} // namespace Tag
|
||||
|
||||
namespace Lowercase {
|
||||
namespace tag {
|
||||
using ordered_iterator = ::LRU::Tag::OrderedIterator;
|
||||
using unordered_iterator = ::LRU::Tag::UnorderedIterator;
|
||||
} // namespace tag
|
||||
} // namespace Lowercase
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_ITERATOR_TAGS_HPP
|
||||
67
src/3rdParty/lru-cache/include/lru/key-statistics.hpp
vendored
Normal file
67
src/3rdParty/lru-cache/include/lru/key-statistics.hpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
|
||||
#ifndef LRU_KEY_STATISTICS_HPP
|
||||
#define LRU_KEY_STATISTICS_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace LRU {
|
||||
|
||||
/// Stores statistics for a single key.
|
||||
///
|
||||
/// The statistics stored are the total number of hits and the total number of
|
||||
/// misses. The total number of acccesses (the sum of hits and misses) may be
|
||||
/// accessed as well.
|
||||
struct KeyStatistics {
|
||||
using size_t = std::size_t;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param hits_ The initial number of hits for the key.
|
||||
/// \param misses_ The initial number of misses for the key.
|
||||
explicit KeyStatistics(size_t hits_ = 0, size_t misses_ = 0)
|
||||
: hits(hits_), misses(misses_) {
|
||||
}
|
||||
|
||||
/// \returns The total number of accesses made for the key.
|
||||
/// \details This is the sum of the hits and misses.
|
||||
size_t accesses() const noexcept {
|
||||
return hits + misses;
|
||||
}
|
||||
|
||||
/// Resets the statistics for a key (sets them to zero).
|
||||
void reset() {
|
||||
hits = 0;
|
||||
misses = 0;
|
||||
}
|
||||
|
||||
/// The number of hits for the key.
|
||||
size_t hits;
|
||||
|
||||
/// The number of misses for the key.
|
||||
size_t misses;
|
||||
};
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_KEY_STATISTICS_HPP
|
||||
34
src/3rdParty/lru-cache/include/lru/lowercase.hpp
vendored
Normal file
34
src/3rdParty/lru-cache/include/lru/lowercase.hpp
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_LOWERCASE_HPP
|
||||
#define LRU_LOWERCASE_HPP
|
||||
|
||||
#include <lru/lru.hpp>
|
||||
|
||||
namespace LRU {
|
||||
using namespace Lowercase; // NOLINT(build/namespaces)
|
||||
} // namespace LRU
|
||||
|
||||
namespace lru = LRU;
|
||||
|
||||
|
||||
#endif // LRU_LOWERCASE_HPP
|
||||
33
src/3rdParty/lru-cache/include/lru/lru.hpp
vendored
Normal file
33
src/3rdParty/lru-cache/include/lru/lru.hpp
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_HPP
|
||||
#define LRU_HPP
|
||||
|
||||
#include <lru/cache-tags.hpp>
|
||||
#include <lru/cache.hpp>
|
||||
#include <lru/error.hpp>
|
||||
#include <lru/iterator-tags.hpp>
|
||||
#include <lru/statistics.hpp>
|
||||
#include <lru/timed-cache.hpp>
|
||||
#include <lru/wrap.hpp>
|
||||
|
||||
#endif // LRU_HPP
|
||||
256
src/3rdParty/lru-cache/include/lru/statistics.hpp
vendored
Normal file
256
src/3rdParty/lru-cache/include/lru/statistics.hpp
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
|
||||
#ifndef LRU_STATISTICS_HPP
|
||||
#define LRU_STATISTICS_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <lru/error.hpp>
|
||||
#include <lru/internal/utility.hpp>
|
||||
#include <lru/key-statistics.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
template <typename>
|
||||
class StatisticsMutator;
|
||||
}
|
||||
|
||||
/// Stores statistics about LRU cache utilization and efficiency.
|
||||
///
|
||||
/// The statistics object stores the number of misses and hits were recorded for
|
||||
/// a cache in total. Furthemore, it is possibly to register a number of keys
|
||||
/// for *monitoring*. For each of these keys, an additional hit and miss count
|
||||
/// is maintained, that can keep insight into the utiliization of a particular
|
||||
/// cache. Note that accesses only mean lookups -- insertions or erasures will
|
||||
/// never signify an "access".
|
||||
///
|
||||
/// \tparam Key The type of the keys being monitored.
|
||||
template <typename Key>
|
||||
class Statistics {
|
||||
public:
|
||||
using size_t = std::size_t;
|
||||
using InitializerList = std::initializer_list<Key>;
|
||||
|
||||
/// Constructor.
|
||||
Statistics() noexcept : _total_accesses(0), _total_hits(0) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param keys Any number of keys to monitor.
|
||||
template <typename... Keys,
|
||||
typename = std::enable_if_t<Internal::all_of_type<Key, Keys...>>>
|
||||
explicit Statistics(Keys&&... keys) : Statistics() {
|
||||
// clang-format off
|
||||
Internal::for_each([this](auto&& key) {
|
||||
this->monitor(std::forward<decltype(key)>(key));
|
||||
}, std::forward<Keys>(keys)...);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param range A range of keys to monitor.
|
||||
template <typename Range, typename = Internal::enable_if_range<Range>>
|
||||
explicit Statistics(const Range& range)
|
||||
: Statistics(std::begin(range), std::end(range)) {
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param begin The start iterator of a range of keys to monitor.
|
||||
/// \param end The end iterator of a range of keys to monitor.
|
||||
template <typename Iterator,
|
||||
typename = Internal::enable_if_iterator<Iterator>>
|
||||
Statistics(Iterator begin, Iterator end) : Statistics() {
|
||||
for (; begin != end; ++begin) {
|
||||
monitor(*begin);
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// \param list A list of keys to monitor.
|
||||
Statistics(InitializerList list) // NOLINT(runtime/explicit)
|
||||
: Statistics(list.begin(), list.end()) {
|
||||
}
|
||||
|
||||
/// \returns The total number of accesses (hits + misses) made to the cache.
|
||||
size_t total_accesses() const noexcept {
|
||||
return _total_accesses;
|
||||
}
|
||||
|
||||
/// \returns The total number of hits made to the cache.
|
||||
size_t total_hits() const noexcept {
|
||||
return _total_hits;
|
||||
}
|
||||
|
||||
/// \returns The total number of misses made to the cache.
|
||||
size_t total_misses() const noexcept {
|
||||
return total_accesses() - total_hits();
|
||||
}
|
||||
|
||||
/// \returns The ratio of hits ($\in [0, 1]$) relative to all accesses.
|
||||
double hit_rate() const noexcept {
|
||||
return static_cast<double>(total_hits()) / total_accesses();
|
||||
}
|
||||
|
||||
/// \returns The ratio of misses ($\in [0, 1]$) relative to all accesses.
|
||||
double miss_rate() const noexcept {
|
||||
return 1 - hit_rate();
|
||||
}
|
||||
|
||||
/// \returns The number of hits for the given key.
|
||||
/// \param key The key to retrieve the hits for.
|
||||
/// \throws LRU::UnmonitoredKey if the key was not registered for monitoring.
|
||||
size_t hits_for(const Key& key) const {
|
||||
return stats_for(key).hits;
|
||||
}
|
||||
|
||||
/// \returns The number of misses for the given key.
|
||||
/// \param key The key to retrieve the misses for.
|
||||
/// \throws LRU::UnmonitoredKey if the key was not registered for monitoring.
|
||||
size_t misses_for(const Key& key) const {
|
||||
return stats_for(key).misses;
|
||||
}
|
||||
|
||||
/// \returns The number of accesses (hits + misses) for the given key.
|
||||
/// \param key The key to retrieve the accesses for.
|
||||
/// \throws LRU::UnmonitoredKey if the key was not registered for monitoring.
|
||||
size_t accesses_for(const Key& key) const {
|
||||
return stats_for(key).accesses();
|
||||
}
|
||||
|
||||
/// \returns A `KeyStatistics` object for the given key.
|
||||
/// \param key The key to retrieve the stats for.
|
||||
/// \throws LRU::UnmonitoredKey if the key was not registered for monitoring.
|
||||
const KeyStatistics& stats_for(const Key& key) const {
|
||||
auto iterator = _key_map.find(key);
|
||||
if (iterator == _key_map.end()) {
|
||||
throw LRU::Error::UnmonitoredKey();
|
||||
}
|
||||
|
||||
return iterator->second;
|
||||
}
|
||||
|
||||
/// \copydoc stats_for()
|
||||
const KeyStatistics& operator[](const Key& key) const {
|
||||
return stats_for(key);
|
||||
}
|
||||
|
||||
/// Registers the key for monitoring.
|
||||
///
|
||||
/// If the key was already registered, this is a no-op (most importantly, the
|
||||
/// old statistics are __not__ wiped).
|
||||
///
|
||||
/// \param key The key to register.
|
||||
void monitor(const Key& key) {
|
||||
// emplace does nothing if the key is already present
|
||||
_key_map.emplace(key, KeyStatistics());
|
||||
}
|
||||
|
||||
/// Unregisters the given key from monitoring.
|
||||
///
|
||||
/// \param key The key to unregister.
|
||||
/// \throws LRU::Error::UnmonitoredKey if the key was never registered for
|
||||
/// monitoring.
|
||||
void unmonitor(const Key& key) {
|
||||
auto iterator = _key_map.find(key);
|
||||
if (iterator == _key_map.end()) {
|
||||
throw LRU::Error::UnmonitoredKey();
|
||||
} else {
|
||||
_key_map.erase(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unregisters all keys from monitoring.
|
||||
void unmonitor_all() {
|
||||
_key_map.clear();
|
||||
}
|
||||
|
||||
/// Clears all statistics for the given key, but keeps on monitoring it.
|
||||
///
|
||||
/// \param key The key to reset.
|
||||
void reset_key(const Key& key) {
|
||||
auto iterator = _key_map.find(key);
|
||||
if (iterator == _key_map.end()) {
|
||||
throw LRU::Error::UnmonitoredKey();
|
||||
} else {
|
||||
iterator->second.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the statistics of all keys, but keeps on monitoring it them.
|
||||
void reset_all() {
|
||||
for (auto& pair : _key_map) {
|
||||
_key_map.second.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns True if the given key is currently registered for monitoring,
|
||||
/// else false.
|
||||
/// \param key The key to check for.
|
||||
bool is_monitoring(const Key& key) const noexcept {
|
||||
return _key_map.count(key);
|
||||
}
|
||||
|
||||
/// \returns The number of keys currnetly being monitored.
|
||||
size_t number_of_monitored_keys() const noexcept {
|
||||
return _key_map.size();
|
||||
}
|
||||
|
||||
/// \returns True if currently any keys at all are being monitored, else
|
||||
/// false.
|
||||
bool is_monitoring_keys() const noexcept {
|
||||
return !_key_map.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend class Internal::StatisticsMutator;
|
||||
|
||||
using HitMap = std::unordered_map<Key, KeyStatistics>;
|
||||
|
||||
/// The total number of accesses made for any key.
|
||||
size_t _total_accesses;
|
||||
|
||||
/// The total number of htis made for any key.
|
||||
size_t _total_hits;
|
||||
|
||||
/// The map to keep track of statistics for monitored keys.
|
||||
HitMap _key_map;
|
||||
};
|
||||
|
||||
namespace Lowercase {
|
||||
template <typename... Ts>
|
||||
using statistics = Statistics<Ts...>;
|
||||
} // namespace Lowercase
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_STATISTICS_HPP
|
||||
391
src/3rdParty/lru-cache/include/lru/timed-cache.hpp
vendored
Normal file
391
src/3rdParty/lru-cache/include/lru/timed-cache.hpp
vendored
Normal file
@@ -0,0 +1,391 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_TIMED_CACHE_HPP
|
||||
#define LRU_TIMED_CACHE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <lru/error.hpp>
|
||||
#include <lru/internal/base-cache.hpp>
|
||||
#include <lru/internal/last-accessed.hpp>
|
||||
#include <lru/internal/timed-information.hpp>
|
||||
|
||||
namespace LRU {
|
||||
namespace Internal {
|
||||
template <typename Key,
|
||||
typename Value,
|
||||
typename HashFunction,
|
||||
typename KeyEqual>
|
||||
using TimedCacheBase = BaseCache<Key,
|
||||
Value,
|
||||
Internal::TimedInformation,
|
||||
HashFunction,
|
||||
KeyEqual,
|
||||
Tag::TimedCache>;
|
||||
} // namespace Internal
|
||||
|
||||
|
||||
/// A timed LRU cache.
|
||||
///
|
||||
/// A timed LRU cache behaves like a regular LRU cache, but adds the concept of
|
||||
/// "expiration". The cache now not only remembers the order of insertion, but
|
||||
/// also the point in time at which each element was inserted into the cache.
|
||||
/// The cache then has an additional "time to live" property, which designates
|
||||
/// the time after which a key in the cache is said to be "expired". Once a key
|
||||
/// has expired, the cache will behave as if the key were not present in the
|
||||
/// cache at all and, for example, return false on calls to `contains()` or
|
||||
/// throw on calls to `lookup()`.
|
||||
///
|
||||
/// \see LRU::Cache
|
||||
template <typename Key,
|
||||
typename Value,
|
||||
typename Duration = std::chrono::duration<double, std::milli>,
|
||||
typename HashFunction = std::hash<Key>,
|
||||
typename KeyEqual = std::equal_to<Key>>
|
||||
class TimedCache
|
||||
: public Internal::TimedCacheBase<Key, Value, HashFunction, KeyEqual> {
|
||||
private:
|
||||
using super = Internal::TimedCacheBase<Key, Value, HashFunction, KeyEqual>;
|
||||
using PRIVATE_BASE_CACHE_MEMBERS;
|
||||
|
||||
public:
|
||||
using Tag = LRU::Tag::TimedCache;
|
||||
using PUBLIC_BASE_CACHE_MEMBERS;
|
||||
using super::ordered_end;
|
||||
using super::unordered_end;
|
||||
using typename super::size_t;
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(size_t,const HashFunction&,const KeyEqual&)
|
||||
template <typename AnyDurationType = Duration>
|
||||
explicit TimedCache(const AnyDurationType& time_to_live,
|
||||
size_t capacity = Internal::DEFAULT_CAPACITY,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(capacity, hash, equal)
|
||||
, _time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(size_t,Iterator,Iterator,const
|
||||
/// HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename Iterator, typename AnyDurationType = Duration>
|
||||
TimedCache(const AnyDurationType& time_to_live,
|
||||
size_t capacity,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(capacity, begin, end, hash, equal)
|
||||
, _time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(Iterator,Iterator,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename Iterator, typename AnyDurationType = Duration>
|
||||
TimedCache(const AnyDurationType& time_to_live,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(begin, end, hash, equal)
|
||||
, _time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(Range,size_t,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename Range,
|
||||
typename AnyDurationType = Duration,
|
||||
typename = Internal::enable_if_range<Range>>
|
||||
TimedCache(const AnyDurationType& time_to_live,
|
||||
size_t capacity,
|
||||
Range&& range,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(capacity, std::forward<Range>(range), hash, equal)
|
||||
, _time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(Range,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename Range,
|
||||
typename AnyDurationType = Duration,
|
||||
typename = Internal::enable_if_range<Range>>
|
||||
explicit TimedCache(const AnyDurationType& time_to_live,
|
||||
Range&& range,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual())
|
||||
: super(std::forward<Range>(range), hash, equal)
|
||||
, _time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(InitializerList,const HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename AnyDurationType = Duration>
|
||||
TimedCache(const AnyDurationType& time_to_live,
|
||||
InitializerList list,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual()) // NOLINT(runtime/explicit)
|
||||
: super(list, hash, equal),
|
||||
_time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \param time_to_live The time to live for keys in the cache.
|
||||
/// \copydoc BaseCache::BaseCache(InitializerList,size_t,const
|
||||
/// HashFunction&,const
|
||||
/// KeyEqual&)
|
||||
template <typename AnyDurationType = Duration>
|
||||
TimedCache(const AnyDurationType& time_to_live,
|
||||
size_t capacity,
|
||||
InitializerList list,
|
||||
const HashFunction& hash = HashFunction(),
|
||||
const KeyEqual& equal = KeyEqual()) // NOLINT(runtime/explicit)
|
||||
: super(capacity, list, hash, equal),
|
||||
_time_to_live(std::chrono::duration_cast<Duration>(time_to_live)) {
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::swap
|
||||
void swap(TimedCache& other) noexcept {
|
||||
using std::swap;
|
||||
|
||||
super::swap(other);
|
||||
swap(_time_to_live, other._time_to_live);
|
||||
}
|
||||
|
||||
/// Swaps the contents of one cache with another cache.
|
||||
///
|
||||
/// \param first The first cache to swap.
|
||||
/// \param second The second cache to swap.
|
||||
friend void swap(TimedCache& first, TimedCache& second) noexcept {
|
||||
first.swap(second);
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::find(const Key&)
|
||||
UnorderedIterator find(const Key& key) override {
|
||||
auto iterator = _map.find(key);
|
||||
if (iterator != _map.end()) {
|
||||
if (!_has_expired(iterator->second)) {
|
||||
_register_hit(key, iterator->second.value);
|
||||
_move_to_front(iterator->second.order);
|
||||
_last_accessed = iterator;
|
||||
return {*this, iterator};
|
||||
}
|
||||
}
|
||||
|
||||
_register_miss(key);
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::find(const Key&) const
|
||||
UnorderedConstIterator find(const Key& key) const override {
|
||||
auto iterator = _map.find(key);
|
||||
if (iterator != _map.end()) {
|
||||
if (!_has_expired(iterator->second)) {
|
||||
_register_hit(key, iterator->second.value);
|
||||
_move_to_front(iterator->second.order);
|
||||
_last_accessed = iterator;
|
||||
return {*this, iterator};
|
||||
}
|
||||
}
|
||||
|
||||
_register_miss(key);
|
||||
|
||||
return cend();
|
||||
}
|
||||
|
||||
// no front() because we may have to erase the
|
||||
// entire cache if everything happens to be expired
|
||||
|
||||
/// \returns True if all keys in the cache have expired, else false.
|
||||
bool all_expired() const {
|
||||
// By the laws of predicate logic, any statement about any empty set is true
|
||||
if (is_empty()) return true;
|
||||
|
||||
/// If the most-recently inserted key has expired, all others must have too.
|
||||
auto latest = _map.find(_order.back());
|
||||
return _has_expired(latest->second);
|
||||
}
|
||||
|
||||
/// Erases all expired elements from the cache.
|
||||
///
|
||||
/// \complexity O(N)
|
||||
/// \returns The number of elements erased.
|
||||
size_t clear_expired() {
|
||||
// We have to do a linear search here because linked lists do not
|
||||
// support O(log N) binary searches given their node-based nature.
|
||||
// Either way, in the worst case the entire cache has expired and
|
||||
// we would have to do O(N) erasures.
|
||||
|
||||
if (is_empty()) return 0;
|
||||
|
||||
auto iterator = _order.begin();
|
||||
size_t number_of_erasures = 0;
|
||||
|
||||
while (iterator != _order.end()) {
|
||||
auto map_iterator = _map.find(*iterator);
|
||||
|
||||
// If the current element hasn't expired, also all elements inserted
|
||||
// after will not have, so we can stop.
|
||||
if (!_has_expired(map_iterator->second)) break;
|
||||
|
||||
_erase(map_iterator);
|
||||
|
||||
iterator = _order.begin();
|
||||
number_of_erasures += 1;
|
||||
}
|
||||
|
||||
return number_of_erasures;
|
||||
}
|
||||
|
||||
/// \returns True if the given key is contained in the cache and has expired.
|
||||
/// \param key The key to test expiration for.
|
||||
bool has_expired(const Key& key) const noexcept {
|
||||
auto iterator = _map.find(key);
|
||||
return iterator != _map.end() && _has_expired(iterator->second);
|
||||
}
|
||||
|
||||
/// \returns True if the key pointed to by the iterator has expired.
|
||||
/// \param ordered_iterator The ordered iterator to check.
|
||||
/// \details If this is the end iterator, this method returns false.
|
||||
bool has_expired(OrderedConstIterator ordered_iterator) const noexcept {
|
||||
if (ordered_iterator == ordered_end()) return false;
|
||||
auto iterator = _map.find(ordered_iterator->key());
|
||||
assert(iterator != _map.end());
|
||||
|
||||
return _has_expired(iterator->second);
|
||||
}
|
||||
|
||||
/// \returns True if the key pointed to by the iterator has expired.
|
||||
/// \param unordered_iterator The unordered iterator to check.
|
||||
/// \details If this is the end iterator, this method returns false.
|
||||
bool has_expired(UnorderedConstIterator unordered_iterator) const noexcept {
|
||||
if (unordered_iterator == unordered_end()) return false;
|
||||
assert(unordered_iterator._iterator != _map.end());
|
||||
|
||||
return _has_expired(unordered_iterator._iterator->second);
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::is_valid(UnorderedConstIterator)
|
||||
bool is_valid(UnorderedConstIterator unordered_iterator) const
|
||||
noexcept override {
|
||||
if (!super::is_valid(unordered_iterator)) return false;
|
||||
if (has_expired(unordered_iterator)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::is_valid(OrderedConstIterator)
|
||||
bool is_valid(OrderedConstIterator ordered_iterator) const noexcept override {
|
||||
if (!super::is_valid(ordered_iterator)) return false;
|
||||
if (has_expired(ordered_iterator)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::is_valid(UnorderedConstIterator)
|
||||
/// \throws LRU::Error::KeyExpired if the key pointed to by the iterator has
|
||||
/// expired.
|
||||
void
|
||||
throw_if_invalid(UnorderedConstIterator unordered_iterator) const override {
|
||||
super::throw_if_invalid(unordered_iterator);
|
||||
if (has_expired(unordered_iterator)) {
|
||||
throw LRU::Error::KeyExpired();
|
||||
}
|
||||
}
|
||||
|
||||
/// \copydoc BaseCache::is_valid(OrderedConstIterator)
|
||||
/// \throws LRU::Error::KeyExpired if the key pointed to by the iterator has
|
||||
/// expired.
|
||||
void throw_if_invalid(OrderedConstIterator ordered_iterator) const override {
|
||||
super::throw_if_invalid(ordered_iterator);
|
||||
if (has_expired(ordered_iterator)) {
|
||||
throw LRU::Error::KeyExpired();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using Clock = Internal::Clock;
|
||||
|
||||
/// \returns True if the last accessed object is valid.
|
||||
/// \details Next to performing the base cache's action, this method also
|
||||
/// checks for expiration of the last accessed key.
|
||||
bool _last_accessed_is_ok(const Key& key) const noexcept override {
|
||||
if (!super::_last_accessed_is_ok(key)) return false;
|
||||
return !_has_expired(_last_accessed.information());
|
||||
}
|
||||
|
||||
/// \copydoc _value_for_last_accessed() const
|
||||
Value& _value_for_last_accessed() override {
|
||||
auto& information = _last_accessed.information();
|
||||
if (_has_expired(information)) {
|
||||
throw LRU::Error::KeyExpired();
|
||||
} else {
|
||||
return information.value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to access the last accessed key's value.
|
||||
/// \throws LRU::Error::KeyExpired if the key has expired.
|
||||
/// \returns The value of the last accessed key.
|
||||
const Value& _value_for_last_accessed() const override {
|
||||
const auto& information = _last_accessed.information();
|
||||
if (_has_expired(information)) {
|
||||
throw LRU::Error::KeyExpired();
|
||||
} else {
|
||||
return information.value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a key has expired, given its information.
|
||||
///
|
||||
/// \param information The information to check expiration with.
|
||||
/// \returns True if the key has expired, else false.
|
||||
bool _has_expired(const Information& information) const noexcept {
|
||||
auto elapsed = Clock::now() - information.insertion_time;
|
||||
return std::chrono::duration_cast<Duration>(elapsed) > _time_to_live;
|
||||
}
|
||||
|
||||
/// The duration after which a key is said to be expired.
|
||||
Duration _time_to_live;
|
||||
};
|
||||
|
||||
namespace Lowercase {
|
||||
template <typename... Ts>
|
||||
using timed_cache = TimedCache<Ts...>;
|
||||
} // namespace Lowercase
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_TIMED_CACHE_HPP
|
||||
99
src/3rdParty/lru-cache/include/lru/wrap.hpp
vendored
Normal file
99
src/3rdParty/lru-cache/include/lru/wrap.hpp
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/// The MIT License (MIT)
|
||||
/// Copyright (c) 2016 Peter Goldsborough
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
/// of this software and associated documentation files (the "Software"), to
|
||||
/// deal in the Software without restriction, including without limitation the
|
||||
/// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
/// sell copies of the Software, and to permit persons to whom the Software is
|
||||
/// furnished to do so, subject to the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be included in
|
||||
/// all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
/// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LRU_WRAP_HPP
|
||||
#define LRU_WRAP_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <lru/cache.hpp>
|
||||
#include <lru/internal/hash.hpp>
|
||||
#include <lru/internal/utility.hpp>
|
||||
|
||||
namespace LRU {
|
||||
|
||||
/// Wraps a function with a "shallow" LRU cache.
|
||||
///
|
||||
/// Given a function, this function will return a new function, where
|
||||
/// "top-level" calls are cached. With "top-level" or "shallow", we mean
|
||||
/// that recursive calls to the same function are not cached, since those
|
||||
/// will call the original function symbol, not the wrapped one.
|
||||
///
|
||||
/// \tparam CacheType The cache template class to use.
|
||||
/// \param original_function The function to wrap.
|
||||
/// \param args Any arguments to forward to the cache.
|
||||
/// \returns A new function with a shallow LRU cache.
|
||||
template <typename Function,
|
||||
template <typename...> class CacheType = Cache,
|
||||
typename... Args>
|
||||
auto wrap(Function original_function, Args&&... args) {
|
||||
return [
|
||||
original_function,
|
||||
cache_args = std::forward_as_tuple(std::forward<Args>(args)...)
|
||||
](auto&&... arguments) mutable {
|
||||
using Arguments = std::tuple<std::decay_t<decltype(arguments)>...>;
|
||||
using ReturnType = decltype(
|
||||
original_function(std::forward<decltype(arguments)>(arguments)...));
|
||||
|
||||
static_assert(!std::is_void<ReturnType>::value,
|
||||
"Return type of wrapped function must not be void");
|
||||
|
||||
static auto cache =
|
||||
Internal::construct_from_tuple<CacheType<Arguments, ReturnType>>(
|
||||
cache_args);
|
||||
|
||||
auto key = std::make_tuple(arguments...);
|
||||
auto iterator = cache.find(key);
|
||||
|
||||
if (iterator != cache.end()) {
|
||||
return iterator->second;
|
||||
}
|
||||
|
||||
auto value =
|
||||
original_function(std::forward<decltype(arguments)>(arguments)...);
|
||||
cache.emplace(key, value);
|
||||
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
/// Wraps a function with a "shallow" LRU timed cache.
|
||||
///
|
||||
/// Given a function, this function will return a new function, where
|
||||
/// "top-level" calls are cached. With "top-level" or "shallow", we mean
|
||||
/// that recursive calls to the same function are not cached, since those
|
||||
/// will call the original function symbol, not the wrapped one.
|
||||
///
|
||||
/// \param original_function The function to wrap.
|
||||
/// \param args Any arguments to forward to the cache.
|
||||
/// \returns A new function with a shallow LRU cache.
|
||||
template <typename Function, typename Duration, typename... Args>
|
||||
auto timed_wrap(Function original_function, Duration duration, Args&&... args) {
|
||||
return wrap<Function, TimedCache>(
|
||||
original_function, duration, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace LRU
|
||||
|
||||
#endif // LRU_WRAP_HPP
|
||||
Reference in New Issue
Block a user