CMS 3D CMS Logo

TRootXTReq.cc
Go to the documentation of this file.
1 
3 
4 #include "TCondition.h"
5 #include "TThread.h"
6 #include "TMutex.h"
7 #include <TSysEvtHandler.h>
8 #include <TSystem.h>
9 #include <TTimer.h>
10 
11 // Bloody root threads do not provide signal delivery.
12 #include <csignal>
13 
14 // TRootXTReq
15 
16 //______________________________________________________________________________
17 //
18 // Abstract base-class for delivering cross-thread requests into ROOT
19 // main thread.
20 // Sub-classes must implement the Act() method.
21 // Two methods are available to request execution:
22 //
23 // - ShootRequest()
24 // Request execution and return immediately.
25 // The request object is deleted in the main thread.
26 //
27 // - ShootRequestAndWait()
28 // Request execution and wait until execution is finished.
29 // This way results can be returned to the caller in data-members.
30 // It is callers responsibility to delete the request object.
31 // It can also be reused.
32 //
33 //
34 // Global queue and locks are implemented via static members of this
35 // class.
36 //
37 // Must be initialized from the main thread like this:
38 // TRootXTReq::Bootstrap(TThread::SelfId());
39 
41 pthread_t TRootXTReq::sRootThread = 0;
42 TMutex *TRootXTReq::sQueueMutex = nullptr;
43 TSignalHandler *TRootXTReq::sSigHandler = nullptr;
44 bool TRootXTReq::sSheduled = false;
45 
46 //==============================================================================
47 
48 TRootXTReq::TRootXTReq(const char *n) : m_return_condition(nullptr), mName(n) {}
49 
51 
52 //------------------------------------------------------------------------------
53 
55  TLockGuard _lck(sQueueMutex);
56 
57  sQueue.push_back(this);
58 
59  if (!sSheduled) {
60  sSheduled = true;
61  pthread_kill(sRootThread, SIGUSR1);
62  }
63 }
64 
66  // Places request into the queue and requests execution in Rint thread.
67  // It returns immediately after that, without waiting for execution.
68  // The request is deleted after execution.
69 
70  if (m_return_condition) {
71  delete m_return_condition;
72  m_return_condition = nullptr;
73  }
74 
75  post_request();
76 }
77 
79  // Places request into the queue, requests execution in Rint thread and
80  // waits for the execution to be completed.
81  // The request is not deleted after execution as it might carry return
82  // value.
83  // The same request can be reused several times.
84 
85  if (!m_return_condition)
86  m_return_condition = new TCondition;
87 
88  m_return_condition->GetMutex()->Lock();
89 
90  post_request();
91 
92  m_return_condition->Wait();
93  m_return_condition->GetMutex()->UnLock();
94 }
95 
96 //==============================================================================
97 
98 class RootSig2XTReqHandler : public TSignalHandler {
99 private:
100  class XTReqTimer : public TTimer {
101  public:
102  XTReqTimer() : TTimer() {}
103  ~XTReqTimer() override {}
104 
105  void FireAway() {
106  Reset();
107  gSystem->AddTimer(this);
108  }
109 
110  Bool_t Notify() override {
111  gSystem->RemoveTimer(this);
113  return kTRUE;
114  }
115  };
116 
118 
119 public:
120  RootSig2XTReqHandler() : TSignalHandler(kSigUser1), mTimer() { Add(); }
121  ~RootSig2XTReqHandler() override {}
122 
123  Bool_t Notify() override {
124  printf("Usr1 Woof Woof in Root thread! Starting Timer.\n");
125  mTimer.FireAway();
126  return kTRUE;
127  }
128 };
129 
130 //------------------------------------------------------------------------------
131 
132 void TRootXTReq::Bootstrap(pthread_t root_thread) {
133  static const TString _eh("TRootXTReq::Bootstrap ");
134 
135  if (sRootThread != 0)
136  throw _eh + "Already initialized.";
137 
138  sRootThread = root_thread;
139  sQueueMutex = new TMutex(kTRUE);
141 }
142 
144  static const TString _eh("TRootXTReq::Shutdown ");
145 
146  if (sRootThread == 0)
147  throw _eh + "Have not beem initialized.";
148 
149  // Should lock and drain queue ... or sth.
150 
151  sRootThread = 0;
152  delete sSigHandler;
153  sSigHandler = nullptr;
154  delete sQueueMutex;
155  sQueueMutex = nullptr;
156 }
157 
159  printf("Timer fired, processing queue.\n");
160 
161  while (true) {
162  TRootXTReq *req = nullptr;
163  {
164  TLockGuard _lck(sQueueMutex);
165 
166  if (!sQueue.empty()) {
167  req = sQueue.front();
168  sQueue.pop_front();
169  } else {
170  sSheduled = false;
171  break;
172  }
173  }
174 
175  req->Act();
176 
177  if (req->m_return_condition) {
178  req->m_return_condition->GetMutex()->Lock();
179  req->m_return_condition->Signal();
180  req->m_return_condition->GetMutex()->UnLock();
181  } else {
182  delete req;
183  }
184  }
185 }
TCondition * m_return_condition
Definition: TRootXTReq.h:21
static void Bootstrap(pthread_t root_thread)
Definition: TRootXTReq.cc:132
void post_request()
Definition: TRootXTReq.cc:54
virtual ~TRootXTReq()
Definition: TRootXTReq.cc:50
virtual void Act()=0
static pthread_t sRootThread
Definition: TRootXTReq.h:24
std::list< TRootXTReq * > lpXTReq_t
Definition: TRootXTReq.h:19
static lpXTReq_t sQueue
Definition: TRootXTReq.h:23
static bool sSheduled
Definition: TRootXTReq.h:27
TRootXTReq(const char *n="TRootXTReq")
Definition: TRootXTReq.cc:48
static void Shutdown()
Definition: TRootXTReq.cc:143
static TSignalHandler * sSigHandler
Definition: TRootXTReq.h:26
void ShootRequest()
Definition: TRootXTReq.cc:65
~RootSig2XTReqHandler() override
Definition: TRootXTReq.cc:121
static void ProcessQueue()
Definition: TRootXTReq.cc:158
Bool_t Notify() override
Definition: TRootXTReq.cc:123
void Reset(std::vector< TH2F > &depth)
void ShootRequestAndWait()
Definition: TRootXTReq.cc:78
static TMutex * sQueueMutex
Definition: TRootXTReq.h:25