| 271 | EnqueueImpl(node, tail); |
| 272 | } |
| 273 | bool Dequeue(T* data) { |
| 274 | TRootNode* newRoot = nullptr; |
| 275 | TListInvertor listInvertor; |
| 276 | AsyncRef(); |
| 277 | for (TRootNode* curRoot = JobQueue.load(std::memory_order_acquire);;) { |
| 278 | TListNode* tail = curRoot->PopQueue.load(std::memory_order_acquire); |
| 279 | if (tail) { |
| 280 | // has elems to pop |
| 281 | if (!newRoot) { |
| 282 | newRoot = new TRootNode; |
| 283 | } |
| 284 | |
| 285 | newRoot->PushQueue.store(curRoot->PushQueue.load(std::memory_order_acquire), std::memory_order_release); |
| 286 | newRoot->PopQueue.store(tail->Next.load(std::memory_order_acquire), std::memory_order_release); |
| 287 | newRoot->CopyCounter(curRoot); |
| 288 | newRoot->DecCount(tail->Data); |
| 289 | Y_ASSERT(curRoot->PopQueue.load() == tail); |
| 290 | if (JobQueue.compare_exchange_weak(curRoot, newRoot)) { |
| 291 | *data = std::move(tail->Data); |
| 292 | tail->Next.store(nullptr, std::memory_order_release); |
| 293 | AsyncUnref(curRoot, tail); |
| 294 | return true; |
| 295 | } |
| 296 | continue; |
| 297 | } |
| 298 | if (curRoot->PushQueue.load(std::memory_order_acquire) == nullptr) { |
| 299 | delete newRoot; |
| 300 | AsyncUnref(); |
| 301 | return false; // no elems to pop |
| 302 | } |
| 303 | |
| 304 | if (!newRoot) { |
| 305 | newRoot = new TRootNode; |
| 306 | } |
| 307 | newRoot->PushQueue.store(nullptr, std::memory_order_release); |
| 308 | listInvertor.DoCopy(curRoot->PushQueue.load(std::memory_order_acquire)); |
| 309 | newRoot->PopQueue.store(listInvertor.Copy, std::memory_order_release); |
| 310 | newRoot->CopyCounter(curRoot); |
| 311 | Y_ASSERT(curRoot->PopQueue.load() == nullptr); |
| 312 | if (JobQueue.compare_exchange_weak(curRoot, newRoot)) { |
| 313 | AsyncDel(curRoot, curRoot->PushQueue.load(std::memory_order_acquire)); |
| 314 | curRoot = newRoot; |
| 315 | newRoot = nullptr; |
| 316 | listInvertor.CopyWasUsed(); |
| 317 | } else { |
| 318 | newRoot->PopQueue.store(nullptr, std::memory_order_release); |
| 319 | } |
| 320 | } |
| 321 | } |
| 322 | template <typename TCollection> |
| 323 | void DequeueAll(TCollection* res) { |
| 324 | AsyncRef(); |
no test coverage detected