1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
#pragma once
#include <c10/macros/Export.h>
#include <c10/util/UniqueVoidPtr.h>
#include <atomic>
#include <cstdint>
#include <memory>
#include <shared_mutex>
#include <variant>
namespace c10::impl::cow {
// A COWDeleterContext object is used as the `ctx` argument for DataPtr
// to implement a Copy-on-write (COW) DataPtr.
class C10_API COWDeleterContext {
public:
// Creates an instance, holding the pair of data and original
// deleter.
//
// Note that the deleter will only be called in our destructor if
// the last reference to this goes away without getting
// materialized.
explicit COWDeleterContext(std::unique_ptr<void, DeleterFnPtr> data);
// Increments the current refcount.
void increment_refcount();
// See README.md in this directory to understand the locking
// strategy.
// Represents a reference to the context.
//
// This is returned by decrement_refcount to allow the caller to
// copy the data under the shared lock.
using NotLastReference = std::shared_lock<std::shared_mutex>;
// Represents the last reference to the context.
//
// This will be returned by decrement_refcount when it is the last
// reference remaining and after any pending copies have completed.
using LastReference = std::unique_ptr<void, DeleterFnPtr>;
// Decrements the refcount, returning a handle indicating what to
// do with it.
std::variant<NotLastReference, LastReference> decrement_refcount();
private:
// The destructor is hidden, this should only ever be used within
// UniqueVoidPtr using cow::delete_context as the deleter.
~COWDeleterContext();
std::shared_mutex mutex_;
std::unique_ptr<void, DeleterFnPtr> data_;
std::atomic<std::int64_t> refcount_ = 1;
};
// `cow_deleter` is used as the `ctx_deleter` for DataPtr to implement a COW
// DataPtr.
//
// Warning: This should only be called on a pointer to a COWDeleterContext that
// was allocated on the heap with `new`, because when the refcount reaches 0,
// the context is deleted with `delete`.
C10_API void cow_deleter(void* ctx);
} // namespace c10::impl::cow
|