ref.h 13 KB

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