Busy waiting added

This commit is contained in:
Nekotekina 2017-02-15 18:07:42 +03:00
parent b637bd3866
commit b1aa87b515
7 changed files with 196 additions and 373 deletions

View file

@ -9,8 +9,7 @@ class shared_mutex final
enum : s64
{
c_one = 1ull << 31, // Fixed-point 1.0 value (one writer)
c_min = 0x00000002, // Fixed-point 1.0/max_readers value
c_sig = 0x00000001,
c_min = 0x00000001, // Fixed-point 1.0/max_readers value
c_max = c_one
};
@ -18,7 +17,7 @@ class shared_mutex final
void imp_lock_shared(s64 _old);
void imp_unlock_shared(s64 _old);
void imp_wait(s64 _old);
void imp_lock(s64 _old);
void imp_unlock(s64 _old);
@ -56,8 +55,8 @@ public:
void lock()
{
// Unconditional decrement
const s64 value = m_value.fetch_sub(c_one);
// Try to lock
const s64 value = m_value.compare_and_swap(c_one, 0);
if (value != c_one)
{
@ -80,7 +79,6 @@ public:
void lock_upgrade()
{
// TODO
if (!m_value.compare_and_swap_test(c_one - c_min, 0))
{
imp_lock_upgrade();
@ -91,7 +89,6 @@ public:
void lock_degrade()
{
// TODO
if (!m_value.compare_and_swap_test(0, c_one - c_min))
{
imp_lock_degrade();
@ -103,15 +100,16 @@ public:
class reader_lock final
{
shared_mutex& m_mutex;
bool m_upgraded = false;
void lock()
{
m_mutex.lock_shared();
m_upgraded ? m_mutex.lock() : m_mutex.lock_shared();
}
void unlock()
{
m_mutex.unlock_shared();
m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared();
}
friend class cond_variable;
@ -125,6 +123,16 @@ public:
lock();
}
// One-way lock upgrade
void upgrade()
{
if (!m_upgraded)
{
m_mutex.lock_upgrade();
m_upgraded = true;
}
}
~reader_lock()
{
unlock();
@ -136,95 +144,29 @@ class writer_lock final
{
shared_mutex& m_mutex;
void lock()
{
m_mutex.lock();
}
void unlock()
{
m_mutex.unlock();
}
friend class cond_variable;
public:
writer_lock(const writer_lock&) = delete;
explicit writer_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock();
lock();
}
~writer_lock()
{
m_mutex.unlock();
}
};
// Exclusive (writer) lock in the scope of shared (reader) lock (experimental).
class upgraded_lock final
{
shared_mutex& m_mutex;
public:
upgraded_lock(const writer_lock&) = delete;
explicit upgraded_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock_upgrade();
}
~upgraded_lock()
{
m_mutex.lock_degrade();
}
};
// Normal mutex with owner registration.
class owned_mutex
{
atomic_t<u32> m_value{0};
atomic_t<u32> m_owner{0};
protected:
// Thread id
static thread_local const u32 g_tid;
public:
constexpr owned_mutex() = default;
// Returns false if current thread already owns the mutex.
bool lock() noexcept;
// Returns false if locked by any thread.
bool try_lock() noexcept;
// Returns false if current thread doesn't own the mutex.
bool unlock() noexcept;
// Check state.
bool is_locked() const { return m_value != 0; }
// Check owner.
bool is_owned() const { return m_owner == g_tid; }
};
// Recursive lock for owned_mutex (experimental).
class recursive_lock final
{
owned_mutex& m_mutex;
const bool m_first;
public:
recursive_lock(const recursive_lock&) = delete;
explicit recursive_lock(owned_mutex& mutex)
: m_mutex(mutex)
, m_first(mutex.lock())
{
}
// Check whether the lock "owns" the mutex
explicit operator bool() const
{
return m_first;
}
~recursive_lock()
{
if (m_first && !m_mutex.unlock())
{
}
unlock();
}
};