@@ -520,17 +520,27 @@ class DetImpl : public o2::base::Detector
520520 }
521521 }
522522
523+ // the hit containers buffered in the hit merger, per event and per hit branch
524+ auto & hitCollector ()
525+ {
526+ using Hit_t = typename std::remove_pointer<decltype (static_cast <Det*>(this )->Det ::getHits (0 ))>::type;
527+ using Collector_t = tbb::concurrent_unordered_map<int , std::vector<std::vector<std::unique_ptr<Hit_t>>>>;
528+ if (!mHitCollector ) {
529+ mHitCollector = std::make_shared<Collector_t>();
530+ }
531+ return *static_cast <Collector_t*>(mHitCollector .get ());
532+ }
533+
523534 void mergeHitEntriesAndFlush (int eventID, TTree& target, std::vector<int > const & trackoffsets, std::vector<int > const & nprimaries, std::vector<int > const & subevtsOrdered) final
524535 {
525536 // loop over hit containers / different branches
526537 // adjust trackID in hits on the go
527538 int probe = 0 ;
528539 using Hit_t = typename std::remove_pointer<decltype (static_cast <Det*>(this )->Det ::getHits (0 ))>::type;
529540 // remove buffered event from the hit store
530- using Collector_t = tbb::concurrent_unordered_map<int , std::vector<std::vector<std::unique_ptr<Hit_t>>>>;
531- auto hitbufferPtr = reinterpret_cast <Collector_t*>(mHitCollectorBufferPtr );
532- auto iter = hitbufferPtr->find (eventID);
533- if (iter == hitbufferPtr->end ()) {
541+ auto & collector = hitCollector ();
542+ auto iter = collector.find (eventID);
543+ if (iter == collector.end ()) {
534544 LOG (error) << " No buffered hits available for event " << eventID;
535545 return ;
536546 }
@@ -553,16 +563,7 @@ class DetImpl : public o2::base::Detector
553563 void collectHits (int eventID, fair::mq::Parts& parts, int & index, bool shm) override
554564 {
555565 using Hit_t = typename std::remove_pointer<decltype (static_cast <Det*>(this )->Det ::getHits (0 ))>::type;
556- using Collector_t = tbb::concurrent_unordered_map<int , std::vector<std::vector<std::unique_ptr<Hit_t>>>>;
557- // note: we can't put this as a member because decltype type deduction doesn't seem to work for
558- // class members; so we use a static and communicate it to other functions via a pointer member.
559- // The collector must be kept *per detector instance* (keyed by 'this'): for most detectors there
560- // is a single instance per C++ type, but several external detectors share the same type
561- // (o2::ext::ExternalDetector) and would otherwise clobber/double-free each other's buffers.
562- // tbb::concurrent_unordered_map is node-based, so the reference stays valid across insertions.
563- static tbb::concurrent_unordered_map<void const *, Collector_t> hitcollectors;
564- auto & hitcollector = hitcollectors[this ];
565- mHitCollectorBufferPtr = (char *)&hitcollector;
566+ auto & hitcollector = hitCollector ();
566567
567568 int probe = 0 ;
568569 ShmBusyFlag* busy = nullptr ;
@@ -750,7 +751,7 @@ class DetImpl : public o2::base::Detector
750751 int mCurrentBuffer = 0 ; // holding the current buffer information
751752 int mInitialized = false ;
752753
753- char * mHitCollectorBufferPtr = nullptr ; // ! pointer to hit (collector) buffer location (strictly internal )
754+ std::shared_ptr< void > mHitCollector ; // ! type-erased hit buffers of this instance in the hit merger (see hitCollector() )
754755
755756 ClassDefOverride (DetImpl, 0 );
756757};
0 commit comments