77template <
typename Position = u
int64_t>
110 void add_link(Position from, Position to);
132 template <
typename Stop_condition>
134 uint32_t max_retry = 1);
148 Position
tail()
const;
197template <
typename Position>
199 : m_capacity(capacity), m_tail(0) {
210 for (
size_t i = 0; i <
capacity; ++i) {
215template <
typename Position>
218template <
typename Position>
220 : m_capacity(rhs.m_capacity), m_tail(rhs.m_tail.
load()) {
222 rhs.m_links =
nullptr;
225template <
typename Position>
229 m_capacity = rhs.m_capacity;
231 m_tail.store(rhs.m_tail.load());
233 m_links = rhs.m_links;
234 rhs.m_links =
nullptr;
239template <
typename Position>
244template <
typename Position>
246 if (m_links !=
nullptr) {
252template <
typename Position>
255 ut_ad(to - from <= std::numeric_limits<Distance>::max());
257 const auto index = slot_index(from);
259 auto &slot = m_links[index];
264template <
typename Position>
267 const auto index = slot_index(position);
269 auto &slot = m_links[index];
271 next = slot.load(std::memory_order_relaxed);
273 return next <= position;
276template <
typename Position>
280 ut_ad(to - from <= std::numeric_limits<Distance>::max());
282 auto position = m_tail.load(std::memory_order_acquire);
284 ut_ad(position <= from);
286 if (position == from) {
288 m_tail.store(to, std::memory_order_release);
290 auto index = slot_index(from);
291 auto &slot = m_links[index];
294 slot.store(to, std::memory_order_release);
296 auto stop_condition = [&](Position prev_pos, Position) {
297 return (prev_pos > from);
300 advance_tail_until(stop_condition);
304template <
typename Position>
305template <
typename Stop_condition>
307 uint32_t max_retry) {
309 auto position = m_tail.load(std::memory_order_acquire);
310 auto from = position;
314 auto index = slot_index(position);
315 auto &slot = m_links[index];
317 auto next_load = slot.load(std::memory_order_acquire);
319 if (next_load >= position + m_capacity) {
322 position = m_tail.load(std::memory_order_acquire);
323 if (position != from) {
329 if (next_load <= position || stop_condition(position, next_load)) {
335 if (slot.compare_exchange_strong(next_load, position,
336 std::memory_order_acq_rel)) {
342 position = m_tail.load(std::memory_order_acquire);
343 if (position == from) {
345 position = next_load;
351 if (
retry > max_retry) {
357 position = m_tail.load(std::memory_order_acquire);
358 if (position == from) {
368 bool stop = next_position(position, next);
370 if (stop || stop_condition(position, next)) {
377 ut_a(from == m_tail.load(std::memory_order_acquire));
380 m_tail.store(position, std::memory_order_release);
382 if (position == from) {
389template <
typename Position>
391 auto stop_condition = [](Position, Position) {
return false; };
393 return advance_tail_until(stop_condition);
396template <
typename Position>
401template <
typename Position>
403 return m_tail.load(std::memory_order_acquire);
406template <
typename Position>
408 auto tail = m_tail.load(std::memory_order_acquire);
409 if (tail + m_capacity > position) {
413 auto stop_condition = [](Position, Position) {
return false; };
414 advance_tail_until(stop_condition, 0);
416 tail = m_tail.load(std::memory_order_acquire);
417 return tail + m_capacity > position;
420template <
typename Position>
422 return position & (m_capacity - 1);
425template <
typename Position>
427 const auto tail = m_tail.load();
431 end = std::min(
end, begin + m_capacity);
433 for (; begin <
end; ++begin) {
434 const size_t index = slot_index(begin);
436 const auto &slot = m_links[index];
438 ut_a(slot.load() <= tail);
442template <
typename Position>
444 validate_no_links(0, m_capacity);
Concurrent data structure, which allows to track concurrently performed operations which locally migh...
Definition: ut0link_buf.h:78
bool advance_tail_until(Stop_condition stop_condition, uint32_t max_retry=1)
Advances the tail pointer in the buffer by following connected path created by links.
Definition: ut0link_buf.h:306
std::atomic< Position > m_tail
Tail pointer in the buffer (expressed in original unit).
Definition: ut0link_buf.h:194
Link_buf & operator=(const Link_buf &rhs)=delete
void add_link(Position from, Position to)
Add a directed link between two given positions.
Definition: ut0link_buf.h:253
~Link_buf()
Destructs the link buffer.
Definition: ut0link_buf.h:240
size_t m_capacity
Capacity of the buffer.
Definition: ut0link_buf.h:188
void add_link_advance_tail(Position from, Position to)
Add a directed link between two given positions.
Definition: ut0link_buf.h:277
bool has_space(Position position)
Checks if there is space to add link at given position.
Definition: ut0link_buf.h:407
bool next_position(Position position, Position &next)
Computes next position by looking into slots array and following single link which starts in provided...
Definition: ut0link_buf.h:265
void validate_no_links()
Validates (using assertions) that there no links at all.
Definition: ut0link_buf.h:443
std::atomic< Distance > * m_links
Pointer to the ring buffer (unaligned).
Definition: ut0link_buf.h:191
size_t slot_index(Position position) const
Translates position expressed in original unit to position in the m_links (which is a ring buffer).
Definition: ut0link_buf.h:421
Position Distance
Type used to express distance between two positions.
Definition: ut0link_buf.h:83
void free()
Deallocated memory, if it was allocated.
Definition: ut0link_buf.h:245
bool advance_tail()
Advances the tail pointer in the buffer without additional condition for stop.
Definition: ut0link_buf.h:390
Link_buf(const Link_buf &rhs)=delete
Link_buf()
Definition: ut0link_buf.h:216
Position tail() const
Definition: ut0link_buf.h:402
size_t capacity() const
Definition: ut0link_buf.h:397
Link_buf & operator=(Link_buf &&rhs)
Definition: ut0link_buf.h:226
#define free(A)
Definition: lexyy.cc:915
bool load(THD *, const dd::String_type &fname, dd::String_type *buf)
Read an sdi file from disk and store in a buffer.
Definition: sdi_file.cc:308
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
constexpr size_t INNODB_CACHE_LINE_SIZE
CPU cache line size.
Definition: ut0cpu_cache.h:41
void delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new_arr*() variants.
Definition: ut0new.h:1109
Light-weight and type-safe wrapper which serves a purpose of being able to select proper ut::new_arr*...
Definition: ut0new.h:981
Debug utilities for Innobase.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:69
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:57
Dynamic memory allocation routines and custom allocators specifically crafted to support memory instr...
#define UT_NEW_THIS_FILE_PSI_KEY
Definition: ut0new.h:564
#define UT_RELAX_CPU()
Definition: ut0ut.h:87
static task_env * retry
Definition: xcom_base.cc:436