ref.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. #pragma once
  2. #include "new.h"
  3. #include "range.h"
  4. #include "shared_range.h"
  5. #include <library/cpp/yt/string/format.h>
  6. #include <type_traits>
  7. namespace NYT {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. // Forward declaration.
  10. class TBlob;
  11. //! A non-owning reference to a range of memory.
  12. class TRef
  13. : public TRange<char>
  14. {
  15. public:
  16. //! Creates a null TRef.
  17. TRef() = default;
  18. //! Creates a TRef for a given block of memory.
  19. TRef(const void* data, size_t size);
  20. //! Creates a TRef for a given range of memory.
  21. TRef(const void* begin, const void* end);
  22. //! Creates an empty TRef.
  23. static TRef MakeEmpty();
  24. //! Creates a non-owning TRef for a given blob.
  25. static TRef FromBlob(const TBlob& blob);
  26. //! Creates a non-owning TRef for a given string.
  27. static TRef FromString(const TString& str);
  28. //! Creates a non-owning TRef for a given std::string.
  29. static TRef FromString(const std::string& str);
  30. //! Creates a non-owning TRef for a given stringbuf.
  31. static TRef FromStringBuf(TStringBuf strBuf);
  32. //! Creates a non-owning TRef for a given pod structure.
  33. template <class T>
  34. static TRef FromPod(const T& data);
  35. //! Converts to TStringBuf.
  36. TStringBuf ToStringBuf() const;
  37. //! Creates a TRef for a part of existing range.
  38. TRef Slice(size_t startOffset, size_t endOffset) const;
  39. //! Compares the content for bitwise equality.
  40. static bool AreBitwiseEqual(TRef lhs, TRef rhs);
  41. };
  42. ////////////////////////////////////////////////////////////////////////////////
  43. //! A non-owning reference to a mutable range of memory.
  44. //! Use with caution :)
  45. class TMutableRef
  46. : public TMutableRange<char>
  47. {
  48. public:
  49. //! Creates a null TMutableRef.
  50. //! Note empty TMutableRef is not the same as null TMutableRef.
  51. //! `operator bool` can be used to check if ref is nonnull.
  52. TMutableRef() = default;
  53. //! Creates a TMutableRef for a given block of memory.
  54. TMutableRef(void* data, size_t size);
  55. //! Creates a TMutableRef for a given range of memory.
  56. TMutableRef(void* begin, void* end);
  57. //! Creates an empty TMutableRef.
  58. static TMutableRef MakeEmpty();
  59. //! Converts a TMutableRef to TRef.
  60. operator TRef() const;
  61. //! Creates a non-owning TMutableRef for a given blob.
  62. static TMutableRef FromBlob(TBlob& blob);
  63. //! Creates a non-owning TMutableRef for a given pod structure.
  64. template <class T>
  65. static TMutableRef FromPod(T& data);
  66. //! Creates a non-owning TMutableRef for a given string.
  67. //! Ensures that the string is not shared.
  68. static TMutableRef FromString(TString& str);
  69. //! Creates a TMutableRef for a part of existing range.
  70. TMutableRef Slice(size_t startOffset, size_t endOffset) const;
  71. };
  72. ////////////////////////////////////////////////////////////////////////////////
  73. //! Default tag type for memory blocks allocated via TSharedRef.
  74. /*!
  75. * Each newly allocated TSharedRef blob is associated with a tag type
  76. * that appears in ref-counted statistics.
  77. */
  78. struct TDefaultSharedBlobTag { };
  79. //! A reference to a range of memory with shared ownership.
  80. class TSharedRef
  81. : public TSharedRange<char>
  82. {
  83. public:
  84. //! Creates a null TSharedRef.
  85. TSharedRef() = default;
  86. //! Creates a TSharedRef with a given holder.
  87. TSharedRef(TRef ref, TSharedRangeHolderPtr holder);
  88. //! Creates a TSharedRef from a pointer and length.
  89. TSharedRef(const void* data, size_t length, TSharedRangeHolderPtr holder);
  90. //! Creates a TSharedRef from a range.
  91. TSharedRef(const void* begin, const void* end, TSharedRangeHolderPtr holder);
  92. //! Creates an empty TSharedRef.
  93. static TSharedRef MakeEmpty();
  94. //! Converts a TSharedRef to TRef.
  95. operator TRef() const;
  96. //! Creates a TSharedRef from a string.
  97. //! Since strings are ref-counted, no data is copied.
  98. //! The memory is marked with a given tag.
  99. template <class TTag>
  100. static TSharedRef FromString(TString str);
  101. //! Creates a TSharedRef from a string.
  102. //! Since strings are ref-counted, no data is copied.
  103. //! The memory is marked with TDefaultSharedBlobTag.
  104. static TSharedRef FromString(TString str);
  105. //! Creates a TSharedRef reference from a string.
  106. //! Since strings are ref-counted, no data is copied.
  107. //! The memory is marked with a given tag.
  108. static TSharedRef FromString(TString str, TRefCountedTypeCookie tagCookie);
  109. //! Creates a TSharedRef for a given blob taking ownership of its content.
  110. static TSharedRef FromBlob(TBlob&& blob);
  111. //! Converts to TStringBuf.
  112. TStringBuf ToStringBuf() const;
  113. //! Creates a copy of a given TRef.
  114. //! The memory is marked with a given tag.
  115. static TSharedRef MakeCopy(TRef ref, TRefCountedTypeCookie tagCookie);
  116. //! Creates a copy of a given TRef.
  117. //! The memory is marked with a given tag.
  118. template <class TTag>
  119. static TSharedRef MakeCopy(TRef ref);
  120. //! Creates a TSharedRef for a part of existing range.
  121. TSharedRef Slice(size_t startOffset, size_t endOffset) const;
  122. //! Creates a TSharedRef for a part of existing range.
  123. TSharedRef Slice(const void* begin, const void* end) const;
  124. //! Creates a vector of slices with specified size.
  125. std::vector<TSharedRef> Split(size_t partSize) const;
  126. private:
  127. friend class TSharedRefArrayImpl;
  128. };
  129. ////////////////////////////////////////////////////////////////////////////////
  130. //! Various options for allocating TSharedMutableRef.
  131. struct TSharedMutableRefAllocateOptions
  132. {
  133. bool InitializeStorage = true;
  134. bool ExtendToUsableSize = false;
  135. };
  136. //! A reference to a mutable range of memory with shared ownership.
  137. //! Use with caution :)
  138. class TSharedMutableRef
  139. : public TSharedMutableRange<char>
  140. {
  141. public:
  142. //! Creates a null TSharedMutableRef.
  143. TSharedMutableRef() = default;
  144. //! Creates a TSharedMutableRef with a given holder.
  145. TSharedMutableRef(const TMutableRef& ref, TSharedRangeHolderPtr holder);
  146. //! Creates a TSharedMutableRef from a pointer and length.
  147. TSharedMutableRef(void* data, size_t length, TSharedRangeHolderPtr holder);
  148. //! Creates a TSharedMutableRef from a range.
  149. TSharedMutableRef(void* begin, void* end, TSharedRangeHolderPtr holder);
  150. //! Creates an empty TSharedMutableRef.
  151. static TSharedMutableRef MakeEmpty();
  152. //! Converts a TSharedMutableRef to TMutableRef.
  153. operator TMutableRef() const;
  154. //! Converts a TSharedMutableRef to TSharedRef.
  155. operator TSharedRef() const;
  156. //! Converts a TSharedMutableRef to TRef.
  157. operator TRef() const;
  158. //! Allocates a new shared block of memory.
  159. //! The memory is marked with a given tag.
  160. template <class TTag>
  161. static TSharedMutableRef Allocate(size_t size, TSharedMutableRefAllocateOptions options = {});
  162. //! Allocates a new shared block of memory.
  163. //! The memory is marked with TDefaultSharedBlobTag.
  164. static TSharedMutableRef Allocate(size_t size, TSharedMutableRefAllocateOptions options = {});
  165. //! Allocates a new shared block of memory.
  166. //! The memory is marked with a given tag.
  167. static TSharedMutableRef Allocate(size_t size, TSharedMutableRefAllocateOptions options, TRefCountedTypeCookie tagCookie);
  168. //! Allocates a new page aligned shared block of memory.
  169. //! #size must be divisible by page size.
  170. //! The memory is marked with a given tag.
  171. template <class TTag>
  172. static TSharedMutableRef AllocatePageAligned(size_t size, TSharedMutableRefAllocateOptions options = {});
  173. //! Allocates a new page aligned shared block of memory.
  174. //! #size must be divisible by page size.
  175. //! The memory is marked with TDefaultSharedBlobTag.
  176. static TSharedMutableRef AllocatePageAligned(size_t size, TSharedMutableRefAllocateOptions options = {});
  177. //! Allocates a new page aligned shared block of memory.
  178. //! #size must be divisible by page size.
  179. //! The memory is marked with a given tag.
  180. static TSharedMutableRef AllocatePageAligned(size_t size, TSharedMutableRefAllocateOptions options, TRefCountedTypeCookie tagCookie);
  181. //! Creates a TSharedMutableRef for the whole blob taking ownership of its content.
  182. static TSharedMutableRef FromBlob(TBlob&& blob);
  183. //! Creates a copy of a given TRef.
  184. //! The memory is marked with a given tag.
  185. static TSharedMutableRef MakeCopy(TRef ref, TRefCountedTypeCookie tagCookie);
  186. //! Creates a copy of a given TRef.
  187. //! The memory is marked with a given tag.
  188. template <class TTag>
  189. static TSharedMutableRef MakeCopy(TRef ref);
  190. //! Creates a reference for a part of existing range.
  191. TSharedMutableRef Slice(size_t startOffset, size_t endOffset) const;
  192. //! Creates a reference for a part of existing range.
  193. TSharedMutableRef Slice(void* begin, void* end) const;
  194. };
  195. ////////////////////////////////////////////////////////////////////////////////
  196. DECLARE_REFCOUNTED_CLASS(TSharedRefArrayImpl)
  197. //! A smart-pointer to a ref-counted immutable sequence of TSharedRef-s.
  198. class TSharedRefArray
  199. {
  200. public:
  201. TSharedRefArray() = default;
  202. TSharedRefArray(const TSharedRefArray& other);
  203. TSharedRefArray(TSharedRefArray&& other) noexcept;
  204. explicit TSharedRefArray(const TSharedRef& part);
  205. explicit TSharedRefArray(TSharedRef&& part);
  206. struct TCopyParts
  207. { };
  208. struct TMoveParts
  209. { };
  210. template <class TParts>
  211. TSharedRefArray(const TParts& parts, TCopyParts);
  212. template <class TParts>
  213. TSharedRefArray(TParts&& parts, TMoveParts);
  214. TSharedRefArray& operator = (const TSharedRefArray& other);
  215. TSharedRefArray& operator = (TSharedRefArray&& other);
  216. explicit operator bool() const;
  217. void Reset();
  218. size_t Size() const;
  219. size_t size() const;
  220. i64 ByteSize() const;
  221. bool Empty() const;
  222. const TSharedRef& operator [] (size_t index) const;
  223. const TSharedRef* Begin() const;
  224. const TSharedRef* End() const;
  225. std::vector<TSharedRef> ToVector() const;
  226. TString ToString() const;
  227. //! Creates a copy of a given TSharedRefArray.
  228. //! The memory is marked with a given tag.
  229. static TSharedRefArray MakeCopy(const TSharedRefArray& array, TRefCountedTypeCookie tagCookie);
  230. private:
  231. friend class TSharedRefArrayBuilder;
  232. TSharedRefArrayImplPtr Impl_;
  233. explicit TSharedRefArray(TSharedRefArrayImplPtr impl);
  234. template <class... As>
  235. static TSharedRefArrayImplPtr NewImpl(
  236. size_t size,
  237. size_t poolCapacity,
  238. TRefCountedTypeCookie cookie,
  239. As&&... args);
  240. };
  241. // STL interop.
  242. const TSharedRef* begin(const TSharedRefArray& array);
  243. const TSharedRef* end(const TSharedRefArray& array);
  244. ////////////////////////////////////////////////////////////////////////////////
  245. struct TDefaultSharedRefArrayBuilderTag { };
  246. //! A helper for creating TSharedRefArray.
  247. class TSharedRefArrayBuilder
  248. {
  249. public:
  250. //! Creates a builder instance.
  251. /*
  252. * The user must provide the total (resulting) part count in #size.
  253. *
  254. * Additionally, the user may request a certain memory pool of size #poolCapacity
  255. * to be created. Parts occupiying space in the above pool are created with #AllocateAndAdd
  256. * calls.
  257. *
  258. * The pool (if any) and the array are created within a single memory allocation tagged with
  259. * #tagCookie.
  260. *
  261. * If less than #size parts are added, the trailing ones are null.
  262. */
  263. explicit TSharedRefArrayBuilder(
  264. size_t size,
  265. size_t poolCapacity = 0,
  266. TRefCountedTypeCookie tagCookie = GetRefCountedTypeCookie<TDefaultSharedRefArrayBuilderTag>());
  267. //! Adds an existing TSharedRef part to the constructed array.
  268. void Add(TSharedRef part);
  269. //! Allocates #size memory from the pool and adds a part to the constuctured array.
  270. /*!
  271. * The resulting TMutableRef enables the user to fill the just-created part appropriately.
  272. * The total sum of #size during all #AllocateAndAll calls must now exceed #allocationCapacity
  273. * passed to the ctor.
  274. *
  275. * The memory is being claimed from the pool contiguously; the user must
  276. * take care of the alignment issues on its own.
  277. */
  278. TMutableRef AllocateAndAdd(size_t size);
  279. //! Finalizes the construction; returns the constructed TSharedRefArray.
  280. TSharedRefArray Finish();
  281. private:
  282. const size_t AllocationCapacity_;
  283. TSharedRefArrayImplPtr Impl_;
  284. char* CurrentAllocationPtr_;
  285. size_t CurrentPartIndex_ = 0;
  286. };
  287. ////////////////////////////////////////////////////////////////////////////////
  288. void FormatValue(TStringBuilderBase* builder, const TRef& ref, TStringBuf spec);
  289. void FormatValue(TStringBuilderBase* builder, const TMutableRef& ref, TStringBuf spec);
  290. void FormatValue(TStringBuilderBase* builder, const TSharedRef& ref, TStringBuf spec);
  291. void FormatValue(TStringBuilderBase* builder, const TSharedMutableRef& ref, TStringBuf);
  292. size_t GetPageSize();
  293. size_t RoundUpToPage(size_t bytes);
  294. size_t GetByteSize(TRef ref);
  295. size_t GetByteSize(const TSharedRefArray& array);
  296. template <class T>
  297. size_t GetByteSize(TRange<T> parts);
  298. template <class T>
  299. size_t GetByteSize(const std::vector<T>& parts);
  300. ////////////////////////////////////////////////////////////////////////////////
  301. } // namespace NYT
  302. #define REF_INL_H_
  303. #include "ref-inl.h"
  304. #undef REF_INL_H_
  305. //! Serialize TSharedRef like vector<char>. Useful for ::Save, ::Load serialization/deserialization. See util/ysaveload.h.
  306. template <>
  307. class TSerializer<NYT::TSharedRef>: public TVectorSerializer<NYT::TSharedRange<char>> {};