You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rust-rocksdb/include/rocksdb/cleanable.h

129 lines
4.3 KiB

// 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).
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#pragma once
#include "rocksdb/rocksdb_namespace.h"
namespace ROCKSDB_NAMESPACE {
class Cleanable {
public:
Cleanable();
// No copy constructor and copy assignment allowed.
Cleanable(Cleanable&) = delete;
Cleanable& operator=(Cleanable&) = delete;
// Executes all the registered cleanups
~Cleanable();
// Move constructor and move assignment is allowed.
Cleanable(Cleanable&&) noexcept;
Cleanable& operator=(Cleanable&&) noexcept;
// Clients are allowed to register function/arg1/arg2 triples that
// will be invoked when this iterator is destroyed.
//
// Note that unlike all of the preceding methods, this method is
// not abstract and therefore clients should not override it.
using CleanupFunction = void (*)(void* arg1, void* arg2);
// Add another Cleanup to the list
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
// Move the cleanups owned by this Cleanable to another Cleanable, adding to
// any existing cleanups it has
void DelegateCleanupsTo(Cleanable* other);
// DoCleanup and also resets the pointers for reuse
inline void Reset() {
DoCleanup();
cleanup_.function = nullptr;
cleanup_.next = nullptr;
}
inline bool HasCleanups() { return cleanup_.function != nullptr; }
protected:
struct Cleanup {
CleanupFunction function;
void* arg1;
void* arg2;
Cleanup* next;
};
Cleanup cleanup_;
// It also becomes the owner of c
void RegisterCleanup(Cleanup* c);
private:
// Performs all the cleanups. It does not reset the pointers. Making it
// private
// to prevent misuse
inline void DoCleanup() {
if (cleanup_.function != nullptr) {
(*cleanup_.function)(cleanup_.arg1, cleanup_.arg2);
for (Cleanup* c = cleanup_.next; c != nullptr;) {
(*c->function)(c->arg1, c->arg2);
Cleanup* next = c->next;
delete c;
c = next;
}
}
}
};
// A copyable, reference-counted pointer to a simple Cleanable that only
// performs registered cleanups after all copies are destroy. This is like
// shared_ptr<Cleanable> but works more efficiently with wrapping the pointer
// in an outer Cleanable (see RegisterCopyWith() and MoveAsCleanupTo()).
// WARNING: if you create a reference cycle, for example:
// SharedCleanablePtr scp;
// scp.Allocate();
// scp.RegisterCopyWith(&*scp);
// It will prevent cleanups from ever happening!
class SharedCleanablePtr {
public:
// Empy/null pointer
SharedCleanablePtr() {}
// Copy and move constructors and assignment
SharedCleanablePtr(const SharedCleanablePtr& from);
SharedCleanablePtr(SharedCleanablePtr&& from) noexcept;
SharedCleanablePtr& operator=(const SharedCleanablePtr& from);
SharedCleanablePtr& operator=(SharedCleanablePtr&& from) noexcept;
// Destructor (decrement refcount if non-null)
~SharedCleanablePtr();
// Create a new simple Cleanable and make this assign this pointer to it.
// (Reset()s first if necessary.)
void Allocate();
// Reset to empty/null (decrement refcount if previously non-null)
void Reset();
// Dereference to pointed-to Cleanable
Cleanable& operator*();
Cleanable* operator->();
// Get as raw pointer to Cleanable
Cleanable* get();
// Creates a (virtual) copy of this SharedCleanablePtr and registers its
// destruction with target, so that the cleanups registered with the
// Cleanable pointed to by this can only happen after the cleanups in the
// target Cleanable are run.
// No-op if this is empty (nullptr).
void RegisterCopyWith(Cleanable* target);
// Moves (virtually) this shared pointer to a new cleanup in the target.
// This is essentilly a move semantics version of RegisterCopyWith(), for
// performance optimization. No-op if this is empty (nullptr).
void MoveAsCleanupTo(Cleanable* target);
private:
struct Impl;
Impl* ptr_ = nullptr;
};
} // namespace ROCKSDB_NAMESPACE