| 566 | } |
| 567 | |
| 568 | inline void set_value(const InternalIndex internal_index, const T value) |
| 569 | { |
| 570 | // ⚠ The method uses CAS spinlocks to prevent data races in parallel calls |
| 571 | // TBB internal atomic's are used for CAS on non-atomic data |
| 572 | // Parallel read and write access is not allowed |
| 573 | |
| 574 | auto &lower_word = vec[internal_index.lower_word]; |
| 575 | auto &upper_word = vec[internal_index.lower_word + 1]; |
| 576 | |
| 577 | // Lock-free update of the lower word |
| 578 | WordT local_lower_word, new_lower_word; |
| 579 | do |
| 580 | { |
| 581 | local_lower_word = lower_word; |
| 582 | new_lower_word = set_lower_value<WordT, T>(local_lower_word, |
| 583 | lower_mask[internal_index.element], |
| 584 | lower_offset[internal_index.element], |
| 585 | value); |
| 586 | } while (!compare_and_swap(&lower_word, local_lower_word, new_lower_word)); |
| 587 | |
| 588 | // Lock-free update of the upper word |
| 589 | WordT local_upper_word, new_upper_word; |
| 590 | do |
| 591 | { |
| 592 | local_upper_word = upper_word; |
| 593 | new_upper_word = set_upper_value<WordT, T>(local_upper_word, |
| 594 | upper_mask[internal_index.element], |
| 595 | upper_offset[internal_index.element], |
| 596 | value); |
| 597 | } while (!compare_and_swap(&upper_word, local_upper_word, new_upper_word)); |
| 598 | } |
| 599 | |
| 600 | util::ViewOrVector<WordT, Ownership> vec; |
| 601 | std::uint64_t num_elements = 0; |
no test coverage detected