mkql_computation_node_list.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #pragma once
  2. #include <yql/essentials/minikql/defs.h>
  3. #include <yql/essentials/minikql/mkql_alloc.h>
  4. #include <yql/essentials/public/udf/udf_value.h>
  5. namespace NKikimr {
  6. namespace NMiniKQL {
  7. template <typename T>
  8. struct TListChunk {
  9. private:
  10. using TSelf = TListChunk<T>;
  11. static void PlacementNew(T* ptr, ui64 count) {
  12. T* end = ptr + count;
  13. for (; ptr != end; ptr++) {
  14. new (ptr) T;
  15. }
  16. }
  17. public:
  18. void CheckMagic() {
  19. Y_DEBUG_ABORT_UNLESS(Magic_ == TListChunkMagic);
  20. }
  21. static TSelf* AllocateChunk(ui64 length) {
  22. const auto block = TWithDefaultMiniKQLAlloc::AllocWithSize(length * sizeof(T) + sizeof(TListChunk));
  23. const auto ptr = new (block) TListChunk(length);
  24. PlacementNew(reinterpret_cast<T*>(ptr + 1), length);
  25. return ptr;
  26. }
  27. TListChunk(ui64 size)
  28. : Magic_(TListChunkMagic)
  29. , Refs_(1)
  30. , DataEnd_(DataBegin() + size)
  31. {
  32. }
  33. ~TListChunk() {
  34. CheckMagic();
  35. for (auto it = DataBegin(); it != DataEnd(); it++) {
  36. it->~T();
  37. }
  38. TWithDefaultMiniKQLAlloc::FreeWithSize(
  39. static_cast<void*>(this), sizeof(TListChunk) + sizeof(T) * (DataEnd() - DataBegin()));
  40. }
  41. inline T* DataBegin() {
  42. CheckMagic();
  43. return reinterpret_cast<T*>(this + 1);
  44. }
  45. inline const T* DataEnd() {
  46. CheckMagic();
  47. return DataEnd_;
  48. }
  49. ui64 Size() {
  50. CheckMagic();
  51. return DataEnd() - DataBegin();
  52. }
  53. void Ref() {
  54. CheckMagic();
  55. Refs_++;
  56. }
  57. void UnRef() {
  58. CheckMagic();
  59. if (--Refs_ == 0) {
  60. this->~TListChunk();
  61. }
  62. }
  63. private:
  64. static const ui32 TListChunkMagic = 12322846;
  65. const ui32 Magic_;
  66. ui32 Refs_;
  67. const T* DataEnd_;
  68. };
  69. template <typename T, ui64 MinChunkSize = 48>
  70. class TListRepresentation {
  71. public:
  72. using TSelf = TListRepresentation<T, MinChunkSize>;
  73. using TChunk = TListChunk<T>;
  74. private:
  75. enum Type {
  76. Normal,
  77. Freezed
  78. };
  79. void NewNormal(const T* begin1, const T* end1, const T* begin2, const T* end2) {
  80. Type_ = Type::Normal;
  81. ui64 oldLength = (end1 - begin1) + (end2 - begin2);
  82. ui64 newLength = std::max((oldLength << 1) - 1, (MinChunkSize + sizeof(T) - 1) / sizeof(T) + 1);
  83. Chunk_ = TChunk::AllocateChunk(newLength);
  84. Begin_ = Chunk_->DataBegin() + ((newLength - oldLength) >> 2);
  85. End_ = std::copy(begin2, end2, std::copy(begin1, end1, Begin_));
  86. }
  87. TListRepresentation(TChunk* chunk, T* begin, T* end, Type type)
  88. : Chunk_(chunk)
  89. , Begin_(begin)
  90. , End_(end)
  91. , Type_(type)
  92. {
  93. if (Chunk_) {
  94. Chunk_->Ref();
  95. }
  96. }
  97. TListRepresentation(T* begin1, T* end1, T* begin2, T* end2)
  98. {
  99. NewNormal(begin1, end1, begin2, end2);
  100. }
  101. public:
  102. struct TIterator {
  103. TIterator()
  104. : Owner_(nullptr)
  105. , Position_(nullptr)
  106. {}
  107. TIterator(const TListRepresentation& owner)
  108. : Owner_(&owner)
  109. , Position_(owner.Begin_)
  110. {
  111. }
  112. TIterator(const TIterator& other)
  113. : Owner_(other.Owner_)
  114. , Position_(other.Position_)
  115. {}
  116. TIterator& operator=(const TIterator& other)
  117. {
  118. Owner_ = other.Owner_;
  119. Position_ = other.Position_;
  120. return *this;
  121. }
  122. bool AtEnd() const {
  123. return Position_ == Owner_->End_;
  124. }
  125. const T& Current() const {
  126. return *Position_;
  127. }
  128. // use with care, list may be shared
  129. T& MutableCurrent() {
  130. return *Position_;
  131. }
  132. void Next() {
  133. Position_++;
  134. }
  135. const TListRepresentation* Owner_;
  136. T* Position_;
  137. };
  138. struct TReverseIterator {
  139. TReverseIterator()
  140. : Owner_(nullptr)
  141. , Position_(nullptr)
  142. {
  143. }
  144. TReverseIterator(const TListRepresentation& owner)
  145. : Owner_(&owner)
  146. , Position_(owner.End_)
  147. {
  148. }
  149. TReverseIterator(const TIterator& other)
  150. : Owner_(other.Owner_)
  151. , Position_(other.Position_)
  152. {
  153. }
  154. TReverseIterator& operator=(const TReverseIterator& other)
  155. {
  156. Owner_ = other.Owner_;
  157. Position_ = other.Position_;
  158. return *this;
  159. }
  160. bool AtEnd() const {
  161. return Position_ == Owner_->Begin_;
  162. }
  163. const T& Current() const {
  164. return *(Position_ - 1);
  165. }
  166. // use with care, list may be shared
  167. T& MutableCurrent() {
  168. return *(Position_ - 1);
  169. }
  170. void Next() {
  171. Position_--;
  172. }
  173. private:
  174. const TListRepresentation* Owner_;
  175. T* Position_;
  176. };
  177. TListRepresentation()
  178. : Chunk_(nullptr)
  179. , Begin_(nullptr)
  180. , End_(nullptr)
  181. , Type_(Type::Freezed)
  182. {
  183. }
  184. ~TListRepresentation() {
  185. if (Chunk_) {
  186. Chunk_->UnRef();
  187. }
  188. }
  189. TListRepresentation(const TSelf& other)
  190. : Chunk_(other.Chunk_)
  191. , Begin_(other.Begin_)
  192. , End_(other.End_)
  193. , Type_(other.Type_)
  194. {
  195. other.Type_ = Type::Freezed;
  196. if (Chunk_) {
  197. Chunk_->Ref();
  198. }
  199. }
  200. TListRepresentation(TSelf&& other)
  201. : Chunk_(other.Chunk_)
  202. , Begin_(other.Begin_)
  203. , End_(other.End_)
  204. , Type_(other.Type_)
  205. {
  206. other.Chunk_ = nullptr;
  207. other.Begin_ = nullptr;
  208. other.End_ = nullptr;
  209. other.Type_ = Type::Freezed;
  210. }
  211. void operator=(const TSelf& other) {
  212. if (this != &other) {
  213. if (other.Chunk_) {
  214. other.Chunk_->Ref();
  215. }
  216. if (Chunk_) {
  217. Chunk_->UnRef();
  218. }
  219. Chunk_ = other.Chunk_;
  220. Begin_ = other.Begin_;
  221. End_ = other.End_;
  222. Type_ = other.Type_;
  223. other.Type_ = Type::Freezed;
  224. }
  225. }
  226. void operator=(TSelf&& other) {
  227. if (Chunk_) {
  228. Chunk_->UnRef();
  229. }
  230. Chunk_ = other.Chunk_;
  231. Begin_ = other.Begin_;
  232. End_ = other.End_;
  233. Type_ = other.Type_;
  234. other.Chunk_ = nullptr;
  235. other.Begin_ = nullptr;
  236. other.End_ = nullptr;
  237. other.Type_ = Type::Freezed;
  238. }
  239. inline void FromSingleElement(T&& element) {
  240. Type_ = Type::Normal;
  241. ui64 chunkLength = (MinChunkSize + sizeof(T) - 1) / sizeof(T);
  242. Chunk_ = TChunk::AllocateChunk(chunkLength);
  243. Begin_ = Chunk_->DataBegin() + (chunkLength >> 2);
  244. End_ = Begin_ + 1;
  245. *Begin_ = std::move(element);
  246. }
  247. TListRepresentation(T&& element)
  248. {
  249. FromSingleElement(std::move(element));
  250. }
  251. TListRepresentation(T&& element, const TSelf& that)
  252. {
  253. if (!that.Chunk_) {
  254. FromSingleElement(std::move(element));
  255. return;
  256. }
  257. if ((that.Type_ == Type::Normal) && (that.Begin_ != that.Chunk_->DataBegin())) {
  258. Type_ = Type::Normal;
  259. that.Type_ = Type::Freezed;
  260. Chunk_ = that.Chunk_;
  261. Chunk_->Ref();
  262. Begin_ = that.Begin_;
  263. End_ = that.End_;
  264. *(--Begin_) = std::move(element);
  265. } else {
  266. NewNormal(&element, &element + 1, that.Begin_, that.End_);
  267. }
  268. }
  269. TListRepresentation(const TSelf& that, T&& element)
  270. {
  271. if (!that.Chunk_) {
  272. FromSingleElement(std::move(element));
  273. return;
  274. }
  275. if ((that.Type_ == Type::Normal) && (that.End_ != that.Chunk_->DataEnd())) {
  276. Type_ = Type::Normal;
  277. that.Type_ = Type::Freezed;
  278. Chunk_ = that.Chunk_;
  279. Chunk_->Ref();
  280. Begin_ = that.Begin_;
  281. End_ = that.End_ + 1;
  282. *(that.End_) = std::move(element);
  283. } else {
  284. NewNormal(that.Begin_, that.End_, &element, &element + 1);
  285. }
  286. }
  287. ui64 GetLength() const {
  288. return End_ - Begin_;
  289. }
  290. TIterator GetIterator() const {
  291. return TIterator(*this);
  292. }
  293. TReverseIterator GetReverseIterator() const {
  294. return TReverseIterator(*this);
  295. }
  296. TSelf Append(T&& right) const {
  297. return TSelf(*this, std::move(right));
  298. }
  299. TSelf Prepend(T&& left) const {
  300. return TSelf(std::move(left), *this);
  301. }
  302. TSelf MassPrepend(T* begin, T* end) const {
  303. if ((Type_ == Type::Normal) && (Chunk_->DataBegin() + (end - begin) <= Begin_)) {
  304. Type_ = Type::Freezed;
  305. return TSelf(Chunk_, std::copy_backward(begin, end, Begin_), End_, Type::Normal);
  306. } else {
  307. return TSelf(begin, end, Begin_, End_);
  308. }
  309. }
  310. TSelf MassAppend(T* begin, T* end) const {
  311. if ((Type_ == Type::Normal) && (End_ + (end - begin) <= Chunk_->DataEnd())) {
  312. Type_ = Type::Freezed;
  313. return TSelf(Chunk_, Begin_, std::copy(begin, end, End_), Type::Normal);
  314. } else {
  315. return TSelf(Begin_, End_, begin, end);
  316. }
  317. }
  318. TSelf Extend(const TSelf& right) const {
  319. ui64 thisLength = GetLength();
  320. ui64 rightLength = right.GetLength();
  321. if (!thisLength)
  322. return TSelf(right);
  323. if (!rightLength)
  324. return TSelf(*this);
  325. if (Type_ == Type::Freezed) {
  326. if (right.Type_ == Type::Freezed) {
  327. return TSelf(Begin_, End_, right.Begin_, right.End_);
  328. } else {
  329. return right.MassPrepend(Begin_, End_);
  330. }
  331. } else if ((right.Type_ == Type::Freezed) || (thisLength > rightLength)) {
  332. return MassAppend(right.Begin_, right.End_);
  333. } else {
  334. return right.MassPrepend(Begin_, End_);
  335. }
  336. }
  337. TSelf SkipFromBegin(ui64 count) const {
  338. Y_DEBUG_ABORT_UNLESS((count > 0) && (count < GetLength()));
  339. return TSelf(Chunk_, Begin_ + count, End_, Type::Freezed);
  340. }
  341. TSelf SkipFromEnd(ui64 count) const {
  342. Y_DEBUG_ABORT_UNLESS((count > 0) && (count < GetLength()));
  343. return TSelf(Chunk_, Begin_, End_ - count, Type::Freezed);
  344. }
  345. T GetItemByIndex(ui64 index) const {
  346. Y_DEBUG_ABORT_UNLESS((index >= 0) && (index < GetLength()));
  347. return Begin_[index];
  348. }
  349. T* GetItems() const {
  350. return Begin_;
  351. }
  352. private:
  353. TChunk* Chunk_;
  354. T* Begin_;
  355. T* End_;
  356. mutable Type Type_;
  357. };
  358. using TDefaultListRepresentation = TListRepresentation<NUdf::TUnboxedValue>;
  359. }
  360. }