blob: 7874eef6d772152a653890e65865153dba295813 [file] [log] [blame]
// 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 <algorithm>
#include <memory>
#include <utility>
#include <vector>
#include "table/internal_iterator.h"
namespace rocksdb {
// PinnedIteratorsManager will be notified whenever we need to pin an Iterator
// and it will be responsible for deleting pinned Iterators when they are
// not needed anymore.
class PinnedIteratorsManager : public Cleanable {
public:
PinnedIteratorsManager() : pinning_enabled(false) {}
~PinnedIteratorsManager() {
if (pinning_enabled) {
ReleasePinnedData();
}
}
// Enable Iterators pinning
void StartPinning() {
assert(pinning_enabled == false);
pinning_enabled = true;
}
// Is pinning enabled ?
bool PinningEnabled() { return pinning_enabled; }
// Take ownership of iter and delete it when ReleasePinnedData() is called
void PinIterator(InternalIterator* iter, bool arena = false) {
if (arena) {
PinPtr(iter, &PinnedIteratorsManager::ReleaseArenaInternalIterator);
} else {
PinPtr(iter, &PinnedIteratorsManager::ReleaseInternalIterator);
}
}
typedef void (*ReleaseFunction)(void* arg1);
void PinPtr(void* ptr, ReleaseFunction release_func) {
assert(pinning_enabled);
if (ptr == nullptr) {
return;
}
pinned_ptrs_.emplace_back(ptr, release_func);
}
// Release pinned Iterators
inline void ReleasePinnedData() {
assert(pinning_enabled == true);
pinning_enabled = false;
// Remove duplicate pointers
std::sort(pinned_ptrs_.begin(), pinned_ptrs_.end());
auto unique_end = std::unique(pinned_ptrs_.begin(), pinned_ptrs_.end());
for (auto i = pinned_ptrs_.begin(); i != unique_end; ++i) {
void* ptr = i->first;
ReleaseFunction release_func = i->second;
release_func(ptr);
}
pinned_ptrs_.clear();
// Also do cleanups from the base Cleanable
Cleanable::Reset();
}
private:
static void ReleaseInternalIterator(void* ptr) {
delete reinterpret_cast<InternalIterator*>(ptr);
}
static void ReleaseArenaInternalIterator(void* ptr) {
reinterpret_cast<InternalIterator*>(ptr)->~InternalIterator();
}
bool pinning_enabled;
std::vector<std::pair<void*, ReleaseFunction>> pinned_ptrs_;
};
} // namespace rocksdb