diff --git a/RecoTracker/MeasurementDet/src/TkMeasurementDetSet.h b/RecoTracker/MeasurementDet/src/TkMeasurementDetSet.h index 92a85c6a5603e..39c32acfd2a89 100644 --- a/RecoTracker/MeasurementDet/src/TkMeasurementDetSet.h +++ b/RecoTracker/MeasurementDet/src/TkMeasurementDetSet.h @@ -165,7 +165,7 @@ class StMeasurementDetSet { void update(int i, int j) { assert(j >= 0); assert(detSet_[i].empty_); - assert(detSet_[i].ready_); + assert(detSet_[i].ready_ == ReadyState::kUnset); detIndex_[i] = j; detSet_[i].empty_ = false; incReady(); @@ -189,7 +189,7 @@ class StMeasurementDetSet { printStat(); for (auto& d : detSet_) { d.empty_ = true; - d.ready_ = true; + d.ready_ = ReadyState::kUnset; } std::fill(detIndex_.begin(), detIndex_.end(), -1); std::fill(activeThisEvent_.begin(), activeThisEvent_.end(), true); @@ -208,7 +208,7 @@ class StMeasurementDetSet { const edm::Handle>& handle() const { return handle_; } // StripDetset & detSet(int i) { return detSet_[i]; } const StripDetset& detSet(int i) const { - if (detSet_[i].ready_) + if (detSet_[i].ready_ == ReadyState::kUnset) getDetSet(i); return detSet_[i].detSet_; } @@ -236,13 +236,22 @@ class StMeasurementDetSet { // edmNew::DetSet::set() internally does an atomic update det.detSet_.set(*handle_, handle_->item(detIndex_[i])); det.empty_ = false; // better be false already + det.ready_ = ReadyState::kSet; incAct(); + incSet(); } else { // we should not be here - det.detSet_ = StripDetset(); - det.empty_ = true; + ReadyState expected = ReadyState::kUnset; + if (det.ready_.compare_exchange_strong(expected, ReadyState::kSetting, std::memory_order_acq_rel)) { + det.detSet_ = StripDetset(); + det.empty_ = true; + det.ready_ = ReadyState::kSet; + incSet(); + } else { + // need to wait + while (ReadyState::kSet != det.ready_.load(std::memory_order_acquire)) { + } + } } - det.ready_ = false; - incSet(); } friend class MeasurementTrackerImpl; @@ -252,12 +261,18 @@ class StMeasurementDetSet { // Globals, per-event edm::Handle> handle_; + enum class ReadyState : char { + kUnset, + kSetting, + kSet + }; + // Helper struct to define only the vector elements as mutable and // to have a vector of atomics without an explicit loop over // elements to set their values struct DetSetHelper { mutable std::atomic empty_ = true; - mutable std::atomic ready_ = true; // to be cleaned + mutable std::atomic ready_ = ReadyState::kUnset; // to be cleaned // only thread-safe non-const member functions are called from a const function CMS_THREAD_SAFE mutable StripDetset detSet_; };