---------------------ExecutionQueueBase--------------------
| 481 | |
| 482 | // ---------------------ExecutionQueueBase-------------------- |
| 483 | inline bool ExecutionQueueBase::_more_tasks( |
| 484 | TaskNode* old_head, TaskNode** new_tail, |
| 485 | bool has_uniterated) { |
| 486 | |
| 487 | CHECK(old_head->next == NULL); |
| 488 | // Try to set _head to NULL to mark that the execute is done. |
| 489 | TaskNode* new_head = old_head; |
| 490 | TaskNode* desired = NULL; |
| 491 | bool return_when_no_more = false; |
| 492 | if (has_uniterated) { |
| 493 | desired = old_head; |
| 494 | return_when_no_more = true; |
| 495 | } |
| 496 | if (_head.compare_exchange_strong( |
| 497 | new_head, desired, butil::memory_order_acquire)) { |
| 498 | // No one added new tasks. |
| 499 | return return_when_no_more; |
| 500 | } |
| 501 | CHECK_NE(new_head, old_head); |
| 502 | // Above acquire fence pairs release fence of exchange in Write() to make |
| 503 | // sure that we see all fields of requests set. |
| 504 | |
| 505 | // Someone added new requests. |
| 506 | // Reverse the list until old_head. |
| 507 | TaskNode* tail = NULL; |
| 508 | if (new_tail) { |
| 509 | *new_tail = new_head; |
| 510 | } |
| 511 | TaskNode* p = new_head; |
| 512 | do { |
| 513 | while (p->next == TaskNode::UNCONNECTED) { |
| 514 | // TODO(gejun): elaborate this |
| 515 | sched_yield(); |
| 516 | } |
| 517 | TaskNode* const saved_next = p->next; |
| 518 | p->next = tail; |
| 519 | tail = p; |
| 520 | p = saved_next; |
| 521 | CHECK(p != NULL); |
| 522 | } while (p != old_head); |
| 523 | |
| 524 | // Link old list with new list. |
| 525 | old_head->next = tail; |
| 526 | return true; |
| 527 | } |
| 528 | |
| 529 | inline int ExecutionQueueBase::dereference() { |
| 530 | const uint64_t vref = _versioned_ref.fetch_sub( |
no test coverage detected