#pragma once #include <atomic> #include"my_dbug.h"
/** Simple read-write lock based on std::atomic */ class rw_lock
{ /** The lock word */
std::atomic<uint32_t> lock;
protected: /** Available lock */ static constexpr uint32_t UNLOCKED= 0; /** Flag to indicate that write_lock() is being held */ static constexpr uint32_t WRITER= 1U << 31; /** Flag to indicate that write_lock_wait() is pending */ static constexpr uint32_t WRITER_WAITING= 1U << 30; /** Flag to indicate that write_lock() or write_lock_wait() is pending */ static constexpr uint32_t WRITER_PENDING= WRITER | WRITER_WAITING;
/** Start waiting for an exclusive lock. */ void write_lock_wait_start()
{
lock.fetch_or(WRITER_WAITING, std::memory_order_relaxed);
} /** Start waiting for an exclusive lock.
@return current value of the lock word */
uint32_t write_lock_wait_start_read()
{ return lock.fetch_or(WRITER_WAITING, std::memory_order_relaxed); } /** Wait for an exclusive lock. @paramlthevalueofthelockword
@return whether the exclusive lock was acquired */ bool write_lock_wait_try(uint32_t &l)
{ return lock.compare_exchange_strong(l, WRITER, std::memory_order_acquire,
std::memory_order_relaxed);
} /** Try to acquire a shared lock. @paramlthevalueofthelockword
@return whether the lock was acquired */ bool read_trylock(uint32_t &l)
{
l= UNLOCKED; while (!lock.compare_exchange_strong(l, l + 1, std::memory_order_acquire,
std::memory_order_relaxed))
{
DBUG_ASSERT(!(WRITER & l) || !(~WRITER_PENDING & l)); if (l & WRITER_PENDING) returnfalse;
} returntrue;
}
/** Wait for an exclusive lock.
@return whether the exclusive lock was acquired */ bool write_lock_poll()
{ auto l= WRITER_WAITING; if (write_lock_wait_try(l)) returntrue; if (!(l & WRITER_WAITING)) /* write_lock() must have succeeded for another thread */
write_lock_wait_start(); returnfalse;
} /** @return the lock word value */
uint32_t value() const { return lock.load(std::memory_order_acquire); }
/** Release a shared lock.
@return whether any writers may have to be woken up */ bool read_unlock()
{ auto l= lock.fetch_sub(1, std::memory_order_release);
DBUG_ASSERT(!(l & WRITER)); /* no write lock must have existed */
DBUG_ASSERT(~(WRITER_PENDING) & l); /* at least one read lock */ return (~WRITER_PENDING & l) == 1;
} /** Release an exclusive lock */ void write_unlock()
{ /* Below, we use fetch_sub(WRITER) instead of fetch_and(~WRITER). ThereasonisthatonIA-32andAMD64ittranslatesintothe80486 instructionLOCKXADD,whilefetch_and()translatesintoaloop
around LOCK CMPXCHG. For other ISA either form should be fine. */
static_assert(WRITER == 1U << 31, "compatibility");
IF_DBUG_ASSERT(auto l=,) lock.fetch_sub(WRITER, std::memory_order_release); /* the write lock must have existed */
DBUG_ASSERT(l & WRITER);
} /** Try to acquire a shared lock.
@return whether the lock was acquired */ bool read_trylock() { uint32_t l; return read_trylock(l); } /** Try to acquire an exclusive lock.
@return whether the lock was acquired */ bool write_trylock()
{ auto l= UNLOCKED; return lock.compare_exchange_strong(l, WRITER, std::memory_order_acquire,
std::memory_order_relaxed);
}
/** @return whether an exclusive lock is being held by any thread */ bool is_write_locked() const { return !!(value() & WRITER); } /** @return whether any lock is being held or waited for by any thread */ bool is_locked_or_waiting() const { return value() != 0; } /** @return whether any lock is being held by any thread */ bool is_locked() const { return (value() & ~WRITER_WAITING) != 0; }
};
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.