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 
40 
42 pthread_t TRootXTReq::sRootThread = 0;
43 TMutex *TRootXTReq::sQueueMutex = nullptr;
44 TSignalHandler *TRootXTReq::sSigHandler = nullptr;
45 bool TRootXTReq::sSheduled = false;
46 
47 
48 //==============================================================================
49 
50 TRootXTReq::TRootXTReq(const char* n) :
51  m_return_condition(nullptr),
52  mName(n)
53 {}
54 
56 {
57  delete m_return_condition;
58 }
59 
60 //------------------------------------------------------------------------------
61 
63 {
64  TLockGuard _lck(sQueueMutex);
65 
66  sQueue.push_back(this);
67 
68  if ( ! sSheduled)
69  {
70  sSheduled = true;
71  pthread_kill(sRootThread, SIGUSR1);
72  }
73 }
74 
76 {
77  // Places request into the queue and requests execution in Rint thread.
78  // It returns immediately after that, without waiting for execution.
79  // The request is deleted after execution.
80 
82  {
83  delete m_return_condition;
84  m_return_condition = nullptr;
85  }
86 
87  post_request();
88 }
89 
91 {
92  // Places request into the queue, requests execution in Rint thread and
93  // waits for the execution to be completed.
94  // The request is not deleted after execution as it might carry return
95  // value.
96  // The same request can be reused several times.
97 
98  if (!m_return_condition)
99  m_return_condition = new TCondition;
100 
101  m_return_condition->GetMutex()->Lock();
102 
103  post_request();
104 
105  m_return_condition->Wait();
106  m_return_condition->GetMutex()->UnLock();
107 }
108 
109 
110 //==============================================================================
111 
112 class RootSig2XTReqHandler : public TSignalHandler
113 {
114 private:
115  class XTReqTimer : public TTimer
116  {
117  public:
118  XTReqTimer() : TTimer() {}
119  ~XTReqTimer() override {}
120 
121  void FireAway()
122  {
123  Reset();
124  gSystem->AddTimer(this);
125  }
126 
127  Bool_t Notify() override
128  {
129  gSystem->RemoveTimer(this);
131  return kTRUE;
132  }
133  };
134 
136 
137 public:
138  RootSig2XTReqHandler() : TSignalHandler(kSigUser1), mTimer() { Add(); }
139  ~RootSig2XTReqHandler() override {}
140 
141  Bool_t Notify() override
142  {
143  printf("Usr1 Woof Woof in Root thread! Starting Timer.\n");
144  mTimer.FireAway();
145  return kTRUE;
146  }
147 };
148 
149 //------------------------------------------------------------------------------
150 
151 void TRootXTReq::Bootstrap(pthread_t root_thread)
152 {
153  static const TString _eh("TRootXTReq::Bootstrap ");
154 
155  if (sRootThread != 0)
156  throw _eh + "Already initialized.";
157 
158  sRootThread = root_thread;
159  sQueueMutex = new TMutex(kTRUE);
161 }
162 
164 {
165  static const TString _eh("TRootXTReq::Shutdown ");
166 
167  if (sRootThread == 0)
168  throw _eh + "Have not beem initialized.";
169 
170  // Should lock and drain queue ... or sth.
171 
172  sRootThread = 0;
173  delete sSigHandler; sSigHandler = nullptr;
174  delete sQueueMutex; sQueueMutex = nullptr;
175 }
176 
178 {
179  printf("Timer fired, processing queue.\n");
180 
181  while (true)
182  {
183  TRootXTReq *req = nullptr;
184  {
185  TLockGuard _lck(sQueueMutex);
186 
187  if ( ! sQueue.empty())
188  {
189  req = sQueue.front();
190  sQueue.pop_front();
191  }
192  else
193  {
194  sSheduled = false;
195  break;
196  }
197  }
198 
199  req->Act();
200 
201  if (req->m_return_condition)
202  {
203  req->m_return_condition->GetMutex()->Lock();
204  req->m_return_condition->Signal();
205  req->m_return_condition->GetMutex()->UnLock();
206  }
207  else
208  {
209  delete req;
210  }
211  }
212 }
TCondition * m_return_condition
Definition: TRootXTReq.h:22
static void Bootstrap(pthread_t root_thread)
Definition: TRootXTReq.cc:151
void post_request()
Definition: TRootXTReq.cc:62
virtual ~TRootXTReq()
Definition: TRootXTReq.cc:55
#define nullptr
virtual void Act()=0
static pthread_t sRootThread
Definition: TRootXTReq.h:25
static lpXTReq_t sQueue
Definition: TRootXTReq.h:24
static bool sSheduled
Definition: TRootXTReq.h:28
TRootXTReq(const char *n="TRootXTReq")
Definition: TRootXTReq.cc:50
static void Shutdown()
Definition: TRootXTReq.cc:163
std::list< TRootXTReq * > lpXTReq_t
Definition: TRootXTReq.h:20
static TSignalHandler * sSigHandler
Definition: TRootXTReq.h:27
void ShootRequest()
Definition: TRootXTReq.cc:75
~RootSig2XTReqHandler() override
Definition: TRootXTReq.cc:139
static void ProcessQueue()
Definition: TRootXTReq.cc:177
Bool_t Notify() override
Definition: TRootXTReq.cc:141
void Reset(std::vector< TH2F > &depth)
void ShootRequestAndWait()
Definition: TRootXTReq.cc:90
static TMutex * sQueueMutex
Definition: TRootXTReq.h:26