pinned_iterators_manager.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. #pragma once
  7. #include <algorithm>
  8. #include <memory>
  9. #include <utility>
  10. #include <vector>
  11. #include "table/internal_iterator.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. // PinnedIteratorsManager will be notified whenever we need to pin an Iterator
  14. // and it will be responsible for deleting pinned Iterators when they are
  15. // not needed anymore.
  16. class PinnedIteratorsManager : public Cleanable {
  17. public:
  18. PinnedIteratorsManager() : pinning_enabled(false) {}
  19. ~PinnedIteratorsManager() {
  20. if (pinning_enabled) {
  21. ReleasePinnedData();
  22. }
  23. }
  24. // Move constructor and move assignment is allowed.
  25. PinnedIteratorsManager(PinnedIteratorsManager&& other) noexcept = default;
  26. PinnedIteratorsManager& operator=(PinnedIteratorsManager&& other) noexcept =
  27. default;
  28. // Enable Iterators pinning
  29. void StartPinning() {
  30. assert(pinning_enabled == false);
  31. pinning_enabled = true;
  32. }
  33. // Is pinning enabled ?
  34. bool PinningEnabled() { return pinning_enabled; }
  35. // Take ownership of iter and delete it when ReleasePinnedData() is called
  36. void PinIterator(InternalIterator* iter, bool arena = false) {
  37. if (arena) {
  38. PinPtr(iter, &PinnedIteratorsManager::ReleaseArenaInternalIterator);
  39. } else {
  40. PinPtr(iter, &PinnedIteratorsManager::ReleaseInternalIterator);
  41. }
  42. }
  43. using ReleaseFunction = void (*)(void* arg1);
  44. void PinPtr(void* ptr, ReleaseFunction release_func) {
  45. assert(pinning_enabled);
  46. if (ptr == nullptr) {
  47. return;
  48. }
  49. pinned_ptrs_.emplace_back(ptr, release_func);
  50. }
  51. // Release pinned Iterators
  52. inline void ReleasePinnedData() {
  53. assert(pinning_enabled == true);
  54. pinning_enabled = false;
  55. // Remove duplicate pointers
  56. std::sort(pinned_ptrs_.begin(), pinned_ptrs_.end());
  57. auto unique_end = std::unique(pinned_ptrs_.begin(), pinned_ptrs_.end());
  58. for (auto i = pinned_ptrs_.begin(); i != unique_end; ++i) {
  59. void* ptr = i->first;
  60. ReleaseFunction release_func = i->second;
  61. release_func(ptr);
  62. }
  63. pinned_ptrs_.clear();
  64. // Also do cleanups from the base Cleanable
  65. Cleanable::Reset();
  66. }
  67. private:
  68. static void ReleaseInternalIterator(void* ptr) {
  69. delete static_cast<InternalIterator*>(ptr);
  70. }
  71. static void ReleaseArenaInternalIterator(void* ptr) {
  72. static_cast<InternalIterator*>(ptr)->~InternalIterator();
  73. }
  74. bool pinning_enabled;
  75. std::vector<std::pair<void*, ReleaseFunction>> pinned_ptrs_;
  76. };
  77. } // namespace ROCKSDB_NAMESPACE