shared_range.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. #pragma once
  2. #include "public.h"
  3. #include "intrusive_ptr.h"
  4. #include "range.h"
  5. #include "ref_counted.h"
  6. #include <library/cpp/yt/assert/assert.h>
  7. #include <util/ysaveload.h>
  8. #include <optional>
  9. namespace NYT {
  10. ////////////////////////////////////////////////////////////////////////////////
  11. template <class T, size_t N>
  12. class TCompactVector;
  13. ////////////////////////////////////////////////////////////////////////////////
  14. struct TSharedRangeHolderCloneOptions
  15. {
  16. bool KeepMemoryReferenceTracking = true;
  17. };
  18. struct TSharedRangeHolder
  19. : public TRefCounted
  20. {
  21. //! Clones the holder possibly adjusting its flavor based on #options.
  22. /*!
  23. * The default implementation just returns this.
  24. */
  25. virtual TSharedRangeHolderPtr Clone(const TSharedRangeHolderCloneOptions& options);
  26. //! Returns the (estimated) total number of bytes being held or |null| if unable to estimate.
  27. /*!
  28. * The returned value is static and never changes.
  29. * The default implementation returns |null|.
  30. */
  31. virtual std::optional<size_t> GetTotalByteSize() const;
  32. };
  33. DEFINE_REFCOUNTED_TYPE(TSharedRangeHolder)
  34. ////////////////////////////////////////////////////////////////////////////////
  35. //! TRange with ownership semantics.
  36. template <class T>
  37. class TSharedRange
  38. : public TRange<T>
  39. {
  40. public:
  41. //! Constructs a null TSharedRange.
  42. TSharedRange()
  43. { }
  44. //! Constructs an empty TSharedRange from a nullptr expression.
  45. TSharedRange(std::nullptr_t)
  46. : TRange<T>(nullptr, 0UL)
  47. , Holder_(nullptr)
  48. { }
  49. //! Constructs a TSharedRange from TRange.
  50. TSharedRange(TRange<T> range, TSharedRangeHolderPtr holder)
  51. : TRange<T>(range)
  52. , Holder_(std::move(holder))
  53. { }
  54. //! Constructs a TSharedRange from a pointer and length.
  55. TSharedRange(const T* data, size_t length, TSharedRangeHolderPtr holder)
  56. : TRange<T>(data, length)
  57. , Holder_(std::move(holder))
  58. { }
  59. //! Constructs a TSharedRange from a range.
  60. TSharedRange(const T* begin, const T* end, TSharedRangeHolderPtr holder)
  61. : TRange<T>(begin, end)
  62. , Holder_(std::move(holder))
  63. { }
  64. //! Constructs a TSharedRange from a TCompactVector.
  65. template <size_t N>
  66. TSharedRange(const TCompactVector<T, N>& elements, TSharedRangeHolderPtr holder)
  67. : TRange<T>(elements)
  68. , Holder_(std::move(holder))
  69. { }
  70. //! Constructs a TSharedRange from an std::vector.
  71. TSharedRange(const std::vector<T>& elements, TSharedRangeHolderPtr holder)
  72. : TRange<T>(elements)
  73. , Holder_(std::move(holder))
  74. { }
  75. //! Constructs a TSharedRange from a C array.
  76. template <size_t N>
  77. TSharedRange(const T (& elements)[N], TSharedRangeHolderPtr holder)
  78. : TRange<T>(elements)
  79. , Holder_(std::move(holder))
  80. { }
  81. TSharedRange(const TSharedRange& other) = default;
  82. TSharedRange(TSharedRange&& other) noexcept
  83. : TSharedRange()
  84. {
  85. other.Swap(*this);
  86. }
  87. TSharedRange& operator=(TSharedRange other) noexcept
  88. {
  89. other.Swap(*this);
  90. return *this;
  91. }
  92. void Swap(TSharedRange& other) noexcept
  93. {
  94. DoSwap(TRange<T>::Data_, other.Data_);
  95. DoSwap(TRange<T>::Length_, other.Length_);
  96. Holder_.Swap(other.Holder_);
  97. }
  98. void Reset()
  99. {
  100. TRange<T>::Data_ = nullptr;
  101. TRange<T>::Length_ = 0;
  102. Holder_.Reset();
  103. }
  104. TSharedRange<T> Slice(size_t startOffset, size_t endOffset) const
  105. {
  106. YT_ASSERT(startOffset <= this->Size());
  107. YT_ASSERT(endOffset >= startOffset && endOffset <= this->Size());
  108. return TSharedRange<T>(this->Begin() + startOffset, endOffset - startOffset, Holder_);
  109. }
  110. TSharedRange<T> Slice(const T* begin, const T* end) const
  111. {
  112. YT_ASSERT(begin >= this->Begin());
  113. YT_ASSERT(end <= this->End());
  114. return TSharedRange<T>(begin, end, Holder_);
  115. }
  116. const TSharedRangeHolderPtr& GetHolder() const
  117. {
  118. return Holder_;
  119. }
  120. TSharedRangeHolderPtr&& ReleaseHolder()
  121. {
  122. return std::move(Holder_);
  123. }
  124. protected:
  125. TSharedRangeHolderPtr Holder_;
  126. };
  127. ////////////////////////////////////////////////////////////////////////////////
  128. //! Constructs a combined holder from a vector of typed holders.
  129. TSharedRangeHolderPtr MakeCompositeSharedRangeHolder(std::vector<TSharedRangeHolderPtr> holders);
  130. //! Constructs a combined holder instance by taking ownership of a given list of holders.
  131. template <class... THolders>
  132. TSharedRangeHolderPtr MakeSharedRangeHolder(THolders&&... holders)
  133. {
  134. struct THolder
  135. : public TSharedRangeHolder
  136. {
  137. std::tuple<typename std::decay<THolders>::type...> Holders;
  138. };
  139. auto holder = New<THolder>();
  140. holder->Holders = std::tuple<THolders...>(std::forward<THolders>(holders)...);
  141. return holder;
  142. }
  143. template <class T, class TContainer, class... THolders>
  144. TSharedRange<T> DoMakeSharedRange(TContainer&& elements, THolders&&... holders)
  145. {
  146. struct THolder
  147. : public TSharedRangeHolder
  148. {
  149. typename std::decay<TContainer>::type Elements;
  150. std::tuple<typename std::decay<THolders>::type...> Holders;
  151. };
  152. auto holder = New<THolder>();
  153. holder->Holders = std::tuple<THolders...>(std::forward<THolders>(holders)...);
  154. holder->Elements = std::forward<TContainer>(elements);
  155. auto range = MakeRange<T>(holder->Elements);
  156. return TSharedRange<T>(range, std::move(holder));
  157. }
  158. //! Constructs a TSharedRange by taking ownership of an std::vector.
  159. template <class T, class... THolders>
  160. TSharedRange<T> MakeSharedRange(std::vector<T>&& elements, THolders&&... holders)
  161. {
  162. return DoMakeSharedRange<T>(std::move(elements), std::forward<THolders>(holders)...);
  163. }
  164. //! Constructs a TSharedRange by taking ownership of an TCompactVector.
  165. template <class T, size_t N, class... THolders>
  166. TSharedRange<T> MakeSharedRange(TCompactVector<T, N>&& elements, THolders&&... holders)
  167. {
  168. return DoMakeSharedRange<T>(std::move(elements), std::forward<THolders>(holders)...);
  169. }
  170. //! Constructs a TSharedRange by copying an std::vector.
  171. template <class T, class... THolders>
  172. TSharedRange<T> MakeSharedRange(const std::vector<T>& elements, THolders&&... holders)
  173. {
  174. return DoMakeSharedRange<T>(elements, std::forward<THolders>(holders)...);
  175. }
  176. template <class T, class... THolders>
  177. TSharedRange<T> MakeSharedRange(TRange<T> range, THolders&&... holders)
  178. {
  179. return TSharedRange<T>(range, MakeSharedRangeHolder(std::forward<THolders>(holders)...));
  180. }
  181. template <class T, class THolder>
  182. TSharedRange<T> MakeSharedRange(TRange<T> range, TSharedRangeHolderPtr holder)
  183. {
  184. return TSharedRange<T>(range, std::move(holder));
  185. }
  186. template <class U, class T>
  187. TSharedRange<U> ReinterpretCastRange(const TSharedRange<T>& range)
  188. {
  189. static_assert(sizeof(T) == sizeof(U), "T and U must have equal sizes.");
  190. return TSharedRange<U>(reinterpret_cast<const U*>(range.Begin()), range.Size(), range.GetHolder());
  191. }
  192. ////////////////////////////////////////////////////////////////////////////////
  193. //! TMutableRange with ownership semantics.
  194. //! Use with caution :)
  195. template <class T>
  196. class TSharedMutableRange
  197. : public TMutableRange<T>
  198. {
  199. public:
  200. //! Constructs a null TSharedMutableRange.
  201. TSharedMutableRange()
  202. { }
  203. //! Constructs a TSharedMutableRange from TMutableRange.
  204. TSharedMutableRange(TMutableRange<T> range, TSharedRangeHolderPtr holder)
  205. : TMutableRange<T>(range)
  206. , Holder_(std::move(holder))
  207. { }
  208. //! Constructs a TSharedMutableRange from a pointer and length.
  209. TSharedMutableRange(T* data, size_t length, TSharedRangeHolderPtr holder)
  210. : TMutableRange<T>(data, length)
  211. , Holder_(std::move(holder))
  212. { }
  213. //! Constructs a TSharedMutableRange from a range.
  214. TSharedMutableRange(T* begin, T* end, TSharedRangeHolderPtr holder)
  215. : TMutableRange<T>(begin, end)
  216. , Holder_(std::move(holder))
  217. { }
  218. //! Constructs a TSharedMutableRange from a TCompactVector.
  219. template <size_t N>
  220. TSharedMutableRange(TCompactVector<T, N>& elements, TSharedRangeHolderPtr holder)
  221. : TMutableRange<T>(elements)
  222. , Holder_(std::move(holder))
  223. { }
  224. //! Constructs a TSharedMutableRange from an std::vector.
  225. TSharedMutableRange(std::vector<T>& elements, TSharedRangeHolderPtr holder)
  226. : TMutableRange<T>(elements)
  227. , Holder_(std::move(holder))
  228. { }
  229. //! Constructs a TSharedMutableRange from a C array.
  230. template <size_t N>
  231. TSharedMutableRange(T (& elements)[N], TSharedRangeHolderPtr holder)
  232. : TMutableRange<T>(elements)
  233. , Holder_(std::move(holder))
  234. { }
  235. TSharedMutableRange(const TSharedMutableRange& other) = default;
  236. TSharedMutableRange(TSharedMutableRange&& other) noexcept
  237. : TSharedMutableRange()
  238. {
  239. other.Swap(*this);
  240. }
  241. TSharedMutableRange& operator=(TSharedMutableRange other) noexcept
  242. {
  243. other.Swap(*this);
  244. return *this;
  245. }
  246. void Swap(TSharedMutableRange& other) noexcept
  247. {
  248. DoSwap(TRange<T>::Data_, other.Data_);
  249. DoSwap(TRange<T>::Length_, other.Length_);
  250. Holder_.Swap(other.Holder_);
  251. }
  252. void Reset()
  253. {
  254. TRange<T>::Data_ = nullptr;
  255. TRange<T>::Length_ = 0;
  256. Holder_.Reset();
  257. }
  258. TSharedMutableRange<T> Slice(size_t startOffset, size_t endOffset) const
  259. {
  260. YT_ASSERT(startOffset <= this->Size());
  261. YT_ASSERT(endOffset >= startOffset && endOffset <= this->Size());
  262. return TSharedMutableRange<T>(this->Begin() + startOffset, endOffset - startOffset, Holder_);
  263. }
  264. TSharedMutableRange<T> Slice(T* begin, T* end) const
  265. {
  266. YT_ASSERT(begin >= this->Begin());
  267. YT_ASSERT(end <= this->End());
  268. return TSharedMutableRange<T>(begin, end, Holder_);
  269. }
  270. TSharedRangeHolderPtr GetHolder() const
  271. {
  272. return Holder_;
  273. }
  274. TSharedRangeHolderPtr&& ReleaseHolder()
  275. {
  276. return std::move(Holder_);
  277. }
  278. protected:
  279. TSharedRangeHolderPtr Holder_;
  280. };
  281. template <class T, class TContainer, class... THolders>
  282. TSharedMutableRange<T> DoMakeSharedMutableRange(TContainer&& elements, THolders&&... holders)
  283. {
  284. struct THolder
  285. : public TSharedRangeHolder
  286. {
  287. typename std::decay<TContainer>::type Elements;
  288. std::tuple<typename std::decay<THolders>::type...> Holders;
  289. };
  290. auto holder = New<THolder>();
  291. holder->Holders = std::tuple<THolders...>(std::forward<THolders>(holders)...);
  292. holder->Elements = std::forward<TContainer>(elements);
  293. auto range = TMutableRange<T>(holder->Elements);
  294. return TSharedMutableRange<T>(range, holder);
  295. }
  296. //! Constructs a TSharedMutableRange by taking ownership of an std::vector.
  297. template <class T, class... THolders>
  298. TSharedMutableRange<T> MakeSharedMutableRange(std::vector<T>&& elements, THolders&&... holders)
  299. {
  300. return DoMakeSharedMutableRange<T>(std::move(elements), std::forward<THolders>(holders)...);
  301. }
  302. ////////////////////////////////////////////////////////////////////////////////
  303. } // namespace NYT