ref.h 14 KB

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