Skip to content

Commit

Permalink
Protect assignment of StripDetset() StMeasurementDetSet::getDetSet()
Browse files Browse the repository at this point in the history
The assigment is a critical section and must be protected.
  • Loading branch information
makortel committed Jun 12, 2023
1 parent af93dcc commit cdda666
Showing 1 changed file with 23 additions and 8 deletions.
31 changes: 23 additions & 8 deletions RecoTracker/MeasurementDet/src/TkMeasurementDetSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
Expand All @@ -208,7 +208,7 @@ class StMeasurementDetSet {
const edm::Handle<edmNew::DetSetVector<SiStripCluster>>& 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_;
}
Expand Down Expand Up @@ -236,13 +236,22 @@ class StMeasurementDetSet {
// edmNew::DetSet<T>::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;
Expand All @@ -252,12 +261,18 @@ class StMeasurementDetSet {
// Globals, per-event
edm::Handle<edmNew::DetSetVector<SiStripCluster>> 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<bool> empty_ = true;
mutable std::atomic<bool> ready_ = true; // to be cleaned
mutable std::atomic<ReadyState> 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_;
};
Expand Down

0 comments on commit cdda666

Please sign in to comment.