Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-16 09:21:18

0001 /// \file
0002 /// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
0003 /// Feedback is welcome!
0004 
0005 #ifndef ROOT_RHistConcurrentFiller
0006 #define ROOT_RHistConcurrentFiller
0007 
0008 #include "RHist.hxx"
0009 #include "RHistFillContext.hxx"
0010 
0011 #include <exception>
0012 #include <memory>
0013 #include <mutex>
0014 #include <stdexcept>
0015 #include <vector>
0016 
0017 namespace ROOT {
0018 namespace Experimental {
0019 
0020 /**
0021 A histogram filler to concurrently fill an RHist.
0022 
0023 \code
0024 auto hist = std::make_shared<ROOT::Experimental::RHist<int>>(10, std::make_pair(5, 15));
0025 {
0026    ROOT::Experimental::RHistConcurrentFiller filler(hist);
0027    auto context = filler.CreateFillContext();
0028    context->Fill(8.5);
0029 }
0030 // hist->GetBinContent(ROOT::Experimental::RBinIndex(3)) will return 1
0031 \endcode
0032 
0033 \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
0034 Feedback is welcome!
0035 */
0036 template <typename BinContentType>
0037 class RHistConcurrentFiller final {
0038    /// A pointer to the filled histogram
0039    std::shared_ptr<RHist<BinContentType>> fHist;
0040 
0041    /// Mutex to protect access to the list of fill contexts (not for filling itself!)
0042    std::mutex fMutex;
0043    /// The list of fill contexts, for checks during destruction
0044    std::vector<std::weak_ptr<RHistFillContext<BinContentType>>> fFillContexts;
0045 
0046 public:
0047    /// Create a filler object.
0048    ///
0049    /// \param[in] hist a pointer to the histogram
0050    explicit RHistConcurrentFiller(std::shared_ptr<RHist<BinContentType>> hist) : fHist(hist)
0051    {
0052       if (!hist) {
0053          throw std::invalid_argument("hist must not be nullptr");
0054       }
0055    }
0056 
0057    RHistConcurrentFiller(const RHistConcurrentFiller &) = delete;
0058    RHistConcurrentFiller(RHistConcurrentFiller &&) = delete;
0059    RHistConcurrentFiller &operator=(const RHistConcurrentFiller &) = delete;
0060    RHistConcurrentFiller &operator=(RHistConcurrentFiller &&) = delete;
0061 
0062    ~RHistConcurrentFiller()
0063    {
0064       for (const auto &context : fFillContexts) {
0065          if (!context.expired()) {
0066             // According to C++ Core Guideline C.36 "A destructor must not fail" and (C.37) "If a destructor tries to
0067             // exit with an exception, it’s a bad design error and the program had better terminate".
0068             std::terminate(); // GCOVR_EXCL_LINE
0069          }
0070       }
0071    }
0072 
0073    const std::shared_ptr<RHist<BinContentType>> &GetHist() const { return fHist; }
0074 
0075    /// Create a new context for concurrent filling.
0076    std::shared_ptr<RHistFillContext<BinContentType>> CreateFillContext()
0077    {
0078       // Cannot use std::make_shared because the constructor of RHistFillContext is private. Also it would mean that the
0079       // (direct) memory of all contexts stays around until the vector of weak_ptr's is cleared.
0080       std::shared_ptr<RHistFillContext<BinContentType>> context(new RHistFillContext<BinContentType>(*fHist));
0081 
0082       {
0083          std::lock_guard g(fMutex);
0084          fFillContexts.push_back(context);
0085       }
0086 
0087       return context;
0088    }
0089 };
0090 
0091 } // namespace Experimental
0092 } // namespace ROOT
0093 
0094 #endif