76template <
typename Position = u
int64_t>
109 void add_link(Position from, Position to);
131 template <
typename Stop_condition>
133 uint32_t max_retry = 1);
147 Position
tail()
const;
196template <
typename Position>
198 : m_capacity(capacity), m_tail(0) {
209 for (
size_t i = 0; i <
capacity; ++i) {
214template <
typename Position>
217template <
typename Position>
219 : m_capacity(rhs.m_capacity), m_tail(rhs.m_tail.
load()) {
221 rhs.m_links =
nullptr;
224template <
typename Position>
228 m_capacity = rhs.m_capacity;
230 m_tail.store(rhs.m_tail.load());
232 m_links = rhs.m_links;
233 rhs.m_links =
nullptr;
238template <
typename Position>
243template <
typename Position>
245 if (m_links !=
nullptr) {
251template <
typename Position>
254 ut_ad(to - from <= std::numeric_limits<Distance>::max());
256 const auto index = slot_index(from);
258 auto &slot = m_links[index];
263template <
typename Position>
266 const auto index = slot_index(position);
268 auto &slot = m_links[index];
270 next = slot.load(std::memory_order_relaxed);
272 return next <= position;
275template <
typename Position>
279 ut_ad(to - from <= std::numeric_limits<Distance>::max());
281 auto position = m_tail.load(std::memory_order_acquire);
283 ut_ad(position <= from);
285 if (position == from) {
287 m_tail.store(to, std::memory_order_release);
289 auto index = slot_index(from);
290 auto &slot = m_links[index];
293 slot.store(to, std::memory_order_release);
295 auto stop_condition = [&](Position prev_pos, Position) {
296 return (prev_pos > from);
299 advance_tail_until(stop_condition);
303template <
typename Position>
304template <
typename Stop_condition>
306 uint32_t max_retry) {
308 auto position = m_tail.load(std::memory_order_acquire);
309 auto from = position;
313 auto index = slot_index(position);
314 auto &slot = m_links[index];
316 auto next_load = slot.load(std::memory_order_acquire);
318 if (next_load >= position + m_capacity) {
321 position = m_tail.load(std::memory_order_acquire);
322 if (position != from) {
328 if (next_load <= position || stop_condition(position, next_load)) {
334 if (slot.compare_exchange_strong(next_load, position,
335 std::memory_order_acq_rel)) {
341 position = m_tail.load(std::memory_order_acquire);
342 if (position == from) {
344 position = next_load;
350 if (
retry > max_retry) {
356 position = m_tail.load(std::memory_order_acquire);
357 if (position == from) {
367 bool stop = next_position(position, next);
369 if (stop || stop_condition(position, next)) {
376 ut_a(from == m_tail.load(std::memory_order_acquire));
379 m_tail.store(position, std::memory_order_release);
381 if (position == from) {
388template <
typename Position>
390 auto stop_condition = [](Position, Position) {
return false; };
392 return advance_tail_until(stop_condition);
395template <
typename Position>
400template <
typename Position>
402 return m_tail.load(std::memory_order_acquire);
405template <
typename Position>
407 auto tail = m_tail.load(std::memory_order_acquire);
408 if (tail + m_capacity > position) {
412 auto stop_condition = [](Position, Position) {
return false; };
413 advance_tail_until(stop_condition, 0);
415 tail = m_tail.load(std::memory_order_acquire);
416 return tail + m_capacity > position;
419template <
typename Position>
421 return position & (m_capacity - 1);
424template <
typename Position>
426 const auto tail = m_tail.load();
430 end = std::min(
end, begin + m_capacity);
432 for (; begin <
end; ++begin) {
433 const size_t index = slot_index(begin);
435 const auto &slot = m_links[index];
437 ut_a(slot.load() <= tail);
441template <
typename Position>
443 validate_no_links(0, m_capacity);
Concurrent data structure, which allows to track concurrently performed operations which locally migh...
Definition: ut0link_buf.h:77
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:305
std::atomic< Position > m_tail
Tail pointer in the buffer (expressed in original unit).
Definition: ut0link_buf.h:193
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:252
~Link_buf()
Destructs the link buffer.
Definition: ut0link_buf.h:239
size_t m_capacity
Capacity of the buffer.
Definition: ut0link_buf.h:187
void add_link_advance_tail(Position from, Position to)
Add a directed link between two given positions.
Definition: ut0link_buf.h:276
bool has_space(Position position)
Checks if there is space to add link at given position.
Definition: ut0link_buf.h:406
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:264
void validate_no_links()
Validates (using assertions) that there no links at all.
Definition: ut0link_buf.h:442
std::atomic< Distance > * m_links
Pointer to the ring buffer (unaligned).
Definition: ut0link_buf.h:190
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:420
Position Distance
Type used to express distance between two positions.
Definition: ut0link_buf.h:82
void free()
Deallocated memory, if it was allocated.
Definition: ut0link_buf.h:244
bool advance_tail()
Advances the tail pointer in the buffer without additional condition for stop.
Definition: ut0link_buf.h:389
Link_buf(const Link_buf &rhs)=delete
Link_buf()
Definition: ut0link_buf.h:215
Position tail() const
Definition: ut0link_buf.h:401
size_t capacity() const
Definition: ut0link_buf.h:396
Link_buf & operator=(Link_buf &&rhs)
Definition: ut0link_buf.h:225
#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:307
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:191
constexpr size_t INNODB_CACHE_LINE_SIZE
CPU cache line size.
Definition: ut0cpu_cache.h:40
void delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new_arr*() variants.
Definition: ut0new.h:1107
Light-weight and type-safe wrapper which serves a purpose of being able to select proper ut::new_arr*...
Definition: ut0new.h:979
Debug utilities for Innobase.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:68
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:56
Dynamic memory allocation routines and custom allocators specifically crafted to support memory instr...
#define UT_NEW_THIS_FILE_PSI_KEY
Definition: ut0new.h:562
#define UT_RELAX_CPU()
Definition: ut0ut.h:86
static task_env * retry
Definition: xcom_base.cc:435