From bc0ddb93c31fd26469ece6fc3a224c4e3e100367 Mon Sep 17 00:00:00 2001
From: Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
Date: Mon, 26 Jun 2023 14:43:52 +0000
Subject: [PATCH] algo::UnpackSts: Make thread-safe.

---
 algo/detectors/sts/UnpackSts.cxx | 27 ++++++++++++++-------------
 algo/detectors/sts/UnpackSts.h   | 22 ++++++++++++++--------
 2 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/algo/detectors/sts/UnpackSts.cxx b/algo/detectors/sts/UnpackSts.cxx
index 06a154a98c..7753040e7d 100644
--- a/algo/detectors/sts/UnpackSts.cxx
+++ b/algo/detectors/sts/UnpackSts.cxx
@@ -20,19 +20,20 @@ namespace cbm::algo
 
   // ----   Algorithm execution   ---------------------------------------------
   UnpackSts::resultType UnpackSts::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
-                                              const uint64_t tTimeslice)
+                                              const uint64_t tTimeslice) const
   {
     // --- Output data
     resultType result = {};
 
     // --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs
     // --- and the epoch is a multiple of ns.
+    TimeSpec time;
     const uint64_t epochLengthInNs = fkEpochLength * fkClockCycleNom / fkClockCycleDen;
-    fCurrentTsTime                 = tTimeslice / epochLengthInNs;
+    time.currentTsTime             = tTimeslice / epochLengthInNs;
 
     // --- Current TS_MSB epoch cycle
     auto const msTime = msDescr.idx;  // Unix time of MS in ns
-    fCurrentCycle     = std::ldiv(msTime, fkCycleLength).quot;
+    time.currentCycle = std::ldiv(msTime, fkCycleLength).quot;
 
     // --- Number of messages in microslice
     auto msSize = msDescr.size;
@@ -60,7 +61,7 @@ namespace cbm::algo
       result.second.fNumErrInvalidFirstMessage++;
       return result;
     }
-    ProcessTsmsbMessage(message[1]);
+    ProcessTsmsbMessage(message[1], time);
 
     // --- Message loop
     for (uint32_t messageNr = 2; messageNr < numMessages; messageNr++) {
@@ -69,11 +70,11 @@ namespace cbm::algo
       switch (message[messageNr].GetMessType()) {
 
         case stsxyter::MessType::Hit: {
-          ProcessHitMessage(message[messageNr], result.first, result.second);
+          ProcessHitMessage(message[messageNr], time, result.first, result.second);
           break;
         }
         case stsxyter::MessType::TsMsb: {
-          ProcessTsmsbMessage(message[messageNr]);
+          ProcessTsmsbMessage(message[messageNr], time);
           break;
         }
         default: {
@@ -91,8 +92,8 @@ namespace cbm::algo
 
 
   // -----   Process hit message   --------------------------------------------
-  inline void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, vector<CbmStsDigi>& digiVec,
-                                           UnpackStsMonitorData& monitor) const
+  inline void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, const TimeSpec& time,
+                                           vector<CbmStsDigi>& digiVec, UnpackStsMonitorData& monitor) const
   {
 
     // --- Check eLink and get parameters
@@ -114,7 +115,7 @@ namespace cbm::algo
     }
 
     // --- Expand time stamp to time within timeslice (in clock cycle)
-    uint64_t messageTime = message.GetHitTimeBinning() + fCurrentEpochTime;
+    uint64_t messageTime = message.GetHitTimeBinning() + time.currentEpochTime;
 
     // --- Convert time stamp from clock cycles to ns. Round to nearest full ns.
     messageTime = (messageTime * fkClockCycleNom + fkClockCycleDen / 2) / fkClockCycleDen;
@@ -143,7 +144,7 @@ namespace cbm::algo
 
 
   // -----   Process an epoch (TS_MSB) message   ------------------------------
-  inline void UnpackSts::ProcessTsmsbMessage(const stsxyter::Message& message)
+  inline void UnpackSts::ProcessTsmsbMessage(const stsxyter::Message& message, TimeSpec& time) const
   {
     // The compression of time is based on the hierarchy epoch cycle - epoch - message time.
     // Cycles are counted from the start of Unix time and are multiples of an epoch (ts_msb).
@@ -156,13 +157,13 @@ namespace cbm::algo
     auto epoch = message.GetTsMsbValBinning();
 
     // --- Cycle wrap
-    if (epoch < fCurrentEpoch) fCurrentCycle++;
+    if (epoch < time.currentEpoch) time.currentCycle++;
 
     // --- Update current epoch counter
-    fCurrentEpoch = epoch;
+    time.currentEpoch = epoch;
 
     // --- Calculate epoch time in clocks cycles relative to timeslice start time
-    fCurrentEpochTime = (fCurrentCycle * fkEpochsPerCycle + epoch - fCurrentTsTime) * fkEpochLength;
+    time.currentEpochTime = (time.currentCycle * fkEpochsPerCycle + epoch - time.currentTsTime) * fkEpochLength;
   }
   // --------------------------------------------------------------------------
 
diff --git a/algo/detectors/sts/UnpackSts.h b/algo/detectors/sts/UnpackSts.h
index 8378c418c3..31cad3bf1f 100644
--- a/algo/detectors/sts/UnpackSts.h
+++ b/algo/detectors/sts/UnpackSts.h
@@ -5,7 +5,6 @@
 #ifndef CBM_ALGO_UNPACKSTS_H
 #define CBM_ALGO_UNPACKSTS_H 1
 
-
 #include "CbmStsDigi.h"
 
 #include "MicrosliceDescriptor.hpp"
@@ -17,6 +16,7 @@
 #include <memory>
 #include <vector>
 
+#include "Prelude.h"
 #include "StsXyterMessage.h"
 
 namespace cbm::algo
@@ -103,13 +103,23 @@ namespace cbm::algo
      ** @return STS digi data
      **/
     resultType operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
-                          const uint64_t tTimeslice);
+                          const uint64_t tTimeslice) const;
 
     /** @brief Set the parameter container
      ** @param params Pointer to parameter container
      **/
     void SetParams(std::unique_ptr<UnpackStsPar> params) { fParams = *(std::move(params)); }
 
+  private:  // types
+    /**
+     * @brief Structure to hold the current time information for the current microslice
+     */
+    struct TimeSpec {
+      u64 currentTsTime    = 0;  ///< Unix time of timeslice in units of epoch length
+      u64 currentCycle     = 0;  ///< Current epoch cycle
+      u32 currentEpoch     = 0;  ///< Current epoch number within epoch cycle
+      u64 currentEpochTime = 0;  ///< Current epoch time relative to timeslice in clock cycles
+    };
 
   private:  // methods
     /** @brief Process a hit message
@@ -117,20 +127,16 @@ namespace cbm::algo
      ** @param digiVec Vector to append the created digi to
      ** @param monitor Reference to monitor object
      **/
-    void ProcessHitMessage(const stsxyter::Message& message, std::vector<CbmStsDigi>& digiVec,
+    void ProcessHitMessage(const stsxyter::Message& message, const TimeSpec& time, std::vector<CbmStsDigi>& digiVec,
                            UnpackStsMonitorData& monitor) const;
 
     /** @brief Process an epoch message (TS_MSB)
      ** @param message SMX message (32-bit word)
      **/
-    void ProcessTsmsbMessage(const stsxyter::Message& message);
+    void ProcessTsmsbMessage(const stsxyter::Message& message, TimeSpec& time) const;
 
 
   private:                            // members
-    uint64_t fCurrentTsTime    = 0;   ///< Unix time of timeslice in units of epoch length
-    uint64_t fCurrentCycle     = 0;   ///< Current epoch cycle
-    uint32_t fCurrentEpoch     = 0;   ///< Current epoch number within epoch cycle
-    uint64_t fCurrentEpochTime = 0;   ///< Current epoch time relative to timeslice in clock cycles
     UnpackStsPar fParams       = {};  ///< Parameter container
 
     /** Number of TS_MSB epochs per cycle **/
-- 
GitLab