swmr_spin_lock.cpp 1.1 KB
Newer Older
1 2 3 4 5 6 7 8 9
#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")
10
  if (write_request_.load(std::memory_order_acquire) == 1) {
11 12 13
    return false;
  }
  // We think we can enter the region
14
  readers_.fetch_add(1, std::memory_order_acquire);
15
  if (write_request_.load(std::memory_order_acquire) == 1) {
16
    // Whoops, the writer acquires the lock, so we back off again
17
    readers_.fetch_add(-1, std::memory_order_release);
18 19 20 21 22 23 24 25
    return false;
  }

  return true;
}

void swmr_spin_lock::reader_unlock() {
  PROFILE_LOCK("Release Read Lock")
26
  readers_--;
27 28 29 30 31
}

void swmr_spin_lock::writer_lock() {
  PROFILE_LOCK("Acquire Write Lock")
  // Tell the readers that we would like to write
32
  write_request_ = 1;
33

34
  // Wait for all of them to exit the critical section
35
  while (readers_ > 0)
36 37 38 39 40
    system_details::relax_cpu(); // Spin, not expensive as relaxed load
}

void swmr_spin_lock::writer_unlock() {
  PROFILE_LOCK("Release Write Lock")
41
  write_request_ = 0;
42 43 44 45 46
}

}
}
}