aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/memory/new.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/memory/new.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/memory/new.h')
-rw-r--r--library/cpp/yt/memory/new.h127
1 files changed, 127 insertions, 0 deletions
diff --git a/library/cpp/yt/memory/new.h b/library/cpp/yt/memory/new.h
new file mode 100644
index 0000000000..2db45e0465
--- /dev/null
+++ b/library/cpp/yt/memory/new.h
@@ -0,0 +1,127 @@
+#pragma once
+
+#include "intrusive_ptr.h"
+#include "ref_tracked.h"
+
+#include <library/cpp/yt/misc/source_location.h>
+
+#include <util/system/defaults.h>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+/*!
+ * \defgroup yt_new New<T> safe smart pointer constructors
+ * \ingroup yt_new
+ *
+ * This is collection of safe smart pointer constructors.
+ *
+ * \page yt_new_rationale Rationale
+ * New<T> function family was designed to prevent the following problem.
+ * Consider the following piece of code.
+ *
+ * \code
+ * class TFoo
+ * : public virtual TRefCounted
+ * {
+ * public:
+ * TFoo();
+ * };
+ *
+ * typedef TIntrusivePtr<TFoo> TFooPtr;
+ *
+ * void RegisterObject(TFooPtr foo)
+ * {
+ * ...
+ * }
+ *
+ * TFoo::TFoo()
+ * {
+ * // ... do something before
+ * RegisterObject(this);
+ * // ... do something after
+ * }
+ * \endcode
+ *
+ * What will happen on <tt>new TFoo()</tt> construction? After memory allocation
+ * the reference counter for newly created instance would be initialized to zero.
+ * Afterwards, the control goes to TFoo constructor. To invoke
+ * <tt>RegisterObject</tt> a new temporary smart pointer to the current instance
+ * have to be created effectively incrementing the reference counter (now one).
+ * After <tt>RegisterObject</tt> returns the control to the constructor
+ * the temporary pointer is destroyed effectively decrementing the reference
+ * counter to zero hence triggering object destruction during its initialization.
+ *
+ * To avoid this undefined behavior <tt>New<T></tt> was introduced.
+ * <tt>New<T></tt> holds a fake
+ * reference to the object during its construction effectively preventing
+ * premature destruction.
+ *
+ * \note An initialization like <tt>TIntrusivePtr&lt;T&gt; p = new T()</tt>
+ * would result in a dangling reference due to internals of #New<T> and
+ * #TRefCountedBase.
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T, class = void>
+struct THasAllocator
+{
+ using TFalse = void;
+};
+
+template <class T>
+struct THasAllocator<T, std::void_t<typename T::TAllocator>>
+{
+ using TTrue = void;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Allocates a new instance of |T|.
+template <class T, class... As, class = typename THasAllocator<T>::TFalse>
+TIntrusivePtr<T> New(As&&... args);
+
+template <class T, class... As, class = typename THasAllocator<T>::TTrue>
+TIntrusivePtr<T> New(typename T::TAllocator* allocator, As&&... args);
+
+//! Allocates an instance of |T| with additional storage of #extraSpaceSize bytes.
+template <class T, class... As, class = typename THasAllocator<T>::TFalse>
+TIntrusivePtr<T> NewWithExtraSpace(size_t extraSpaceSize, As&&... args);
+
+template <class T, class... As, class = typename THasAllocator<T>::TTrue>
+TIntrusivePtr<T> NewWithExtraSpace(typename T::TAllocator* allocator, size_t extraSpaceSize, As&&... args);
+
+//! Allocates a new instance of |T| with user deleter.
+template <class T, class TDeleter, class... As>
+TIntrusivePtr<T> NewWithDelete(const TDeleter& deleter, As&&... args);
+
+//! Allocates a new instance of |T|.
+//! The allocation is additionally marked with #location.
+template <class T, class TTag, int Counter, class... As>
+TIntrusivePtr<T> NewWithLocation(const TSourceLocation& location, As&&... args);
+
+//! Enables calling #New and co for types with private ctors.
+#define DECLARE_NEW_FRIEND() \
+ template <class DECLARE_NEW_FRIEND_T> \
+ friend struct NYT::TRefCountedWrapper;
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! CRTP mixin enabling access to instance's extra space.
+template <class T>
+class TWithExtraSpace
+{
+protected:
+ const void* GetExtraSpacePtr() const;
+ void* GetExtraSpacePtr();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+#define NEW_INL_H_
+#include "new-inl.h"
+#undef NEW_INL_H_