On May 2, 2014 1:37:46 AM EDT, Antony Polukhin
This is just a refining of idea that was once implemented and worked well. The idea was to make shared spin lock. Here is some pseudo-code:
class shared_spin_lock { atomic_max_uint_t state_;
lock_shared() { do { // CAS loop auto snapshot = state_.load(); if (snapshot.has_writer_bit_set()) { reader_wait(); // waiting for writer to finish continue; }
auto new_state = snapshot + 1; } while(!CAS(state, new_state)); }
unlock_shared() { --state; }
lock() { do { // CAS loop auto snapshot = state_.load(); if (snapshot.has_writer_bit_set()) { writer_wait(); // waiting for other writer to finish continue; }
auto new_state = snapshot.set_writer_bit(); } while(!CAS(state, new_state));
Why wouldn't you set the writer bit once you own the mutex? As it is, you release the mutex and the use CAS to try to set it, but no other writer can set it when you hold the mutex.
// we have set the writer bit, now waiting for readers to finish while (state_.readers_count) ; // busy loop, can we do better?
Run the busy loop a limited number of times before adding a yield or sleep instruction, then repeat.
writer_started(); }
unlock() { auto snapshot = state_.reset_writer_bit(); writer_finished(); ASSERT (snapshot.has_writer_bit_set()); }
};
When all the *_wait() and writer_*() functions do nothing we get a shared spinlock.
Now if we add helper mutex and make all the *_wait() functions to lock and unlock mutex; writer_start() - lock the mutex; writer finished() - unlock the mutex... we get a simplified shared_mutex that is faster (in theory) than current implementation.
I haven't seen the code to which you're comparing this implementation, so I have no idea whether it is faster. ___ Rob (Sent from my portable computation engine)