Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RHistConcurrentFill.hxx
Go to the documentation of this file.
1 /// \file ROOT/RHistConcurrentFill.h
2 /// \ingroup Hist ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2015-07-03
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #ifndef ROOT7_RHistConcurrentFill
17 #define ROOT7_RHistConcurrentFill
18 
19 #include "ROOT/RSpan.hxx"
21 
22 #include <mutex>
23 
24 namespace ROOT {
25 namespace Experimental {
26 
27 template <class HIST, int SIZE>
28 class RHistConcurrentFillManager;
29 
30 /**
31  \class RHistConcurrentFiller
32  Buffers a thread's Fill calls and submits them to the
33  RHistConcurrentFillManager. Enables multi-threaded filling.
34  **/
35 
36 template <class HIST, int SIZE>
37 class RHistConcurrentFiller: public Internal::RHistBufferedFillBase<RHistConcurrentFiller<HIST, SIZE>, HIST, SIZE> {
38  RHistConcurrentFillManager<HIST, SIZE> &fManager;
39 
40 public:
41  using CoordArray_t = typename HIST::CoordArray_t;
42  using Weight_t = typename HIST::Weight_t;
43 
44  RHistConcurrentFiller(RHistConcurrentFillManager<HIST, SIZE> &manager): fManager(manager) {}
45 
46  /// Thread-specific HIST::Fill().
47  using Internal::RHistBufferedFillBase<RHistConcurrentFiller<HIST, SIZE>, HIST, SIZE>::Fill;
48 
49  /// Thread-specific HIST::FillN().
50  void FillN(const std::span<const CoordArray_t> xN, const std::span<const Weight_t> weightN)
51  {
52  fManager.FillN(xN, weightN);
53  }
54 
55  /// Thread-specific HIST::FillN().
56  void FillN(const std::span<const CoordArray_t> xN) { fManager.FillN(xN); }
57 
58  static constexpr int GetNDim() { return HIST::GetNDim(); }
59 
60 private:
61  friend class Internal::RHistBufferedFillBase<RHistConcurrentFiller<HIST, SIZE>, HIST, SIZE>;
62  void FlushImpl() { fManager.FillN(this->GetCoords(), this->GetWeights()); }
63 };
64 
65 /**
66  \class RHistConcurrentFillManager
67  Manages the synchronization of calls to FillN().
68 
69  The HIST template can be a RHist instance. This class hands out
70  RHistConcurrentFiller objects that can concurrently fill the histogram. They
71  buffer calls to Fill() until the buffer is full, and then swap the buffer
72  with that of the RHistConcurrentFillManager. The manager than fills the
73  histogram.
74  **/
75 
76 template <class HIST, int SIZE = 1024>
77 class RHistConcurrentFillManager {
78  friend class RHistConcurrentFiller<HIST, SIZE>;
79 
80 public:
81  using Hist_t = HIST;
82  using CoordArray_t = typename HIST::CoordArray_t;
83  using Weight_t = typename HIST::Weight_t;
84 
85 private:
86  HIST &fHist;
87  std::mutex fFillMutex; // should become a spin lock
88 
89 public:
90  RHistConcurrentFillManager(HIST &hist): fHist(hist) {}
91 
92  RHistConcurrentFiller<HIST, SIZE> MakeFiller() { return RHistConcurrentFiller<HIST, SIZE>{*this}; }
93 
94  /// Thread-specific HIST::FillN().
95  void FillN(const std::span<const CoordArray_t> xN, const std::span<const Weight_t> weightN)
96  {
97  std::lock_guard<std::mutex> lockGuard(fFillMutex);
98  fHist.FillN(xN, weightN);
99  }
100 
101  /// Thread-specific HIST::FillN().
102  void FillN(const std::span<const CoordArray_t> xN)
103  {
104  std::lock_guard<std::mutex> lockGuard(fFillMutex);
105  fHist.FillN(xN);
106  }
107 };
108 
109 } // namespace Experimental
110 } // namespace ROOT
111 
112 #endif