// @(#)root/net:$Name: $:$Id: TMonitor.cxx,v 1.7 2004/12/15 17:48:03 rdm Exp $
// Author: Fons Rademakers 09/01/97
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TMonitor //
// //
// This class monitors activity on a number of network sockets. //
// The actual monitoring is done by TSystem::DispatchOneEvent(). //
// Typical usage: create a TMonitor object. Register a number of //
// TSocket objects and call TMonitor::Select(). Select() returns the //
// socket object which has data waiting. TSocket objects can be added, //
// removed, (temporary) enabled or disabled. //
// //
//////////////////////////////////////////////////////////////////////////
#include "TMonitor.h"
#include "TSocket.h"
#include "TList.h"
#include "TSystem.h"
#include "TSysEvtHandler.h"
#include "TTimer.h"
#include "TError.h"
//---- Socket event handler ----------------------------------------------------
//
// This utility class is only used by TMonitor.
//
class TSocketHandler : public TFileHandler {
private:
TMonitor *fMonitor; //monitor to which this handler belongs
TSocket *fSocket; //socket being handled
public:
TSocketHandler(TMonitor *m, TSocket *s, Int_t interest, Bool_t mainloop = kTRUE);
Bool_t Notify();
Bool_t ReadNotify() { return Notify(); }
Bool_t WriteNotify() { return Notify(); }
TSocket *GetSocket() const { return fSocket; }
};
TSocketHandler::TSocketHandler(TMonitor *m, TSocket *s,
Int_t interest, Bool_t mainloop)
: TFileHandler(s->GetDescriptor(), interest)
{
fMonitor = m;
fSocket = s;
if (mainloop)
Add();
}
Bool_t TSocketHandler::Notify()
{
fMonitor->SetReady(fSocket);
return kTRUE;
}
//---- Timeout timer -----------------------------------------------------------
//
// This utility class is only used via TMonitor::Select(Int_t timeout)
//
class TTimeOutTimer : public TTimer {
private:
TMonitor *fMonitor; //monitor to which this timer belongs
public:
TTimeOutTimer(TMonitor *m, Long_t ms);
Bool_t Notify();
};
TTimeOutTimer::TTimeOutTimer(TMonitor *m, Long_t ms)
: TTimer(ms, kTRUE)
{
fMonitor = m;
gSystem->AddTimer(this);
}
Bool_t TTimeOutTimer::Notify()
{
fMonitor->SetReady((TSocket *)-1);
Remove(); // one shot only
return kTRUE;
}
//------------------------------------------------------------------------------
ClassImp(TMonitor)
//______________________________________________________________________________
TMonitor::TMonitor(Bool_t mainloop)
{
// Create a monitor object. If mainloop is true the monitoring will be
// done in the main event loop.
Assert(gSystem);
fActive = new TList;
fDeActive = new TList;
fMainLoop = mainloop;
}
//______________________________________________________________________________
TMonitor::~TMonitor()
{
// Cleanup the monitor object. Does not delete socket being monitored.
fActive->Delete();
SafeDelete(fActive);
fDeActive->Delete();
SafeDelete(fDeActive);
}
//______________________________________________________________________________
void TMonitor::Add(TSocket *sock, Int_t interest)
{
// Add socket to the monitor's active list. If interest=kRead then we
// want to monitor the socket for read readiness, if interest=kWrite
// then we monitor the socket for write readiness, if interest=kRead|kWrite
// then we monitor both read and write readiness.
fActive->Add(new TSocketHandler(this, sock, interest, fMainLoop));
}
//______________________________________________________________________________
void TMonitor::SetInterest(TSocket *sock, Int_t interest)
{
// Set interest mask for socket sock to interest. If the socket is not
// in the active list move it or add it there.
// If interest=kRead then we want to monitor the socket for read readiness,
// if interest=kWrite then we monitor the socket for write readiness,
// if interest=kRead|kWrite then we monitor both read and write readiness.
TSocketHandler *s = 0;
if (!interest)
interest = kRead;
// Check first the activated list ...
TIter next(fActive);
while ((s = (TSocketHandler *) next())) {
if (sock == s->GetSocket()) {
s->SetInterest(interest);
return;
}
}
// Check now the deactivated list ...
TIter next1(fDeActive);
while ((s = (TSocketHandler *) next1())) {
if (sock == s->GetSocket()) {
fDeActive->Remove(s);
fActive->Add(s);
s->SetInterest(interest);
return;
}
}
// The socket is not in our lists: just add it
fActive->Add(new TSocketHandler(this, sock, interest, fMainLoop));
}
//______________________________________________________________________________
void TMonitor::Remove(TSocket *sock)
{
// Remove a socket from the monitor.
TIter next(fActive);
TSocketHandler *s;
while ((s = (TSocketHandler *) next())) {
if (sock == s->GetSocket()) {
fActive->Remove(s);
delete s;
return;
}
}
TIter next1(fDeActive);
while ((s = (TSocketHandler *) next1())) {
if (sock == s->GetSocket()) {
fDeActive->Remove(s);
delete s;
return;
}
}
}
//______________________________________________________________________________
void TMonitor::RemoveAll()
{
// Remove all sockets from the monitor.
fActive->Delete();
fDeActive->Delete();
}
//______________________________________________________________________________
void TMonitor::Activate(TSocket *sock)
{
// Activate a de-activated socket.
TIter next(fDeActive);
TSocketHandler *s;
while ((s = (TSocketHandler *) next())) {
if (sock == s->GetSocket()) {
fDeActive->Remove(s);
fActive->Add(s);
s->Add();
return;
}
}
}
//______________________________________________________________________________
void TMonitor::ActivateAll()
{
// Activate all de-activated sockets.
TIter next(fDeActive);
TSocketHandler *s;
while ((s = (TSocketHandler *) next())) {
fActive->Add(s);
s->Add();
}
fDeActive->Clear();
}
//______________________________________________________________________________
void TMonitor::DeActivate(TSocket *sock)
{
// De-activate a socket.
TIter next(fActive);
TSocketHandler *s;
while ((s = (TSocketHandler *) next())) {
if (sock == s->GetSocket()) {
fActive->Remove(s);
fDeActive->Add(s);
s->Remove();
return;
}
}
}
//______________________________________________________________________________
void TMonitor::DeActivateAll()
{
// De-activate all activated sockets.
TIter next(fActive);
TSocketHandler *s;
while ((s = (TSocketHandler *) next())) {
fDeActive->Add(s);
s->Remove();
}
fActive->Clear();
}
//______________________________________________________________________________
TSocket *TMonitor::Select()
{
// Return pointer to socket for which an event is waiting.
// Return 0 in case of error.
fReady = 0;
while (!fReady)
gSystem->InnerLoop();
return fReady;
}
//______________________________________________________________________________
TSocket *TMonitor::Select(Long_t timeout)
{
// Return pointer to socket for which an event is waiting.
// Wait a maximum of timeout milliseconds.
// If return is due to timeout it returns (TSocket *)-1.
// Return 0 in case of any other error situation.
fReady = 0;
TTimeOutTimer t(this, timeout);
while (!fReady)
gSystem->InnerLoop();
return fReady;
}
//______________________________________________________________________________
Int_t TMonitor::Select(TList *rdready, TList *wrready, Long_t timeout)
{
// Return numbers of sockets that are ready for reading or writing.
// Wait a maximum of timeout milliseconds.
// Return 0 if timed-out. Return < 0 in case of error.
// If rdready and/or wrready are not 0, the lists of sockets with
// something to read and/or write are also returned.
Int_t nr = -2;
TSocketHandler *h = 0;
Int_t ns = fActive->GetSize();
if (ns == 1) {
// Avoid additional loops inside
h = (TSocketHandler *)fActive->First();
nr = gSystem->Select((TFileHandler *)h, timeout);
} else if (ns > 1) {
nr = gSystem->Select(fActive, timeout);
}
if (nr > 0 && (rdready || wrready)) {
// Clear the lists
if (rdready)
rdready->Clear();
if (wrready)
wrready->Clear();
// Got a file descriptor
if (!h) {
TIter next(fActive);
while ((h = (TSocketHandler *)next())) {
if (rdready && h->IsReadReady())
rdready->Add(h->GetSocket());
if (wrready && h->IsWriteReady())
wrready->Add(h->GetSocket());
}
} else {
if (rdready && h->IsReadReady())
rdready->Add(h->GetSocket());
if (wrready && h->IsWriteReady())
wrready->Add(h->GetSocket());
}
}
return nr;
}
//______________________________________________________________________________
void TMonitor::SetReady(TSocket *sock)
{
// Called by TSocketHandler::Notify() to signal which socket is ready
// to be read or written. User should not call this routine. The ready
// socket will be returned via the Select() user function.
// Ready(TSocket *sock) signal is emitted.
fReady = sock;
Ready(fReady);
}
//______________________________________________________________________________
Int_t TMonitor::GetActive() const
{
// Return number of sockets in the active list.
return fActive->GetSize();
}
//______________________________________________________________________________
Int_t TMonitor::GetDeActive() const
{
// Return number of sockets in the de-active list.
return fDeActive->GetSize();
}
//______________________________________________________________________________
TList *TMonitor::GetListOfActives() const
{
// Returns a list with all active sockets. This list must be deleted
// by the user. DO NOT call Delete() on this list as it will delete
// the sockets that are still being used by the monitor.
TList *list = new TList;
TIter next(fActive);
while (TSocketHandler *h = (TSocketHandler*) next())
list->Add(h->GetSocket());
return list;
}
//______________________________________________________________________________
TList *TMonitor::GetListOfDeActives() const
{
// Returns a list with all de-active sockets. This list must be deleted
// by the user. DO NOT call Delete() on this list as it will delete
// the sockets that are still being used by the monitor.
TList *list = new TList;
TIter next(fDeActive);
while (TSocketHandler *h = (TSocketHandler*) next())
list->Add(h->GetSocket());
return list;
}
//______________________________________________________________________________
void TMonitor::Ready(TSocket *sock)
{
// Emit signal when some socket is ready
Emit("Ready(TSocket*)", (Long_t)sock);
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.