ref.h 13 KB

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