ROOT  6.06/09
Reference Guide
TMonitor.cxx
Go to the documentation of this file.
1 // @(#)root/net:$Id$
2 // Author: Fons Rademakers 09/01/97
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TMonitor //
15 // //
16 // This class monitors activity on a number of network sockets. //
17 // The actual monitoring is done by TSystem::DispatchOneEvent(). //
18 // Typical usage: create a TMonitor object. Register a number of //
19 // TSocket objects and call TMonitor::Select(). Select() returns the //
20 // socket object which has data waiting. TSocket objects can be added, //
21 // removed, (temporary) enabled or disabled. //
22 // //
23 //////////////////////////////////////////////////////////////////////////
24 
25 #include "TMonitor.h"
26 #include "TSocket.h"
27 #include "TList.h"
28 #include "TSystem.h"
29 #include "TSysEvtHandler.h"
30 #include "TTimer.h"
31 #include "TError.h"
32 
33 
34 //---- Socket event handler ----------------------------------------------------
35 //
36 // This utility class is only used by TMonitor.
37 //
38 
39 class TSocketHandler : public TFileHandler {
40 private:
41  TMonitor *fMonitor; //monitor to which this handler belongs
42  TSocket *fSocket; //socket being handled
43 
44 public:
45  TSocketHandler(TMonitor *m, TSocket *s, Int_t interest, Bool_t mainloop = kTRUE);
46  Bool_t Notify();
47  Bool_t ReadNotify() { return Notify(); }
48  Bool_t WriteNotify() { return Notify(); }
49  TSocket *GetSocket() const { return fSocket; }
50 };
51 
52 TSocketHandler::TSocketHandler(TMonitor *m, TSocket *s,
53  Int_t interest, Bool_t mainloop)
54  : TFileHandler(s->GetDescriptor(), interest)
55 {
56  //constructor
57  fMonitor = m;
58  fSocket = s;
59 
60  if (mainloop)
61  Add();
62 }
63 
65 {
66  //notifier
67  fMonitor->SetReady(fSocket);
68  return kTRUE;
69 }
70 
71 //---- Timeout timer -----------------------------------------------------------
72 //
73 // This utility class is only used via TMonitor::Select(Int_t timeout)
74 //
75 
76 class TTimeOutTimer : public TTimer {
77 private:
78  TMonitor *fMonitor; //monitor to which this timer belongs
79 
80 public:
81  TTimeOutTimer(TMonitor *m, Long_t ms);
82  Bool_t Notify();
83 };
84 
85 TTimeOutTimer::TTimeOutTimer(TMonitor *m, Long_t ms)
86  : TTimer(ms, kTRUE)
87 {
88  //constructor
89  fMonitor = m;
90  gSystem->AddTimer(this);
91 }
92 
94 {
95  //notifier
96  fMonitor->SetReady((TSocket *)-1);
97  Remove(); // one shot only
98  return kTRUE;
99 }
100 //------------------------------------------------------------------------------
101 
102 
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// Create a monitor object. If mainloop is true the monitoring will be
107 /// done in the main event loop.
108 
109 TMonitor::TMonitor(Bool_t mainloop) : TObject() , TQObject()
110 {
112 
113  fActive = new TList;
114  fDeActive = new TList;
115  fMainLoop = mainloop;
116  fInterrupt = kFALSE;
117  fReady = 0;
118 }
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Copy constructor
122 
124 {
125  TSocketHandler *sh = 0;
126  // Active list
127  fActive = new TList;
128  TIter nxa(m.fActive);
129  while ((sh = (TSocketHandler *)nxa())) {
130  Int_t mask = 0;
131  if (sh->HasReadInterest()) mask |= 0x1;
132  if (sh->HasWriteInterest()) mask |= 0x2;
133  fActive->Add(new TSocketHandler(this, sh->GetSocket(), mask, m.fMainLoop));
134  }
135  // Deactive list
136  fDeActive = new TList;
137  TIter nxd(m.fDeActive);
138  while ((sh = (TSocketHandler *)nxd())) {
139  Int_t mask = 0;
140  if (sh->HasReadInterest()) mask |= 0x1;
141  if (sh->HasWriteInterest()) mask |= 0x2;
142  fDeActive->Add(new TSocketHandler(this, sh->GetSocket(), mask, m.fMainLoop));
143  }
144  // Other members
145  fMainLoop = m.fMainLoop;
147  fReady = 0;
148 }
149 
150 ////////////////////////////////////////////////////////////////////////////////
151 /// Cleanup the monitor object. Does not delete sockets being monitored.
152 
154 {
155  fActive->Delete();
157 
158  fDeActive->Delete();
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Add socket to the monitor's active list. If interest=kRead then we
164 /// want to monitor the socket for read readiness, if interest=kWrite
165 /// then we monitor the socket for write readiness, if interest=kRead|kWrite
166 /// then we monitor both read and write readiness.
167 
168 void TMonitor::Add(TSocket *sock, Int_t interest)
169 {
170  fActive->Add(new TSocketHandler(this, sock, interest, fMainLoop));
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Set interest mask for socket sock to interest. If the socket is not
175 /// in the active list move it or add it there.
176 /// If interest=kRead then we want to monitor the socket for read readiness,
177 /// if interest=kWrite then we monitor the socket for write readiness,
178 /// if interest=kRead|kWrite then we monitor both read and write readiness.
179 
180 void TMonitor::SetInterest(TSocket *sock, Int_t interest)
181 {
182  TSocketHandler *s = 0;
183 
184  if (!interest)
185  interest = kRead;
186 
187  // Check first the activated list ...
188  TIter next(fActive);
189  while ((s = (TSocketHandler *) next())) {
190  if (sock == s->GetSocket()) {
191  s->SetInterest(interest);
192  return;
193  }
194  }
195 
196  // Check now the deactivated list ...
197  TIter next1(fDeActive);
198  while ((s = (TSocketHandler *) next1())) {
199  if (sock == s->GetSocket()) {
200  fDeActive->Remove(s);
201  fActive->Add(s);
202  s->SetInterest(interest);
203  return;
204  }
205  }
206 
207  // The socket is not in our lists: just add it
208  fActive->Add(new TSocketHandler(this, sock, interest, fMainLoop));
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////
212 /// Remove a socket from the monitor.
213 
215 {
216  TIter next(fActive);
217  TSocketHandler *s;
218 
219  while ((s = (TSocketHandler *) next())) {
220  if (sock == s->GetSocket()) {
221  fActive->Remove(s);
222  delete s;
223  return;
224  }
225  }
226 
227  TIter next1(fDeActive);
228 
229  while ((s = (TSocketHandler *) next1())) {
230  if (sock == s->GetSocket()) {
231  fDeActive->Remove(s);
232  delete s;
233  return;
234  }
235  }
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Remove all sockets from the monitor.
240 
242 {
243  fActive->Delete();
244  fDeActive->Delete();
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Activate a de-activated socket.
249 
251 {
253  TSocketHandler *s;
254 
255  while ((s = (TSocketHandler *) next())) {
256  if (sock == s->GetSocket()) {
257  fDeActive->Remove(s);
258  fActive->Add(s);
259  s->Add();
260  return;
261  }
262  }
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Activate all de-activated sockets.
267 
269 {
271  TSocketHandler *s;
272 
273  while ((s = (TSocketHandler *) next())) {
274  fActive->Add(s);
275  s->Add();
276  }
277  fDeActive->Clear();
278  fInterrupt = kFALSE;
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// De-activate a socket.
283 
285 {
286  TIter next(fActive);
287  TSocketHandler *s;
288 
289  while ((s = (TSocketHandler *) next())) {
290  if (sock == s->GetSocket()) {
291  fActive->Remove(s);
292  fDeActive->Add(s);
293  s->Remove();
294  return;
295  }
296  }
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// De-activate all activated sockets.
301 
303 {
304  TIter next(fActive);
305  TSocketHandler *s;
306 
307  while ((s = (TSocketHandler *) next())) {
308  fDeActive->Add(s);
309  s->Remove();
310  }
311  fActive->Clear();
312  fInterrupt = kFALSE;
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// Return pointer to socket for which an event is waiting.
317 /// Select can be interrupt by a call to Interrupt() (e.g. connected with a
318 /// Ctrl-C handler); a call to ResetInterrupt() before Select() is advisable
319 /// in such a case.
320 /// Return 0 in case of error.
321 
323 {
324  fReady = 0;
325 
326  while (!fReady && !fInterrupt)
327  gSystem->InnerLoop();
328 
329  // Notify interrupts
330  if (fInterrupt) {
331  fInterrupt = kFALSE;
332  fReady = 0;
333  Info("Select","*** interrupt occured ***");
334  }
335 
336  return fReady;
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Return pointer to socket for which an event is waiting.
341 /// Wait a maximum of timeout milliseconds.
342 /// If return is due to timeout it returns (TSocket *)-1.
343 /// Select() can be interrupt by a call to Interrupt() (e.g. connected with a
344 /// Ctrl-C handler); a call to ResetInterrupt() before Select() is advisable
345 /// in such a case.
346 /// Return 0 in case of any other error situation.
347 
349 {
350  if (timeout < 0)
351  return TMonitor::Select();
352 
353  fReady = 0;
354 
355  TTimeOutTimer t(this, timeout);
356 
357  while (!fReady && !fInterrupt)
358  gSystem->InnerLoop();
359 
360  // Notify interrupts
361  if (fInterrupt) {
362  fInterrupt = kFALSE;
363  fReady = 0;
364  Info("Select","*** interrupt occured ***");
365  }
366 
367  return fReady;
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Return numbers of sockets that are ready for reading or writing.
372 /// Wait a maximum of timeout milliseconds.
373 /// Return 0 if timed-out. Return < 0 in case of error.
374 /// If rdready and/or wrready are not 0, the lists of sockets with
375 /// something to read and/or write are also returned.
376 
377 Int_t TMonitor::Select(TList *rdready, TList *wrready, Long_t timeout)
378 {
379  Int_t nr = -2;
380 
381  TSocketHandler *h = 0;
382  Int_t ns = fActive->GetSize();
383  if (ns == 1) {
384  // Avoid additional loops inside
385  h = (TSocketHandler *)fActive->First();
386  nr = gSystem->Select((TFileHandler *)h, timeout);
387  } else if (ns > 1) {
388  nr = gSystem->Select(fActive, timeout);
389  }
390 
391  if (nr > 0 && (rdready || wrready)) {
392  // Clear the lists
393  if (rdready)
394  rdready->Clear();
395  if (wrready)
396  wrready->Clear();
397  // Got a file descriptor
398  if (!h) {
399  TIter next(fActive);
400  while ((h = (TSocketHandler *)next())) {
401  if (rdready && h->IsReadReady())
402  rdready->Add(h->GetSocket());
403  if (wrready && h->IsWriteReady())
404  wrready->Add(h->GetSocket());
405  }
406  } else {
407  if (rdready && h->IsReadReady())
408  rdready->Add(h->GetSocket());
409  if (wrready && h->IsWriteReady())
410  wrready->Add(h->GetSocket());
411  }
412  }
413 
414  return nr;
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Called by TSocketHandler::Notify() to signal which socket is ready
419 /// to be read or written. User should not call this routine. The ready
420 /// socket will be returned via the Select() user function.
421 /// The Ready(TSocket *sock) signal is emitted.
422 
424 {
425  fReady = sock;
426  Ready(fReady);
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 /// Return number of sockets in the active list. If timeout > 0, remove from
431 /// the list those sockets which did not have any activity since timeout
432 /// millisecs. If timeout = 0, then reset activity timestamp on all active
433 /// sockets. This time out is typically used if GetActive() is used to see
434 /// how many remotes still need to send something. If they pass the timeout
435 /// they will be skipped and GetActive() will return 0 and the loop can be
436 /// exited.
437 
439 {
440  if (timeout >= 0) {
441  TIter next(fActive);
442  TSocketHandler *s;
443  if (timeout > 0) {
444  TTimeStamp now;
445  while ((s = (TSocketHandler *) next())) {
446  TSocket *xs = s->GetSocket();
447  TTimeStamp ts = xs->GetLastUsage();
448  Long_t dt = (Long_t)(now.GetSec() - ts.GetSec()) * 1000 +
449  (Long_t)(now.GetNanoSec() - ts.GetNanoSec()) / 1000000 ;
450  if (dt > timeout) {
451  Info("GetActive", "socket: %p: %s:%d did not show any activity"
452  " during the last %ld millisecs: deactivating",
453  xs, xs->GetInetAddress().GetHostName(),
454  xs->GetInetAddress().GetPort(), timeout);
455  fActive->Remove(s);
456  fDeActive->Add(s);
457  s->Remove();
458  }
459  }
460  } else if (timeout == 0) {
461  // Reset time stamps
462  while ((s = (TSocketHandler *) next())) {
463  s->GetSocket()->Touch();
464  }
465  }
466  }
467  return fActive->GetSize();
468 }
469 
470 ////////////////////////////////////////////////////////////////////////////////
471 /// Return number of sockets in the de-active list.
472 
474 {
475  return fDeActive->GetSize();
476 }
477 
478 ////////////////////////////////////////////////////////////////////////////////
479 /// Check if socket 's' is in the active list. Avoids the duplication
480 /// of active list via TMonitor::GetListOfActives().
481 
483 {
484  TIter next(fActive);
485  while (TSocketHandler *h = (TSocketHandler*) next())
486  if (sock == h->GetSocket())
487  return kTRUE;
488 
489  // Not found
490  return kFALSE;
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// Returns a list with all active sockets. This list must be deleted
495 /// by the user. DO NOT call Delete() on this list as it will delete
496 /// the sockets that are still being used by the monitor.
497 
499 {
500  TList *list = new TList;
501 
502  TIter next(fActive);
503 
504  while (TSocketHandler *h = (TSocketHandler*) next())
505  list->Add(h->GetSocket());
506 
507  return list;
508 }
509 
510 ////////////////////////////////////////////////////////////////////////////////
511 /// Returns a list with all de-active sockets. This list must be deleted
512 /// by the user. DO NOT call Delete() on this list as it will delete
513 /// the sockets that are still being used by the monitor.
514 
516 {
517  TList *list = new TList;
518 
520 
521  while (TSocketHandler *h = (TSocketHandler*) next())
522  list->Add(h->GetSocket());
523 
524  return list;
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 /// Emit signal when some socket is ready
529 
531 {
532  Emit("Ready(TSocket*)", (Long_t)sock);
533 }
Bool_t fMainLoop
Definition: TMonitor.h:51
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
const char * GetHostName() const
Definition: TInetAddress.h:75
virtual Bool_t Notify()
Notify when event occurred on descriptor associated with this handler.
virtual void Remove(TSocket *sock)
Remove a socket from the monitor.
Definition: TMonitor.cxx:214
TSocket * fReady
Definition: TMonitor.h:50
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Int_t GetPort() const
Definition: TInetAddress.h:77
TH1 * h
Definition: legend2.C:5
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
This is the ROOT implementation of the Qt object communication mechanism (see also http://www...
Definition: TQObject.h:53
Bool_t Notify()
Definition: TTimer.cxx:65
#define R__ASSERT(e)
Definition: TError.h:98
virtual void Add(TSocket *sock, Int_t interest=kRead)
Add socket to the monitor's active list.
Definition: TMonitor.cxx:168
TList * GetListOfActives() const
Returns a list with all active sockets.
Definition: TMonitor.cxx:498
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void RemoveAll()
Remove all sockets from the monitor.
Definition: TMonitor.cxx:241
virtual ~TMonitor()
Cleanup the monitor object. Does not delete sockets being monitored.
Definition: TMonitor.cxx:153
virtual void DeActivateAll()
De-activate all activated sockets.
Definition: TMonitor.cxx:302
Bool_t fInterrupt
Definition: TMonitor.h:52
TTimeStamp GetLastUsage()
Definition: TSocket.h:159
#define SafeDelete(p)
Definition: RConfig.h:436
static const double x2[5]
virtual void DeActivate(TSocket *sock)
De-activate a socket.
Definition: TMonitor.cxx:284
TList * GetListOfDeActives() const
Returns a list with all de-active sockets.
Definition: TMonitor.cxx:515
friend class TTimeOutTimer
Definition: TMonitor.h:43
TSocket * Select()
Return pointer to socket for which an event is waiting.
Definition: TMonitor.cxx:322
void Emit(const char *signal)
Acitvate signal without args.
Definition: TQObject.cxx:559
virtual Bool_t Notify()
Notify when timer times out.
Definition: TTimer.cxx:141
A doubly linked list.
Definition: TList.h:47
virtual void SetInterest(TSocket *sock, Int_t interest=kRead)
Set interest mask for socket sock to interest.
Definition: TMonitor.cxx:180
virtual Bool_t WriteNotify()
Notify when something can be written to the descriptor associated with this handler.
time_t GetSec() const
Definition: TTimeStamp.h:140
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
Int_t GetNanoSec() const
Definition: TTimeStamp.h:141
void SetReady(TSocket *sock)
Called by TSocketHandler::Notify() to signal which socket is ready to be read or written.
Definition: TMonitor.cxx:423
TMarker * m
Definition: textangle.C:8
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:57
virtual void InnerLoop()
Inner event loop.
Definition: TSystem.cxx:404
ClassImp(TMonitor) TMonitor
Create a monitor object.
Definition: TMonitor.cxx:103
virtual void Activate(TSocket *sock)
Activate a de-activated socket.
Definition: TMonitor.cxx:250
virtual Int_t Select(TList *active, Long_t timeout)
Select on active file descriptors (called by TMonitor).
Definition: TSystem.cxx:449
long Long_t
Definition: RtypesCore.h:50
virtual Int_t GetSize() const
Definition: TCollection.h:95
static const double x1[5]
Int_t GetActive(Long_t timeout=-1) const
Return number of sockets in the active list.
Definition: TMonitor.cxx:438
TList * fDeActive
Definition: TMonitor.h:49
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:76
virtual void Ready(TSocket *sock)
Emit signal when some socket is ready.
Definition: TMonitor.cxx:530
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:348
Mother of all ROOT objects.
Definition: TObject.h:58
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:556
Bool_t IsActive(TSocket *s) const
Check if socket 's' is in the active list.
Definition: TMonitor.cxx:482
friend class TSocketHandler
Definition: TMonitor.h:42
TMonitor(Bool_t mainloop=kTRUE)
virtual void Add(TObject *obj)
Definition: TList.h:81
Int_t GetDeActive() const
Return number of sockets in the de-active list.
Definition: TMonitor.cxx:473
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition: TSystem.cxx:475
virtual Bool_t ReadNotify()
Notify when something can be read from the descriptor associated with this handler.
TList * fActive
Definition: TMonitor.h:48
virtual void ActivateAll()
Activate all de-activated sockets.
Definition: TMonitor.cxx:268
TInetAddress GetInetAddress() const
Definition: TSocket.h:143
const Bool_t kTRUE
Definition: Rtypes.h:91