+/** hazptr_tc - functions */
+
+inline void hazptr_tc_entry::fill(hazptr_rec* hprec, hazptr_domain* domain) {
+ hprec_.store(hprec, std::memory_order_release);
+ domain_.store(domain, std::memory_order_release);
+ hprec->tc_.store(this, std::memory_order_release);
+ DEBUG_PRINT(this << " " << domain << " " << hprec);
+}
+
+inline hazptr_rec* hazptr_tc_entry::get(hazptr_domain* domain) {
+ if (domain == domain_.load(std::memory_order_acquire)) {
+ auto hprec = hprec_.load(std::memory_order_acquire);
+ if (hprec) {
+ hprec_.store(nullptr, std::memory_order_release);
+ DEBUG_PRINT(this << " " << domain << " " << hprec);
+ return hprec;
+ }
+ }
+ return nullptr;
+}
+
+inline void hazptr_tc_entry::invalidate(hazptr_rec* hprec) {
+ DCHECK_EQ(hprec, hprec_);
+ hprec_.store(nullptr, std::memory_order_release);
+ domain_.store(nullptr, std::memory_order_release);
+ hprec->tc_.store(nullptr, std::memory_order_relaxed);
+ hprec->release();
+ DEBUG_PRINT(this << " " << hprec);
+}
+
+inline void hazptr_tc_entry::evict() {
+ auto hprec = hprec_.load(std::memory_order_relaxed);
+ if (hprec) {
+ hazptr_tc_guard g(hazptr_tc_lock());
+ hprec = hprec_.load(std::memory_order_relaxed);
+ if (hprec) {
+ invalidate(hprec);
+ }
+ }
+ DEBUG_PRINT(hprec);
+}
+
+inline hazptr_tc::hazptr_tc() {
+ DEBUG_PRINT(this);
+}
+
+inline hazptr_tc::~hazptr_tc() {
+ DEBUG_PRINT(this);
+ for (int i = 0; i < HAZPTR_TC_SIZE; ++i) {
+ tc_[i].evict();
+ }
+}
+
+inline hazptr_rec* hazptr_tc::get(hazptr_domain* domain) {
+ for (int i = 0; i < HAZPTR_TC_SIZE; ++i) {
+ auto hprec = tc_[i].get(domain);
+ if (hprec) {
+ DEBUG_PRINT(this << " " << domain << " " << hprec);
+ return hprec;
+ }
+ }
+ DEBUG_PRINT(this << " " << domain << " nullptr");
+ return nullptr;
+}
+
+inline bool hazptr_tc::put(hazptr_rec* hprec, hazptr_domain* domain) {
+ int other = HAZPTR_TC_SIZE;
+ for (int i = 0; i < HAZPTR_TC_SIZE; ++i) {
+ if (tc_[i].hprec_.load(std::memory_order_acquire) == nullptr) {
+ tc_[i].fill(hprec, domain);
+ DEBUG_PRINT(this << " " << i);
+ return true;
+ }
+ if (tc_[i].domain_.load(std::memory_order_relaxed) != domain) {
+ other = i;
+ }
+ }
+ if (other < HAZPTR_TC_SIZE) {
+ tc_[other].evict();
+ tc_[other].fill(hprec, domain);
+ DEBUG_PRINT(this << " " << other);
+ return true;
+ }
+ return false;
+}
+
+inline class hazptr_tc& hazptr_tc() {
+ static thread_local class hazptr_tc tc;
+ DEBUG_PRINT(&tc);
+ return tc;
+}
+
+inline std::mutex& hazptr_tc_lock() {
+ static std::mutex m;
+ DEBUG_PRINT(&m);
+ return m;
+}
+