Permalink
Browse files

New shared_mutex

Experimental sync utils
New semaphore<>
New cond_variable
New owned_mutex
  • Loading branch information...
1 parent 98fc131 commit 1c14d872a852ae7cd5c9281dc14de8077b4d65a9 @Nekotekina Nekotekina committed with Nekotekina Jan 24, 2017
View
@@ -300,21 +300,24 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
static inline bool bts(T& dest, uint bit)
{
bool result;
- __asm__("lock btsw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
+ ushort _bit = (ushort)bit;
+ __asm__("lock btsw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btr(T& dest, uint bit)
{
bool result;
- __asm__("lock btrw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
+ ushort _bit = (ushort)bit;
+ __asm__("lock btrw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btc(T& dest, uint bit)
{
bool result;
- __asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
+ ushort _bit = (ushort)bit;
+ __asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
return result;
}
#endif
@@ -498,21 +501,24 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
static inline bool bts(T& dest, uint bit)
{
bool result;
- __asm__("lock btsq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
+ ullong _bit = bit;
+ __asm__("lock btsq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btr(T& dest, uint bit)
{
bool result;
- __asm__("lock btrq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
+ ullong _bit = bit;
+ __asm__("lock btrq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
return result;
}
static inline bool btc(T& dest, uint bit)
{
bool result;
- __asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
+ ullong _bit = bit;
+ __asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
return result;
}
#endif
View
@@ -1,6 +1,6 @@
#include "File.h"
+#include "mutex.h"
#include "StrFmt.h"
-#include "SharedMutex.h"
#include "BEType.h"
#include "Crypto/sha1.h"
@@ -1,90 +0,0 @@
-#include "Utilities/Semaphore.h"
-
-#include <mutex>
-#include <condition_variable>
-
-struct benaphore::internal
-{
- std::mutex mutex;
-
- std::size_t acq_order{};
- std::size_t rel_order{};
-
- std::condition_variable cond;
-};
-
-void benaphore::wait_hard()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- // Notify non-zero waiter queue size
- if (m_value.exchange(-1) == 1)
- {
- // Return immediately (acquired)
- m_value = 0;
- return;
- }
-
- // Remember the order
- const std::size_t order = ++m_data->acq_order;
-
- // Wait for the appropriate rel_order (TODO)
- while (m_data->rel_order < order)
- {
- m_data->cond.wait(lock);
- }
-
- if (order == m_data->acq_order && m_data->acq_order == m_data->rel_order)
- {
- // Cleaup
- m_data->acq_order = 0;
- m_data->rel_order = 0;
- m_value.compare_and_swap(-1, 0);
- }
-}
-
-void benaphore::post_hard()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- if (m_value.compare_and_swap(0, 1) != -1)
- {
- // Do nothing (released)
- return;
- }
-
- if (m_data->acq_order == m_data->rel_order)
- {
- m_value = 1;
- return;
- }
-
- // Awake one thread
- m_data->rel_order += 1;
-
- // Unlock and notify
- lock.unlock();
- m_data->cond.notify_one();
-}
-
-void benaphore::initialize_once()
-{
- if (UNLIKELY(!m_data))
- {
- auto ptr = new benaphore::internal;
-
- if (!m_data.compare_and_swap_test(nullptr, ptr))
- {
- delete ptr;
- }
- }
-}
-
-benaphore::~benaphore()
-{
- delete m_data;
-}
View
@@ -1,47 +0,0 @@
-#pragma once
-
-#include "types.h"
-#include "Atomic.h"
-
-// Binary semaphore
-class benaphore
-{
- struct internal;
-
- // Reserved value (-1) enforces *_hard() calls
- atomic_t<u32> m_value{};
-
- atomic_t<internal*> m_data{};
-
- void wait_hard();
- void post_hard();
-
-public:
- constexpr benaphore() = default;
-
- ~benaphore();
-
- // Initialize internal data
- void initialize_once();
-
- void wait()
- {
- if (UNLIKELY(!m_value.compare_and_swap_test(1, 0)))
- {
- wait_hard();
- }
- }
-
- bool try_wait()
- {
- return m_value.compare_and_swap_test(1, 0);
- }
-
- void post()
- {
- if (UNLIKELY(!m_value.compare_and_swap_test(0, 1)))
- {
- post_hard();
- }
- }
-};
@@ -1,187 +0,0 @@
-#include "SharedMutex.h"
-
-#include <mutex>
-#include <condition_variable>
-
-struct shared_mutex::internal
-{
- std::mutex mutex;
-
- std::size_t rq_size{}; // Reader queue size (threads waiting on m_rcv)
- std::size_t wq_size{}; // Writer queue size (threads waiting on m_wcv and m_ocv)
-
- std::condition_variable rcv; // Reader queue
- std::condition_variable wcv; // Writer queue
- std::condition_variable ocv; // For current exclusive owner
-};
-
-void shared_mutex::lock_shared_hard()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- // Validate
- if ((m_ctrl & SM_INVALID_BIT) != 0) throw std::runtime_error("shared_mutex::lock_shared(): Invalid bit");
- if ((m_ctrl & SM_READER_MASK) == 0) throw std::runtime_error("shared_mutex::lock_shared(): No readers");
-
- // Notify non-zero reader queue size
- m_ctrl |= SM_WAITERS_BIT, m_data->rq_size++;
-
- // Fix excess reader count
- if ((--m_ctrl & SM_READER_MASK) == 0 && m_data->wq_size)
- {
- // Notify exclusive owner
- m_data->ocv.notify_one();
- }
-
- // Obtain the reader lock
- while (true)
- {
- const auto ctrl = m_ctrl.load();
-
- // Check writers and reader limit
- if (m_data->wq_size || (ctrl & ~SM_WAITERS_BIT) >= SM_READER_MAX)
- {
- m_data->rcv.wait(lock);
- continue;
- }
-
- if (m_ctrl.compare_and_swap_test(ctrl, ctrl + 1))
- {
- break;
- }
- }
-
- if (!--m_data->rq_size && !m_data->wq_size)
- {
- m_ctrl &= ~SM_WAITERS_BIT;
- }
-}
-
-void shared_mutex::unlock_shared_notify()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- if ((m_ctrl & SM_READER_MASK) == 0 && m_data->wq_size)
- {
- // Notify exclusive owner
- lock.unlock();
- m_data->ocv.notify_one();
- }
- else if (m_data->rq_size)
- {
- // Notify other readers
- lock.unlock();
- m_data->rcv.notify_one();
- }
-}
-
-void shared_mutex::lock_hard()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- // Validate
- if ((m_ctrl & SM_INVALID_BIT) != 0) throw std::runtime_error("shared_mutex::lock(): Invalid bit");
-
- // Notify non-zero writer queue size
- m_ctrl |= SM_WAITERS_BIT, m_data->wq_size++;
-
- // Obtain the writer lock
- while (true)
- {
- const auto ctrl = m_ctrl.load();
-
- if (ctrl & SM_WRITER_LOCK)
- {
- m_data->wcv.wait(lock);
- continue;
- }
-
- if (m_ctrl.compare_and_swap_test(ctrl, ctrl | SM_WRITER_LOCK))
- {
- break;
- }
- }
-
- // Wait for remaining readers
- while ((m_ctrl & SM_READER_MASK) != 0)
- {
- m_data->ocv.wait(lock);
- }
-
- if (!--m_data->wq_size && !m_data->rq_size)
- {
- m_ctrl &= ~SM_WAITERS_BIT;
- }
-}
-
-void shared_mutex::unlock_notify()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- if (m_data->wq_size)
- {
- // Notify next exclusive owner
- lock.unlock();
- m_data->wcv.notify_one();
- }
- else if (m_data->rq_size)
- {
- // Notify all readers
- lock.unlock();
- m_data->rcv.notify_all();
- }
-}
-
-void shared_mutex::lock_upgrade_hard()
-{
- unlock_shared();
- lock();
-}
-
-void shared_mutex::lock_degrade_hard()
-{
- initialize_once();
-
- std::unique_lock<std::mutex> lock(m_data->mutex);
-
- m_ctrl -= SM_WRITER_LOCK - 1;
-
- if (m_data->rq_size)
- {
- // Notify all readers
- lock.unlock();
- m_data->rcv.notify_all();
- }
- else if (m_data->wq_size)
- {
- // Notify next exclusive owner
- lock.unlock();
- m_data->wcv.notify_one();
- }
-}
-
-void shared_mutex::initialize_once()
-{
- if (UNLIKELY(!m_data))
- {
- auto ptr = new shared_mutex::internal;
-
- if (!m_data.compare_and_swap_test(nullptr, ptr))
- {
- delete ptr;
- }
- }
-}
-
-shared_mutex::~shared_mutex()
-{
- delete m_data;
-}
Oops, something went wrong.

0 comments on commit 1c14d87

Please sign in to comment.