diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/include/llvm/ADT/IntrusiveRefCntPtr.h | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/include/llvm/ADT/IntrusiveRefCntPtr.h')
-rw-r--r-- | contrib/libs/llvm14/include/llvm/ADT/IntrusiveRefCntPtr.h | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/include/llvm/ADT/IntrusiveRefCntPtr.h b/contrib/libs/llvm14/include/llvm/ADT/IntrusiveRefCntPtr.h new file mode 100644 index 0000000000..ba7d8498b1 --- /dev/null +++ b/contrib/libs/llvm14/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -0,0 +1,321 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the RefCountedBase, ThreadSafeRefCountedBase, and +/// IntrusiveRefCntPtr classes. +/// +/// IntrusiveRefCntPtr is a smart pointer to an object which maintains a +/// reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a +/// refcount member variable and methods for updating the refcount. An object +/// that inherits from (ThreadSafe)RefCountedBase deletes itself when its +/// refcount hits zero. +/// +/// For example: +/// +/// ``` +/// class MyClass : public RefCountedBase<MyClass> {}; +/// +/// void foo() { +/// // Constructing an IntrusiveRefCntPtr increases the pointee's refcount +/// // by 1 (from 0 in this case). +/// IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass()); +/// +/// // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. +/// IntrusiveRefCntPtr<MyClass> Ptr2(Ptr1); +/// +/// // Constructing an IntrusiveRefCntPtr has no effect on the object's +/// // refcount. After a move, the moved-from pointer is null. +/// IntrusiveRefCntPtr<MyClass> Ptr3(std::move(Ptr1)); +/// assert(Ptr1 == nullptr); +/// +/// // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1. +/// Ptr2.reset(); +/// +/// // The object deletes itself when we return from the function, because +/// // Ptr3's destructor decrements its refcount to 0. +/// } +/// ``` +/// +/// You can use IntrusiveRefCntPtr with isa<T>(), dyn_cast<T>(), etc.: +/// +/// ``` +/// IntrusiveRefCntPtr<MyClass> Ptr(new MyClass()); +/// OtherClass *Other = dyn_cast<OtherClass>(Ptr); // Ptr.get() not required +/// ``` +/// +/// IntrusiveRefCntPtr works with any class that +/// +/// - inherits from (ThreadSafe)RefCountedBase, +/// - has Retain() and Release() methods, or +/// - specializes IntrusiveRefCntPtrInfo. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H +#define LLVM_ADT_INTRUSIVEREFCNTPTR_H + +#include <atomic> +#include <cassert> +#include <cstddef> +#include <memory> + +namespace llvm { + +/// A CRTP mixin class that adds reference counting to a type. +/// +/// The lifetime of an object which inherits from RefCountedBase is managed by +/// calls to Release() and Retain(), which increment and decrement the object's +/// refcount, respectively. When a Release() call decrements the refcount to 0, +/// the object deletes itself. +template <class Derived> class RefCountedBase { + mutable unsigned RefCount = 0; + +protected: + RefCountedBase() = default; + RefCountedBase(const RefCountedBase &) {} + RefCountedBase &operator=(const RefCountedBase &) = delete; + +#ifndef NDEBUG + ~RefCountedBase() { + assert(RefCount == 0 && + "Destruction occured when there are still references to this."); + } +#else + // Default the destructor in release builds, A trivial destructor may enable + // better codegen. + ~RefCountedBase() = default; +#endif + +public: + void Retain() const { ++RefCount; } + + void Release() const { + assert(RefCount > 0 && "Reference count is already zero."); + if (--RefCount == 0) + delete static_cast<const Derived *>(this); + } +}; + +/// A thread-safe version of \c RefCountedBase. +template <class Derived> class ThreadSafeRefCountedBase { + mutable std::atomic<int> RefCount{0}; + +protected: + ThreadSafeRefCountedBase() = default; + ThreadSafeRefCountedBase(const ThreadSafeRefCountedBase &) {} + ThreadSafeRefCountedBase & + operator=(const ThreadSafeRefCountedBase &) = delete; + +#ifndef NDEBUG + ~ThreadSafeRefCountedBase() { + assert(RefCount == 0 && + "Destruction occured when there are still references to this."); + } +#else + // Default the destructor in release builds, A trivial destructor may enable + // better codegen. + ~ThreadSafeRefCountedBase() = default; +#endif + +public: + void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } + + void Release() const { + int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1; + assert(NewRefCount >= 0 && "Reference count was already zero."); + if (NewRefCount == 0) + delete static_cast<const Derived *>(this); + } +}; + +/// Class you can specialize to provide custom retain/release functionality for +/// a type. +/// +/// Usually specializing this class is not necessary, as IntrusiveRefCntPtr +/// works with any type which defines Retain() and Release() functions -- you +/// can define those functions yourself if RefCountedBase doesn't work for you. +/// +/// One case when you might want to specialize this type is if you have +/// - Foo.h defines type Foo and includes Bar.h, and +/// - Bar.h uses IntrusiveRefCntPtr<Foo> in inline functions. +/// +/// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in +/// the declaration of Foo. Without the declaration of Foo, normally Bar.h +/// wouldn't be able to use IntrusiveRefCntPtr<Foo>, which wants to call +/// T::Retain and T::Release. +/// +/// To resolve this, Bar.h could include a third header, FooFwd.h, which +/// forward-declares Foo and specializes IntrusiveRefCntPtrInfo<Foo>. Then +/// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any +/// functions on Foo itself, because Foo would be an incomplete type. +template <typename T> struct IntrusiveRefCntPtrInfo { + static void retain(T *obj) { obj->Retain(); } + static void release(T *obj) { obj->Release(); } +}; + +/// A smart pointer to a reference-counted object that inherits from +/// RefCountedBase or ThreadSafeRefCountedBase. +/// +/// This class increments its pointee's reference count when it is created, and +/// decrements its refcount when it's destroyed (or is changed to point to a +/// different object). +template <typename T> class IntrusiveRefCntPtr { + T *Obj = nullptr; + +public: + using element_type = T; + + explicit IntrusiveRefCntPtr() = default; + IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); } + IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); } + IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; } + + template <class X, + std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true> + IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> S) : Obj(S.get()) { + S.Obj = nullptr; + } + + template <class X, + std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true> + IntrusiveRefCntPtr(std::unique_ptr<X> S) : Obj(S.release()) { + retain(); + } + + ~IntrusiveRefCntPtr() { release(); } + + IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) { + swap(S); + return *this; + } + + T &operator*() const { return *Obj; } + T *operator->() const { return Obj; } + T *get() const { return Obj; } + explicit operator bool() const { return Obj; } + + void swap(IntrusiveRefCntPtr &other) { + T *tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; + } + + void reset() { + release(); + Obj = nullptr; + } + + void resetWithoutRelease() { Obj = nullptr; } + +private: + void retain() { + if (Obj) + IntrusiveRefCntPtrInfo<T>::retain(Obj); + } + + void release() { + if (Obj) + IntrusiveRefCntPtrInfo<T>::release(Obj); + } + + template <typename X> friend class IntrusiveRefCntPtr; +}; + +template <class T, class U> +inline bool operator==(const IntrusiveRefCntPtr<T> &A, + const IntrusiveRefCntPtr<U> &B) { + return A.get() == B.get(); +} + +template <class T, class U> +inline bool operator!=(const IntrusiveRefCntPtr<T> &A, + const IntrusiveRefCntPtr<U> &B) { + return A.get() != B.get(); +} + +template <class T, class U> +inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) { + return A.get() == B; +} + +template <class T, class U> +inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) { + return A.get() != B; +} + +template <class T, class U> +inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) { + return A == B.get(); +} + +template <class T, class U> +inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) { + return A != B.get(); +} + +template <class T> +bool operator==(std::nullptr_t, const IntrusiveRefCntPtr<T> &B) { + return !B; +} + +template <class T> +bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return B == A; +} + +template <class T> +bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !(A == B); +} + +template <class T> +bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return !(A == B); +} + +// Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from +// Casting.h. +template <typename From> struct simplify_type; + +template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> { + using SimpleType = T *; + + static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) { + return Val.get(); + } +}; + +template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> { + using SimpleType = /*const*/ T *; + + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) { + return Val.get(); + } +}; + +/// Factory function for creating intrusive ref counted pointers. +template <typename T, typename... Args> +IntrusiveRefCntPtr<T> makeIntrusiveRefCnt(Args &&...A) { + return IntrusiveRefCntPtr<T>(new T(std::forward<Args>(A)...)); +} + +} // end namespace llvm + +#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |