swmr_spin_lock.cpp 1.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include "pls/internal/base/swmr_spin_lock.h"
#include "pls/internal/base/system_details.h"

namespace pls {
namespace internal {
namespace base {

bool swmr_spin_lock::reader_try_lock() {
  PROFILE_LOCK("Try Acquire Read Lock")
  if (write_request_.load(std::memory_order_relaxed) == 1) {
    return false;
  }
  // We think we can enter the region
  readers_++;
  if (write_request_.load() == 1) {
    // Whoops, the writer acquires the lock, so we back off again
    readers_--;
    return false;
  }

  return true;
}

void swmr_spin_lock::reader_unlock() {
  PROFILE_LOCK("Release Read Lock")
  readers_--;
}

void swmr_spin_lock::writer_lock() {
  PROFILE_LOCK("Acquire Write Lock")
  // Tell the readers that we would like to write
  write_request_ = 1;
  // Wait for all of them to exit the critical section
  while (readers_.load(std::memory_order_relaxed) > 0)
    system_details::relax_cpu(); // Spin, not expensive as relaxed load
}

void swmr_spin_lock::writer_unlock() {
  PROFILE_LOCK("Release Write Lock")
  write_request_ = 0;
}

}
}
}