ref-inl.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. #ifndef REF_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include ref.h"
  3. // For the sake of sane code completion.
  4. #include "ref.h"
  5. #endif
  6. #include <library/cpp/yt/misc/concepts.h>
  7. namespace NYT {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. namespace NDetail {
  10. extern const char EmptyRefData[];
  11. extern char MutableEmptyRefData[];
  12. } // namespace NDetail
  13. ////////////////////////////////////////////////////////////////////////////////
  14. Y_FORCE_INLINE TRef::TRef(const void* data, size_t size)
  15. : TRange<char>(static_cast<const char*>(data), size)
  16. { }
  17. Y_FORCE_INLINE TRef::TRef(const void* begin, const void* end)
  18. : TRange<char>(static_cast<const char*>(begin), static_cast<const char*>(end))
  19. { }
  20. Y_FORCE_INLINE TRef TRef::MakeEmpty()
  21. {
  22. return TRef(NDetail::EmptyRefData, NDetail::EmptyRefData);
  23. }
  24. Y_FORCE_INLINE TRef TRef::FromString(const TString& str)
  25. {
  26. return FromStringBuf(str);
  27. }
  28. Y_FORCE_INLINE TRef TRef::FromString(const std::string& str)
  29. {
  30. return TRef(str.data(), str.size());
  31. }
  32. Y_FORCE_INLINE TRef TRef::FromStringBuf(TStringBuf strBuf)
  33. {
  34. return TRef(strBuf.data(), strBuf.length());
  35. }
  36. template <class T>
  37. Y_FORCE_INLINE TRef TRef::FromPod(const T& data)
  38. {
  39. static_assert(TTypeTraits<T>::IsPod || (std::is_standard_layout_v<T> && std::is_trivial_v<T>), "T must be a pod-type.");
  40. return TRef(&data, sizeof(data));
  41. }
  42. Y_FORCE_INLINE TStringBuf TRef::ToStringBuf() const
  43. {
  44. return TStringBuf(Begin(), Size());
  45. }
  46. Y_FORCE_INLINE TRef TRef::Slice(size_t startOffset, size_t endOffset) const
  47. {
  48. YT_ASSERT(endOffset >= startOffset && endOffset <= Size());
  49. return TRef(Begin() + startOffset, endOffset - startOffset);
  50. }
  51. ////////////////////////////////////////////////////////////////////////////////
  52. Y_FORCE_INLINE TMutableRef::TMutableRef(void* data, size_t size)
  53. : TMutableRange<char>(static_cast<char*>(data), size)
  54. { }
  55. Y_FORCE_INLINE TMutableRef::TMutableRef(void* begin, void* end)
  56. : TMutableRange<char>(static_cast<char*>(begin), static_cast<char*>(end))
  57. { }
  58. Y_FORCE_INLINE TMutableRef TMutableRef::MakeEmpty()
  59. {
  60. return TMutableRef(NDetail::MutableEmptyRefData, NDetail::MutableEmptyRefData);
  61. }
  62. Y_FORCE_INLINE TMutableRef::operator TRef() const
  63. {
  64. return TRef(Begin(), Size());
  65. }
  66. template <class T>
  67. Y_FORCE_INLINE TMutableRef TMutableRef::FromPod(T& data)
  68. {
  69. static_assert(TTypeTraits<T>::IsPod || (std::is_standard_layout_v<T> && std::is_trivial_v<T>), "T must be a pod-type.");
  70. return TMutableRef(&data, sizeof(data));
  71. }
  72. Y_FORCE_INLINE TMutableRef TMutableRef::FromString(TString& str)
  73. {
  74. // NB: begin() invokes CloneIfShared().
  75. return TMutableRef(str.begin(), str.length());
  76. }
  77. Y_FORCE_INLINE TMutableRef TMutableRef::FromString(std::string& str)
  78. {
  79. return TMutableRef(str.data(), str.length());
  80. }
  81. Y_FORCE_INLINE TMutableRef TMutableRef::Slice(size_t startOffset, size_t endOffset) const
  82. {
  83. YT_ASSERT(endOffset >= startOffset && endOffset <= Size());
  84. return TMutableRef(Begin() + startOffset, endOffset - startOffset);
  85. }
  86. ////////////////////////////////////////////////////////////////////////////////
  87. Y_FORCE_INLINE TSharedRef::TSharedRef(TRef ref, TSharedRangeHolderPtr holder)
  88. : TSharedRange<char>(ref, std::move(holder))
  89. { }
  90. Y_FORCE_INLINE TSharedRef::TSharedRef(const void* data, size_t length, TSharedRangeHolderPtr holder)
  91. : TSharedRange<char>(static_cast<const char*>(data), length, std::move(holder))
  92. { }
  93. Y_FORCE_INLINE TSharedRef::TSharedRef(const void* begin, const void* end, TSharedRangeHolderPtr holder)
  94. : TSharedRange<char>(static_cast<const char*>(begin), static_cast<const char*>(end), std::move(holder))
  95. { }
  96. Y_FORCE_INLINE TSharedRef TSharedRef::MakeEmpty()
  97. {
  98. return TSharedRef(TRef::MakeEmpty(), nullptr);
  99. }
  100. Y_FORCE_INLINE TSharedRef::operator TRef() const
  101. {
  102. return TRef(Begin(), Size());
  103. }
  104. template <class TTag>
  105. Y_FORCE_INLINE TSharedRef TSharedRef::FromString(TString str)
  106. {
  107. static_assert(IsEmptyClass<TTag>());
  108. return FromString(std::move(str), GetRefCountedTypeCookie<TTag>());
  109. }
  110. Y_FORCE_INLINE TSharedRef TSharedRef::FromString(TString str)
  111. {
  112. return FromString<TDefaultSharedBlobTag>(std::move(str));
  113. }
  114. template <class TTag>
  115. Y_FORCE_INLINE TSharedRef TSharedRef::FromString(std::string str)
  116. {
  117. static_assert(IsEmptyClass<TTag>());
  118. return FromString(std::move(str), GetRefCountedTypeCookie<TTag>());
  119. }
  120. Y_FORCE_INLINE TSharedRef TSharedRef::FromString(std::string str)
  121. {
  122. return FromString<TDefaultSharedBlobTag>(std::move(str));
  123. }
  124. Y_FORCE_INLINE TStringBuf TSharedRef::ToStringBuf() const
  125. {
  126. return TStringBuf(Begin(), Size());
  127. }
  128. template <class TTag>
  129. Y_FORCE_INLINE TSharedRef TSharedRef::MakeCopy(TRef ref)
  130. {
  131. static_assert(IsEmptyClass<TTag>());
  132. return MakeCopy(ref, GetRefCountedTypeCookie<TTag>());
  133. }
  134. Y_FORCE_INLINE TSharedRef TSharedRef::Slice(size_t startOffset, size_t endOffset) const
  135. {
  136. YT_ASSERT(endOffset >= startOffset && endOffset <= Size());
  137. return TSharedRef(Begin() + startOffset, endOffset - startOffset, Holder_);
  138. }
  139. Y_FORCE_INLINE TSharedRef TSharedRef::Slice(const void* begin, const void* end) const
  140. {
  141. YT_ASSERT(begin >= Begin());
  142. YT_ASSERT(end <= End());
  143. return TSharedRef(begin, end, Holder_);
  144. }
  145. ////////////////////////////////////////////////////////////////////////////////
  146. Y_FORCE_INLINE TSharedMutableRef::TSharedMutableRef(const TMutableRef& ref, TSharedRangeHolderPtr holder)
  147. : TSharedMutableRange<char>(ref, std::move(holder))
  148. { }
  149. Y_FORCE_INLINE TSharedMutableRef::TSharedMutableRef(void* data, size_t length, TSharedRangeHolderPtr holder)
  150. : TSharedMutableRange<char>(static_cast<char*>(data), length, std::move(holder))
  151. { }
  152. Y_FORCE_INLINE TSharedMutableRef::TSharedMutableRef(void* begin, void* end, TSharedRangeHolderPtr holder)
  153. : TSharedMutableRange<char>(static_cast<char*>(begin), static_cast<char*>(end), std::move(holder))
  154. { }
  155. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::MakeEmpty()
  156. {
  157. return TSharedMutableRef(TMutableRef::MakeEmpty(), nullptr);
  158. }
  159. Y_FORCE_INLINE TSharedMutableRef::operator TMutableRef() const
  160. {
  161. return TMutableRef(Begin(), Size());
  162. }
  163. Y_FORCE_INLINE TSharedMutableRef::operator TSharedRef() const
  164. {
  165. return TSharedRef(Begin(), Size(), Holder_);
  166. }
  167. Y_FORCE_INLINE TSharedMutableRef::operator TRef() const
  168. {
  169. return TRef(Begin(), Size());
  170. }
  171. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::Allocate(size_t size, TSharedMutableRefAllocateOptions options)
  172. {
  173. return Allocate<TDefaultSharedBlobTag>(size, options);
  174. }
  175. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::AllocatePageAligned(size_t size, TSharedMutableRefAllocateOptions options)
  176. {
  177. return AllocatePageAligned<TDefaultSharedBlobTag>(size, options);
  178. }
  179. template <class TTag>
  180. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::MakeCopy(TRef ref)
  181. {
  182. static_assert(IsEmptyClass<TTag>());
  183. return MakeCopy(ref, GetRefCountedTypeCookie<TTag>());
  184. }
  185. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::Slice(size_t startOffset, size_t endOffset) const
  186. {
  187. YT_ASSERT(endOffset >= startOffset && endOffset <= Size());
  188. return TSharedMutableRef(Begin() + startOffset, endOffset - startOffset, Holder_);
  189. }
  190. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::Slice(void* begin, void* end) const
  191. {
  192. YT_ASSERT(begin >= Begin());
  193. YT_ASSERT(end <= End());
  194. return TSharedMutableRef(begin, end, Holder_);
  195. }
  196. template <class TTag>
  197. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::Allocate(size_t size, TSharedMutableRefAllocateOptions options)
  198. {
  199. static_assert(IsEmptyClass<TTag>());
  200. return Allocate(size, options, GetRefCountedTypeCookie<TTag>());
  201. }
  202. template <class TTag>
  203. Y_FORCE_INLINE TSharedMutableRef TSharedMutableRef::AllocatePageAligned(size_t size, TSharedMutableRefAllocateOptions options)
  204. {
  205. static_assert(IsEmptyClass<TTag>());
  206. return AllocatePageAligned(size, options, GetRefCountedTypeCookie<TTag>());
  207. }
  208. ////////////////////////////////////////////////////////////////////////////////
  209. Y_FORCE_INLINE size_t GetByteSize(TRef ref)
  210. {
  211. return ref ? ref.Size() : 0;
  212. }
  213. template <class T>
  214. size_t GetByteSize(TRange<T> parts)
  215. {
  216. size_t size = 0;
  217. for (const auto& part : parts) {
  218. size += part.Size();
  219. }
  220. return size;
  221. }
  222. template <class T>
  223. size_t GetByteSize(const std::vector<T>& parts)
  224. {
  225. return GetByteSize(TRange(parts));
  226. }
  227. ////////////////////////////////////////////////////////////////////////////////
  228. class TSharedRefArrayImpl
  229. : public TSharedRangeHolder
  230. , public TWithExtraSpace<TSharedRefArrayImpl>
  231. {
  232. public:
  233. TSharedRefArrayImpl(
  234. size_t extraSpaceSize,
  235. TRefCountedTypeCookie tagCookie,
  236. size_t size)
  237. : Size_(size)
  238. , ExtraSpaceSize_(extraSpaceSize)
  239. , TagCookie_(tagCookie)
  240. {
  241. for (size_t index = 0; index < Size_; ++index) {
  242. new (MutableBegin() + index) TSharedRef();
  243. }
  244. RegisterWithRefCountedTracker();
  245. }
  246. TSharedRefArrayImpl(
  247. size_t extraSpaceSize,
  248. TRefCountedTypeCookie tagCookie,
  249. const TSharedRef& part)
  250. : Size_(1)
  251. , ExtraSpaceSize_(extraSpaceSize)
  252. , TagCookie_(tagCookie)
  253. {
  254. new (MutableBegin()) TSharedRef(part);
  255. RegisterWithRefCountedTracker();
  256. }
  257. TSharedRefArrayImpl(
  258. size_t extraSpaceSize,
  259. TRefCountedTypeCookie tagCookie,
  260. TSharedRef&& part)
  261. : Size_(1)
  262. , ExtraSpaceSize_(extraSpaceSize)
  263. , TagCookie_(tagCookie)
  264. {
  265. new (MutableBegin()) TSharedRef(std::move(part));
  266. RegisterWithRefCountedTracker();
  267. }
  268. template <class TParts>
  269. TSharedRefArrayImpl(
  270. size_t extraSpaceSize,
  271. TRefCountedTypeCookie tagCookie,
  272. const TParts& parts,
  273. TSharedRefArray::TCopyParts)
  274. : Size_(parts.size())
  275. , ExtraSpaceSize_(extraSpaceSize)
  276. , TagCookie_(tagCookie)
  277. {
  278. for (size_t index = 0; index < Size_; ++index) {
  279. new (MutableBegin() + index) TSharedRef(parts[index]);
  280. }
  281. RegisterWithRefCountedTracker();
  282. }
  283. template <class TParts>
  284. TSharedRefArrayImpl(
  285. size_t extraSpaceSize,
  286. TRefCountedTypeCookie tagCookie,
  287. TParts&& parts,
  288. TSharedRefArray::TMoveParts)
  289. : Size_(parts.size())
  290. , ExtraSpaceSize_(extraSpaceSize)
  291. , TagCookie_(tagCookie)
  292. {
  293. for (size_t index = 0; index < Size_; ++index) {
  294. new (MutableBegin() + index) TSharedRef(std::move(parts[index]));
  295. }
  296. RegisterWithRefCountedTracker();
  297. }
  298. ~TSharedRefArrayImpl()
  299. {
  300. for (size_t index = 0; index < Size_; ++index) {
  301. auto& part = MutableBegin()[index];
  302. if (part.GetHolder() == this) {
  303. part.Holder_.Release();
  304. }
  305. part.TSharedRef::~TSharedRef();
  306. }
  307. UnregisterFromRefCountedTracker();
  308. }
  309. size_t Size() const
  310. {
  311. return Size_;
  312. }
  313. bool Empty() const
  314. {
  315. return Size_ == 0;
  316. }
  317. const TSharedRef& operator [] (size_t index) const
  318. {
  319. YT_ASSERT(index < Size());
  320. return Begin()[index];
  321. }
  322. const TSharedRef* Begin() const
  323. {
  324. return static_cast<const TSharedRef*>(GetExtraSpacePtr());
  325. }
  326. const TSharedRef* End() const
  327. {
  328. return Begin() + Size_;
  329. }
  330. // TSharedRangeHolder overrides.
  331. std::optional<size_t> GetTotalByteSize() const override
  332. {
  333. size_t result = 0;
  334. for (size_t index = 0; index < Size(); ++index) {
  335. const auto& part = (*this)[index];
  336. if (!part) {
  337. continue;
  338. }
  339. auto partSize = part.GetHolder()->GetTotalByteSize();
  340. if (!partSize) {
  341. return std::nullopt;
  342. }
  343. result += *partSize;
  344. }
  345. return result;
  346. }
  347. private:
  348. friend class TSharedRefArrayBuilder;
  349. const size_t Size_;
  350. const size_t ExtraSpaceSize_;
  351. const TRefCountedTypeCookie TagCookie_;
  352. void RegisterWithRefCountedTracker()
  353. {
  354. TRefCountedTrackerFacade::AllocateTagInstance(TagCookie_);
  355. TRefCountedTrackerFacade::AllocateSpace(TagCookie_, ExtraSpaceSize_);
  356. }
  357. void UnregisterFromRefCountedTracker()
  358. {
  359. TRefCountedTrackerFacade::FreeTagInstance(TagCookie_);
  360. TRefCountedTrackerFacade::FreeSpace(TagCookie_, ExtraSpaceSize_);
  361. }
  362. TSharedRef* MutableBegin()
  363. {
  364. return static_cast<TSharedRef*>(GetExtraSpacePtr());
  365. }
  366. TSharedRef* MutableEnd()
  367. {
  368. return MutableBegin() + Size_;
  369. }
  370. char* GetBeginAllocationPtr()
  371. {
  372. return static_cast<char*>(static_cast<void*>(MutableEnd()));
  373. }
  374. };
  375. DEFINE_REFCOUNTED_TYPE(TSharedRefArrayImpl)
  376. ////////////////////////////////////////////////////////////////////////////////
  377. struct TSharedRefArrayTag { };
  378. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(TIntrusivePtr<TSharedRefArrayImpl> impl)
  379. : Impl_(std::move(impl))
  380. { }
  381. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(const TSharedRefArray& other)
  382. : Impl_(other.Impl_)
  383. { }
  384. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(TSharedRefArray&& other) noexcept
  385. : Impl_(std::move(other.Impl_))
  386. { }
  387. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(const TSharedRef& part)
  388. : Impl_(NewImpl(1, 0, GetRefCountedTypeCookie<TSharedRefArrayTag>(), part))
  389. { }
  390. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(TSharedRef&& part)
  391. : Impl_(NewImpl(1, 0, GetRefCountedTypeCookie<TSharedRefArrayTag>(), std::move(part)))
  392. { }
  393. template <class TParts>
  394. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(const TParts& parts, TSharedRefArray::TCopyParts)
  395. : Impl_(NewImpl(parts.size(), 0, GetRefCountedTypeCookie<TSharedRefArrayTag>(), parts, TSharedRefArray::TCopyParts{}))
  396. { }
  397. template <class TParts>
  398. Y_FORCE_INLINE TSharedRefArray::TSharedRefArray(TParts&& parts, TSharedRefArray::TMoveParts)
  399. : Impl_(NewImpl(parts.size(), 0, GetRefCountedTypeCookie<TSharedRefArrayTag>(), std::move(parts), TSharedRefArray::TMoveParts{}))
  400. { }
  401. Y_FORCE_INLINE TSharedRefArray& TSharedRefArray::operator=(const TSharedRefArray& other)
  402. {
  403. Impl_ = other.Impl_;
  404. return *this;
  405. }
  406. Y_FORCE_INLINE TSharedRefArray& TSharedRefArray::operator=(TSharedRefArray&& other)
  407. {
  408. Impl_ = std::move(other.Impl_);
  409. return *this;
  410. }
  411. Y_FORCE_INLINE void TSharedRefArray::Reset()
  412. {
  413. Impl_.Reset();
  414. }
  415. Y_FORCE_INLINE TSharedRefArray::operator bool() const
  416. {
  417. return Impl_.operator bool();
  418. }
  419. Y_FORCE_INLINE size_t TSharedRefArray::Size() const
  420. {
  421. return Impl_ ? Impl_->Size() : 0;
  422. }
  423. Y_FORCE_INLINE size_t TSharedRefArray::size() const
  424. {
  425. return Impl_ ? Impl_->Size() : 0;
  426. }
  427. Y_FORCE_INLINE bool TSharedRefArray::Empty() const
  428. {
  429. return Impl_ ? Impl_->Empty() : true;
  430. }
  431. Y_FORCE_INLINE const TSharedRef& TSharedRefArray::operator[](size_t index) const
  432. {
  433. YT_ASSERT(Impl_);
  434. return (*Impl_)[index];
  435. }
  436. Y_FORCE_INLINE const TSharedRef* TSharedRefArray::Begin() const
  437. {
  438. return Impl_ ? Impl_->Begin() : nullptr;
  439. }
  440. Y_FORCE_INLINE const TSharedRef* TSharedRefArray::End() const
  441. {
  442. return Impl_ ? Impl_->End() : nullptr;
  443. }
  444. template <class... As>
  445. TSharedRefArrayImplPtr TSharedRefArray::NewImpl(
  446. size_t size,
  447. size_t poolCapacity,
  448. TRefCountedTypeCookie tagCookie,
  449. As&&... args)
  450. {
  451. auto extraSpaceSize = sizeof(TSharedRef) * size + poolCapacity;
  452. return NewWithExtraSpace<TSharedRefArrayImpl>(
  453. extraSpaceSize,
  454. extraSpaceSize,
  455. tagCookie,
  456. std::forward<As>(args)...);
  457. }
  458. Y_FORCE_INLINE const TSharedRef* begin(const TSharedRefArray& array)
  459. {
  460. return array.Begin();
  461. }
  462. Y_FORCE_INLINE const TSharedRef* end(const TSharedRefArray& array)
  463. {
  464. return array.End();
  465. }
  466. ////////////////////////////////////////////////////////////////////////////////
  467. } // namespace NYT