Skip to content

Commit

Permalink
Merge pull request #205 from vkuznet/ThreadSafe_TransientTrack
Browse files Browse the repository at this point in the history
Thread safe TransientTrack package
  • Loading branch information
ktf committed Aug 2, 2013
2 parents 1c24c1c + 8c3c48e commit 99bb122
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 129 deletions.
198 changes: 104 additions & 94 deletions TrackingTools/TransientTrack/interface/TrackTransientTrack.h
@@ -1,94 +1,104 @@
#ifndef TrackReco_TrackTransientTrack_h
#define TrackReco_TrackTransientTrack_h

/**
* Concrete implementation of the TransientTrack for a reco::Track
*/

#include "TrackingTools/TransientTrack/interface/BasicTransientTrack.h"
#include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
#include "DataFormats/TrackReco/interface/Track.h"
#include "DataFormats/TrackReco/interface/TrackFwd.h"
#include "TrackingTools/PatternTools/interface/TSCPBuilderNoMaterial.h"

namespace reco {

class TrackTransientTrack : public Track, public BasicTransientTrack {
public:

// constructor from persistent track
TrackTransientTrack();
TrackTransientTrack( const Track & tk , const MagneticField* field);
TrackTransientTrack( const TrackRef & tk , const MagneticField* field);

TrackTransientTrack( const TrackRef & tk , const MagneticField* field, const edm::ESHandle<GlobalTrackingGeometry>& trackingGeometry);

TrackTransientTrack( const Track & tk , const MagneticField* field, const edm::ESHandle<GlobalTrackingGeometry>& trackingGeometry);

TrackTransientTrack( const TrackTransientTrack & tt );

TrackTransientTrack& operator=(const TrackTransientTrack & tt);

void setES(const edm::EventSetup& );

void setTrackingGeometry(const edm::ESHandle<GlobalTrackingGeometry>& );

void setBeamSpot(const reco::BeamSpot& beamSpot);

FreeTrajectoryState initialFreeState() const {return initialFTS;}

TrajectoryStateOnSurface outermostMeasurementState() const;

TrajectoryStateOnSurface innermostMeasurementState() const;

TrajectoryStateClosestToPoint
trajectoryStateClosestToPoint( const GlobalPoint & point ) const
{return builder(initialFTS, point);}

/**
* The TSOS at any point. The initial state will be used for the propagation.
*/
TrajectoryStateOnSurface stateOnSurface(const GlobalPoint & point) const;

TrajectoryStateClosestToPoint impactPointTSCP() const;

TrajectoryStateOnSurface impactPointState() const;

bool impactPointStateAvailable() const {return initialTSOSAvailable;}

/**
* access to original persistent track
*/
TrackRef persistentTrackRef() const { return tkr_; }

TrackBaseRef trackBaseRef() const {return TrackBaseRef(tkr_);}

TrackCharge charge() const {return Track::charge();}

const MagneticField* field() const {return theField;}

const Track & track() const {return *this;}

TrajectoryStateClosestToBeamLine stateAtBeamLine() const;

private:

void calculateTSOSAtVertex() const;

TrackRef tkr_;
const MagneticField* theField;

FreeTrajectoryState initialFTS;
mutable bool initialTSOSAvailable, initialTSCPAvailable, blStateAvailable;
mutable TrajectoryStateOnSurface initialTSOS;
mutable TrajectoryStateClosestToPoint initialTSCP;
TSCPBuilderNoMaterial builder;
edm::ESHandle<GlobalTrackingGeometry> theTrackingGeometry;
reco::BeamSpot theBeamSpot;
mutable TrajectoryStateClosestToBeamLine trajectoryStateClosestToBeamLine;

};

}

#endif
#ifndef TrackingTools_TransientTrack_TrackingTransientTrack_h
#define TrackingTools_TransientTrack_TrackingTransientTrack_h

#include <atomic>

/**
* Concrete implementation of the TransientTrack for a reco::Track
*/

#include "TrackingTools/TransientTrack/interface/BasicTransientTrack.h"
#include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
#include "DataFormats/TrackReco/interface/Track.h"
#include "DataFormats/TrackReco/interface/TrackFwd.h"
#include "TrackingTools/PatternTools/interface/TSCPBuilderNoMaterial.h"

namespace reco {

class TrackTransientTrack : public Track, public BasicTransientTrack {
public:

// constructor from persistent track
TrackTransientTrack();
TrackTransientTrack( const Track & tk , const MagneticField* field);
TrackTransientTrack( const TrackRef & tk , const MagneticField* field);

TrackTransientTrack( const TrackRef & tk , const MagneticField* field, const edm::ESHandle<GlobalTrackingGeometry>& trackingGeometry);

TrackTransientTrack( const Track & tk , const MagneticField* field, const edm::ESHandle<GlobalTrackingGeometry>& trackingGeometry);

TrackTransientTrack( const TrackTransientTrack & tt );

TrackTransientTrack& operator=(const TrackTransientTrack & tt);

void setES(const edm::EventSetup& );

void setTrackingGeometry(const edm::ESHandle<GlobalTrackingGeometry>& );

void setBeamSpot(const reco::BeamSpot& beamSpot);

FreeTrajectoryState initialFreeState() const {return initialFTS;}

TrajectoryStateOnSurface outermostMeasurementState() const;

TrajectoryStateOnSurface innermostMeasurementState() const;

TrajectoryStateClosestToPoint
trajectoryStateClosestToPoint( const GlobalPoint & point ) const
{return builder(initialFTS, point);}

/**
* The TSOS at any point. The initial state will be used for the propagation.
*/
TrajectoryStateOnSurface stateOnSurface(const GlobalPoint & point) const;

TrajectoryStateClosestToPoint impactPointTSCP() const;

TrajectoryStateOnSurface impactPointState() const;

bool impactPointStateAvailable() const {return (m_TSOS.load()==kSet ? true : false); }

/**
* access to original persistent track
*/
TrackRef persistentTrackRef() const { return tkr_; }

TrackBaseRef trackBaseRef() const {return TrackBaseRef(tkr_);}

TrackCharge charge() const {return Track::charge();}

const MagneticField* field() const {return theField;}

const Track & track() const {return *this;}

TrajectoryStateClosestToBeamLine stateAtBeamLine() const;

private:

TrackRef tkr_;
const MagneticField* theField;

FreeTrajectoryState initialFTS;

// mutable member data, those should be treated very carefully to guarantee
// thread safeness of the code by using atomic thread-safe helpers, see below
mutable TrajectoryStateOnSurface initialTSOS;
mutable TrajectoryStateClosestToPoint initialTSCP;
mutable TrajectoryStateClosestToBeamLine trajectoryStateClosestToBeamLine;
// thread-safe helpers to guarantee proper update of mutable member data
mutable std::atomic<char> m_TSOS;
mutable std::atomic<char> m_TSCP;
mutable std::atomic<char> m_SCTBL;

TSCPBuilderNoMaterial builder;
edm::ESHandle<GlobalTrackingGeometry> theTrackingGeometry;
reco::BeamSpot theBeamSpot;

// to be used to setup thread states of class mutables
enum CacheStates {kUnset, kSetting, kSet};

};

}

#endif
91 changes: 56 additions & 35 deletions TrackingTools/TransientTrack/src/TrackTransientTrack.cc
Expand Up @@ -5,42 +5,50 @@
#include "TrackingTools/PatternTools/interface/TSCBLBuilderNoMaterial.h"
#include <iostream>

/*
* ThreadSafe statement:
* This class is using mutable member data: initialTSOS, initialTSCP,
* trajectoryStateClosestToBeamLine. To guarantee thread safeness we
* rely on helper member data: m_TSOS, m_TSCP and m_SCTBL, respectively.
* Each time we'll change mutable member data we rely on specific order of the
* operator= and the store. It is important since C++11 will guarantee that
* the value changed by the operator= will be seen by all threads as occuring
* before the call to store and therefore the kSet == m_TSOS.load is always
* guaranteed to be true if and only if the thread will see the most recent
* value of initialTSOS
*/

using namespace reco;

TrackTransientTrack::TrackTransientTrack() :
Track(), tkr_(), theField(0), initialTSOSAvailable(false),
initialTSCPAvailable(false), blStateAvailable(false)
Track(), tkr_(), theField(0), m_TSOS(kUnset), m_TSCP(kUnset), m_SCTBL(kUnset)
{
}

TrackTransientTrack::TrackTransientTrack( const Track & tk , const MagneticField* field) :
Track(tk), tkr_(), theField(field), initialTSOSAvailable(false),
initialTSCPAvailable(false), blStateAvailable(false)
Track(tk), tkr_(), theField(field), m_TSOS(kUnset), m_TSCP(kUnset), m_SCTBL(kUnset)
{

initialFTS = trajectoryStateTransform::initialFreeState(tk, field);
}


TrackTransientTrack::TrackTransientTrack( const TrackRef & tk , const MagneticField* field) :
Track(*tk), tkr_(tk), theField(field), initialTSOSAvailable(false),
initialTSCPAvailable(false), blStateAvailable(false)
Track(*tk), tkr_(tk), theField(field), m_TSOS(kUnset), m_TSCP(kUnset), m_SCTBL(kUnset)
{

initialFTS = trajectoryStateTransform::initialFreeState(*tk, field);
}

TrackTransientTrack::TrackTransientTrack( const Track & tk , const MagneticField* field, const edm::ESHandle<GlobalTrackingGeometry>& tg) :
Track(tk), tkr_(), theField(field), initialTSOSAvailable(false),
initialTSCPAvailable(false), blStateAvailable(false), theTrackingGeometry(tg)
Track(tk), tkr_(), theField(field), m_TSOS(kUnset), m_TSCP(kUnset), m_SCTBL(kUnset), theTrackingGeometry(tg)
{

initialFTS = trajectoryStateTransform::initialFreeState(tk, field);
}

TrackTransientTrack::TrackTransientTrack( const TrackRef & tk , const MagneticField* field, const edm::ESHandle<GlobalTrackingGeometry>& tg) :
Track(*tk), tkr_(tk), theField(field), initialTSOSAvailable(false),
initialTSCPAvailable(false), blStateAvailable(false), theTrackingGeometry(tg)
Track(*tk), tkr_(tk), theField(field), m_TSOS(kUnset), m_TSCP(kUnset), m_SCTBL(kUnset), theTrackingGeometry(tg)
{

initialFTS = trajectoryStateTransform::initialFreeState(*tk, field);
Expand All @@ -49,16 +57,17 @@ TrackTransientTrack::TrackTransientTrack( const TrackRef & tk , const MagneticFi

TrackTransientTrack::TrackTransientTrack( const TrackTransientTrack & tt ) :
Track(tt), tkr_(tt.persistentTrackRef()), theField(tt.field()),
initialFTS(tt.initialFreeState()), initialTSOSAvailable(false),
initialTSCPAvailable(false)
initialFTS(tt.initialFreeState()), m_TSOS(kUnset), m_TSCP(kUnset)
{
if (tt.initialTSOSAvailable) {
// see ThreadSafe statement above about the order of operator= and store
if (kSet == tt.m_TSOS.load()) {
initialTSOS= tt.impactPointState();
initialTSOSAvailable = true;
m_TSOS.store(kSet);
}
if (tt.initialTSCPAvailable) {
// see ThreadSafe statement above about the order of operator= and store
if (kSet == tt.m_TSCP.load()) {
initialTSCP= tt.impactPointTSCP();
initialTSCPAvailable = true;
m_TSCP.store(kSet);
}
}

Expand All @@ -77,22 +86,36 @@ void TrackTransientTrack::setTrackingGeometry(const edm::ESHandle<GlobalTracking
void TrackTransientTrack::setBeamSpot(const BeamSpot& beamSpot)
{
theBeamSpot = beamSpot;
blStateAvailable = false;
m_SCTBL = kUnset;
}

TrajectoryStateOnSurface TrackTransientTrack::impactPointState() const
{
if (!initialTSOSAvailable) calculateTSOSAtVertex();
return initialTSOS;
// see ThreadSafe statement above about the order of operator= and store
if(kSet == m_TSOS.load()) return initialTSOS;
TransverseImpactPointExtrapolator tipe(theField);
auto tmp = tipe.extrapolate(initialFTS, initialFTS.position());
char expected = kUnset;
if(m_TSOS.compare_exchange_strong(expected, kSetting)) {
initialTSOS = tmp;
m_TSOS.store(kSet);
return initialTSOS;
}
return tmp;
}

TrajectoryStateClosestToPoint TrackTransientTrack::impactPointTSCP() const
{
if (!initialTSCPAvailable) {
initialTSCP = builder(initialFTS, initialFTS.position());
initialTSCPAvailable = true;
// see ThreadSafe statement above about the order of operator= and store
if(kSet == m_TSCP.load()) return initialTSCP;
auto tmp = builder(initialFTS, initialFTS.position());
char expected = kUnset;
if(m_TSCP.compare_exchange_strong(expected, kSetting)) {
initialTSCP = tmp;
m_TSCP.store(kSet);
return initialTSCP;
}
return initialTSCP;
return tmp;
}

TrajectoryStateOnSurface TrackTransientTrack::outermostMeasurementState() const
Expand All @@ -107,13 +130,6 @@ TrajectoryStateOnSurface TrackTransientTrack::innermostMeasurementState() const
return trajectoryStateTransform::innerStateOnSurface((*this),*theTrackingGeometry,theField);
}

void TrackTransientTrack::calculateTSOSAtVertex() const
{
TransverseImpactPointExtrapolator tipe(theField);
initialTSOS = tipe.extrapolate(initialFTS, initialFTS.position());
initialTSOSAvailable = true;
}

TrajectoryStateOnSurface
TrackTransientTrack::stateOnSurface(const GlobalPoint & point) const
{
Expand All @@ -123,11 +139,16 @@ TrackTransientTrack::stateOnSurface(const GlobalPoint & point) const

TrajectoryStateClosestToBeamLine TrackTransientTrack::stateAtBeamLine() const
{
if (!blStateAvailable) {
TSCBLBuilderNoMaterial blsBuilder;
trajectoryStateClosestToBeamLine = blsBuilder(initialFTS, theBeamSpot);
blStateAvailable = true;
// see ThreadSafe statement above about the order of operator= and store
if(kSet == m_SCTBL.load()) return trajectoryStateClosestToBeamLine;
TSCBLBuilderNoMaterial blsBuilder;
const auto tmp = blsBuilder(initialFTS, theBeamSpot);
char expected = kUnset;
if(m_SCTBL.compare_exchange_strong(expected, kSetting)) {
trajectoryStateClosestToBeamLine = tmp;
m_SCTBL.store(kSet);
return trajectoryStateClosestToBeamLine;
}
return trajectoryStateClosestToBeamLine;
return tmp;
}

0 comments on commit 99bb122

Please sign in to comment.