mirror of https://github.com/facebook/rocksdb.git
146 lines
3.8 KiB
C++
146 lines
3.8 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
#pragma once
|
|
|
|
#include <cassert>
|
|
|
|
#include "rocksdb/cache.h"
|
|
#include "rocksdb/rocksdb_namespace.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
// Returns the cached value given a cache handle.
|
|
template <typename T>
|
|
T* GetFromCacheHandle(Cache* cache, Cache::Handle* handle) {
|
|
assert(cache);
|
|
assert(handle);
|
|
|
|
return static_cast<T*>(cache->Value(handle));
|
|
}
|
|
|
|
// Simple generic deleter for Cache (to be used with Cache::Insert).
|
|
template <typename T>
|
|
void DeleteCacheEntry(const Slice& /* key */, void* value) {
|
|
delete static_cast<T*>(value);
|
|
}
|
|
|
|
// Turns a T* into a Slice so it can be used as a key with Cache.
|
|
template <typename T>
|
|
Slice GetSlice(const T* t) {
|
|
return Slice(reinterpret_cast<const char*>(t), sizeof(T));
|
|
}
|
|
|
|
// Generic resource management object for cache handles that releases the handle
|
|
// when destroyed. Has unique ownership of the handle, so copying it is not
|
|
// allowed, while moving it transfers ownership.
|
|
template <typename T>
|
|
class CacheHandleGuard {
|
|
public:
|
|
CacheHandleGuard() = default;
|
|
|
|
CacheHandleGuard(Cache* cache, Cache::Handle* handle)
|
|
: cache_(cache),
|
|
handle_(handle),
|
|
value_(GetFromCacheHandle<T>(cache, handle)) {
|
|
assert(cache_ && handle_ && value_);
|
|
}
|
|
|
|
CacheHandleGuard(const CacheHandleGuard&) = delete;
|
|
CacheHandleGuard& operator=(const CacheHandleGuard&) = delete;
|
|
|
|
CacheHandleGuard(CacheHandleGuard&& rhs) noexcept
|
|
: cache_(rhs.cache_), handle_(rhs.handle_), value_(rhs.value_) {
|
|
assert((!cache_ && !handle_ && !value_) || (cache_ && handle_ && value_));
|
|
|
|
rhs.ResetFields();
|
|
}
|
|
|
|
CacheHandleGuard& operator=(CacheHandleGuard&& rhs) noexcept {
|
|
if (this == &rhs) {
|
|
return *this;
|
|
}
|
|
|
|
ReleaseHandle();
|
|
|
|
cache_ = rhs.cache_;
|
|
handle_ = rhs.handle_;
|
|
value_ = rhs.value_;
|
|
|
|
assert((!cache_ && !handle_ && !value_) || (cache_ && handle_ && value_));
|
|
|
|
rhs.ResetFields();
|
|
|
|
return *this;
|
|
}
|
|
|
|
~CacheHandleGuard() { ReleaseHandle(); }
|
|
|
|
bool IsEmpty() const { return !handle_; }
|
|
|
|
Cache* GetCache() const { return cache_; }
|
|
Cache::Handle* GetCacheHandle() const { return handle_; }
|
|
T* GetValue() const { return value_; }
|
|
|
|
void TransferTo(Cleanable* cleanable) {
|
|
if (cleanable) {
|
|
if (handle_ != nullptr) {
|
|
assert(cache_);
|
|
cleanable->RegisterCleanup(&ReleaseCacheHandle, cache_, handle_);
|
|
}
|
|
}
|
|
ResetFields();
|
|
}
|
|
|
|
void Reset() {
|
|
ReleaseHandle();
|
|
ResetFields();
|
|
}
|
|
|
|
private:
|
|
void ReleaseHandle() {
|
|
if (IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
assert(cache_);
|
|
cache_->Release(handle_);
|
|
}
|
|
|
|
void ResetFields() {
|
|
cache_ = nullptr;
|
|
handle_ = nullptr;
|
|
value_ = nullptr;
|
|
}
|
|
|
|
static void ReleaseCacheHandle(void* arg1, void* arg2) {
|
|
Cache* const cache = static_cast<Cache*>(arg1);
|
|
assert(cache);
|
|
|
|
Cache::Handle* const cache_handle = static_cast<Cache::Handle*>(arg2);
|
|
assert(cache_handle);
|
|
|
|
cache->Release(cache_handle);
|
|
}
|
|
|
|
private:
|
|
Cache* cache_ = nullptr;
|
|
Cache::Handle* handle_ = nullptr;
|
|
T* value_ = nullptr;
|
|
};
|
|
|
|
// Build an aliasing shared_ptr that keeps `handle` in cache while there
|
|
// are references, but the pointer is to the value for that cache entry,
|
|
// which must be of type T. This is copyable, unlike CacheHandleGuard, but
|
|
// does not provide access to caching details.
|
|
template <typename T>
|
|
std::shared_ptr<T> MakeSharedCacheHandleGuard(Cache* cache,
|
|
Cache::Handle* handle) {
|
|
auto wrapper = std::make_shared<CacheHandleGuard<T>>(cache, handle);
|
|
return std::shared_ptr<T>(wrapper, static_cast<T*>(cache->Value(handle)));
|
|
}
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|