XRootD
XrdSys::IOEvents::Channel Class Reference

#include <XrdSysIOEvents.hh>

+ Collaboration diagram for XrdSys::IOEvents::Channel:

Public Types

enum  EventCode {
  readEvents = 0x01 ,
  writeEvents = 0x04 ,
  rwEvents = 0x05 ,
  errorEvents = 0x10 ,
  stopEvent = 0x20 ,
  allEvents = 0x35
}
 Event bits used to feed Enable() and Disable(); can be or'd. More...
 

Public Member Functions

 Channel (Poller *pollP, int fd, CallBack *cbP=0, void *cbArg=0)
 
void Delete ()
 
bool Disable (int events, const char **eText=0)
 
bool Enable (int events, int timeout=0, const char **eText=0)
 
void GetCallBack (CallBack **cbP, void **cbArg)
 
int GetEvents ()
 
int GetFD ()
 
void SetCallBack (CallBack *cbP, void *cbArg=0)
 
void SetFD (int fd)
 

Friends

class Poller
 

Detailed Description

Definition at line 173 of file XrdSysIOEvents.hh.

Member Enumeration Documentation

◆ EventCode

Event bits used to feed Enable() and Disable(); can be or'd.

Enumerator
readEvents 

Read and Read Timeouts.

writeEvents 

Write and Write Timeouts.

rwEvents 

Both of the above.

errorEvents 

Error event non-r/w specific.

stopEvent 

Poller stop event.

allEvents 

All of the above.

Definition at line 192 of file XrdSysIOEvents.hh.

192  {readEvents = 0x01,
193  writeEvents = 0x04,
194  rwEvents = 0x05,
195  errorEvents = 0x10,
196  stopEvent = 0x20,
197  allEvents = 0x35
198  };
@ allEvents
All of the above.
@ errorEvents
Error event non-r/w specific.
@ stopEvent
Poller stop event.
@ writeEvents
Write and Write Timeouts.
@ rwEvents
Both of the above.
@ readEvents
Read and Read Timeouts.

Constructor & Destructor Documentation

◆ Channel()

XrdSys::IOEvents::Channel::Channel ( Poller pollP,
int  fd,
CallBack cbP = 0,
void *  cbArg = 0 
)

Constructor.

Parameters
pollPPointer to the poller object to which this channel will be assigned. Events are initially disabled after assignment and no timeout applies. Poller object assignment is permanent for the life of the channel object.
fdThe associated file descriptor number. It should not be assigned to any other channel and must be valid when the channel is enabled. Use SetFD() to set a new value.
cbPPointer to the callback object (see above). The callback object must not be deleted while associated to a channel. A callback object must exist in order for the channel to be enabled. Use SetCallBack() if you deferred setting it here.
cbArgThe argument to be passed to the callback object.

Definition at line 285 of file XrdSysIOEvents.cc.

287  : chPollXQ(pollP), chCB(cbP), chCBA(cbArg)
288 {
289  attList.next = attList.prev = this;
290  tmoList.next = tmoList.prev = this;
291  inTOQ = 0;
292  pollEnt = 0;
293  chStat = isClear;
294  Reset(&pollInit, fd);
295 
296  pollP->Attach(this);
297 }

References XrdSys::IOEvents::pollInit.

Member Function Documentation

◆ Delete()

void XrdSys::IOEvents::Channel::Delete ( )

Delete a channel. You must use this method instead of delete. The Delete() may block if an channel is being deleted outside of the poller thread. When this object is deleted, all events are disabled, pending callbacks are either completed or canceled, and the channel is removed from the assigned poller. Only then is the storage freed.

Definition at line 303 of file XrdSysIOEvents.cc.

304 {
305  Poller *myPoller;
306  bool isLocked = true;
307 
308 // Do some tracing
309 //
310  IF_TRACE(Delete,chFD,"status="<<STATUS);
311 
312 // Lock ourselves during the delete process. If the channel is disassociated
313 // or the real poller is set to the error poller then this channel is clean
314 // and can be deleted (i.e. the channel ran through Detach()).
315 //
316  chMutex.Lock();
317  if (!chPollXQ || chPollXQ == &pollErr1)
318  {chMutex.UnLock();
319  delete this;
320  return;
321  }
322 
323 // Disable and remove ourselves from all queues
324 //
325  myPoller = chPollXQ;
326  chPollXQ->Detach(this,isLocked,false);
327  if (!isLocked) chMutex.Lock();
328 
329 // If we are in callback mode then we will need to delay the destruction until
330 // after the callback completes unless this is the poller thread. In that case,
331 // we need to tell the poller that we have been destroyed in a shelf-stable way.
332 //
333  if (chStat)
334  {if (XrdSysThread::Same(XrdSysThread::ID(),myPoller->pollTid))
335  {myPoller->chDead = true;
336  chMutex.UnLock();
337  } else {
338  XrdSysSemaphore cbDone(0);
339  IF_TRACE(Delete,chFD,"waiting for callback");
340  chStat = isDead;
341  chCBA = (void *)&cbDone;
342  chMutex.UnLock();
343  cbDone.Wait();
344  }
345  } else chMutex.UnLock();
346 
347 // It is now safe to release the storage
348 //
349  IF_TRACE(Delete,chFD,"chan="<< std::hex<<(void *)this<< std::dec);
350  delete this;
351 }
#define IF_TRACE(x, fd, y)
#define STATUS
static int Same(pthread_t t1, pthread_t t2)
static pthread_t ID(void)
@ dec
Definition: XrdSysTrace.hh:42
@ hex
Definition: XrdSysTrace.hh:42

References XrdSys::IOEvents::Poller::chDead, Xrd::dec, Xrd::hex, XrdSysThread::ID(), IF_TRACE, XrdSys::IOEvents::pollErr1, XrdSys::IOEvents::Poller::pollTid, XrdSysThread::Same(), STATUS, and XrdSysSemaphore::Wait().

+ Here is the call graph for this function:

◆ Disable()

bool XrdSys::IOEvents::Channel::Disable ( int  events,
const char **  eText = 0 
)

Disable one or more events. Ignored for already disabled events.

Parameters
eventsone or more events or'd together (see EventCode above).
eTextoptional pointer to where an operation description is to be placed when an error occurs (i.e. returns false).
Returns
true Events successfully disabled. false Events not disabled; errno holds the error number and if eText is supplied, points to the operation desscription.

Definition at line 357 of file XrdSysIOEvents.cc.

358 {
359  int eNum = 0, newev, curev;
360  bool retval = true, isLocked = true;
361 
362 // Lock this channel
363 //
364  chMutex.Lock();
365 
366 // Get correct current events; depending on the state of the channel
367 //
368  if (chPoller == &pollWait) curev = static_cast<int>(reMod);
369  else curev = static_cast<int>(chEvents);
370 
371 // Trace this entry
372 //
373  IF_TRACE(Disable,chFD,"->Disable(" <<events <<") chev=" <<curev);
374 
375 // Calculate new event mask
376 //
377  events &= allEvents;
378  newev = curev & ~events;
379 
380 // If something has changed, then modify the event mask in the poller. The
381 // poller may or may not unlock this channel during the process.
382 //
383  if (newev != curev)
384  {chEvents = newev;
385  retval = chPoller->Modify(this, eNum, eText, isLocked);
386  TRACE_MOD(Disable,chFD,newev);
387  } else {
388  TRACE_NOD(Disable,chFD,newev);
389  }
390  if (isLocked) chMutex.UnLock();
391 
392 // All done
393 //
394  if (!retval) errno = eNum;
395  return retval;
396 }
#define TRACE_NOD(x, fd, y)
#define TRACE_MOD(x, fd, y)
bool Disable(int events, const char **eText=0)
virtual bool Modify(Channel *cP, int &eNum, const char **eTxt, bool &isLocked)=0

References IF_TRACE, XrdSys::IOEvents::pollWait, TRACE_MOD, and TRACE_NOD.

◆ Enable()

bool XrdSys::IOEvents::Channel::Enable ( int  events,
int  timeout = 0,
const char **  eText = 0 
)

Enable one or more events. Events that are already enabled remain enabled but may have their timeout value change.

Enable can fail for many reasons. Most importantly, if the channel was disabled for all events when a fatal error occurred; enabling it immediately returns the fatal error without invoking the callback. This happens on platforms that disallow physically masking out error events.

Additionally, when an error occurs and the channel is not enabled for error events but is enabled for read or write, the callback is called indicating ReadyToRead or ReadyToWrite. A subsequent write will then end with an error (typically, EPIPE) and a subsequent read will end with an erorr or indicate zero bytes read; either of which should be treated as an error (typically, POLLHUP). Generally, you should always allow separable error events.

Parameters
eventsone or more events or'd together (see EventCode above).
timeout>0 maximum seconds that may elapsed before a timeout event corresponding to the specified event(s) occurs. =0 Keep whatever timeout is currently in effect from the previous Enable() invocation for the event(s). <0 No timeout applies. There can be separate timeouts for read and write if Enable() is separately called for each event code. Otherwise, the timeout applies to all specified events. The timeout is ignored for error events.
eTextoptional pointer to where an operation description is to be placed when an error occurs (i.e. returns false).
Returns
true Events successfully enabled. false Events not enabled; errno holds the error number and if eText is supplied, points to the operation desscription.

Definition at line 402 of file XrdSysIOEvents.cc.

404 {
405  int eNum = 0, newev, curev, tmoSet = 0;
406  bool retval, setTO, isLocked = true;
407 
408 // Lock ourselves against any changes (this is a recursive mutex)
409 //
410  chMutex.Lock();
411 
412 // Get correct current events; depending on the state of the channel
413 //
414  if (chPoller == &pollWait) curev = static_cast<int>(reMod);
415  else curev = static_cast<int>(chEvents);
416 
417 // Trace this entry
418 //
419  IF_TRACE(Enable,chFD,"->Enable("<<events<<','<<timeout<<") chev="<<curev);
420 
421 // Establish events that should be enabled
422 //
423  events &= allEvents;
424  newev = (curev ^ events) & events;
425  chEvents = curev | events;
426 
427 // Handle timeout changes now
428 //
429  if (REVENTS(events))
430  { if (timeout > 0) chRTO = timeout;
431  else if (timeout < 0) chRTO = 0;
432  if (rdDL != Poller::maxTime || chRTO) tmoSet |= CallBack::ReadyToRead;
433  }
434 
435  if (WEVENTS(events))
436  { if (timeout > 0) chWTO = timeout;
437  else if (timeout < 0) chWTO = 0;
438  if (wrDL != Poller::maxTime || chWTO) tmoSet |= CallBack::ReadyToWrite;
439  }
440 
441 // Check if we have to reset the timeout. We need to hold the channel lock here.
442 //
443  if (tmoSet && chPoller != &pollErr1)
444  setTO = chPollXQ->TmoAdd(this, tmoSet);
445  else setTO = false;
446 
447 // Check if any modifcations needed here. If so, invoke the modifier. Note that
448 // the modify will unlock the channel if the operation causes a wait. So,
449 // we cannot depend on the channel being locked upon return. The reason we do
450 // not unlock here is because we must ensure the channel doesn't change while
451 // we call modify. We let modify determine what to do.
452 //
453  if (newev)
454  {retval = chPoller->Modify(this, eNum, eText, isLocked);
455  TRACE_MOD(Enable,chFD,(curev | events));
456  } else {
457  retval = true;
458  TRACE_NOD(Enable,chFD,(curev | events));
459  }
460 
461 // We need to notify the poller thread if the added deadline is the first in the
462 // queue and the poller is waiting. We also optimize for the case where the
463 // poller thread is always woken up to perform an action in which case it
464 // doesn't need a separate wakeup. We only do this if the enable succeeed. Note
465 // that we cannot hold the channel mutex for this call because it may wait.
466 //
467  if (isLocked) chMutex.UnLock();
468  bool isWakePend = CPP_ATOMIC_LOAD(chPollXQ->wakePend, std::memory_order_consume);
469  if (retval && !isWakePend && setTO && isLocked) chPollXQ->WakeUp();
470 
471 // All done
472 //
473  if (!retval) errno = eNum;
474  return retval;
475 }
#define CPP_ATOMIC_LOAD(x, order)
#define REVENTS(x)
#define WEVENTS(x)
@ ReadyToWrite
Writing won't block.
@ ReadyToRead
New data has arrived.
bool Enable(int events, int timeout=0, const char **eText=0)
bool TmoAdd(Channel *cP, int tmoSet)

References CPP_ATOMIC_LOAD, IF_TRACE, XrdSys::IOEvents::Poller::maxTime, XrdSys::IOEvents::pollErr1, XrdSys::IOEvents::pollWait, XrdSys::IOEvents::CallBack::ReadyToRead, XrdSys::IOEvents::CallBack::ReadyToWrite, REVENTS, TRACE_MOD, TRACE_NOD, and WEVENTS.

Referenced by XrdCl::PollerBuiltIn::Start().

+ Here is the caller graph for this function:

◆ GetCallBack()

void XrdSys::IOEvents::Channel::GetCallBack ( CallBack **  cbP,
void **  cbArg 
)

Get the callback object and argument associated with this channel.

Parameters
cbPPlace where the pointer is to be returned.
cbArgPlace where the callback argument is to be returned.

Definition at line 481 of file XrdSysIOEvents.cc.

482 {
483  chMutex.Lock();
484  *cbP = chCB;
485  *cbArg = chCBA;
486  chMutex.UnLock();
487 }

◆ GetEvents()

int XrdSys::IOEvents::Channel::GetEvents ( )
inline

Get the events that are currently enabled for this channel.

Returns
>0 Event bits that are enabled (see EventCode above). =0 No events are enabled. <0 Channel not assigned to a Poller object.

Definition at line 267 of file XrdSysIOEvents.hh.

267 {return (chPoller ? static_cast<int>(chEvents) : -1);}

Referenced by XrdSys::IOEvents::PollE::Include(), XrdSys::IOEvents::PollPoll::Include(), XrdSys::IOEvents::PollPort::Include(), XrdSys::IOEvents::PollE::Modify(), XrdSys::IOEvents::PollKQ::Modify(), XrdSys::IOEvents::PollPoll::Modify(), and XrdSys::IOEvents::PollPort::Modify().

+ Here is the caller graph for this function:

◆ GetFD()

int XrdSys::IOEvents::Channel::GetFD ( )
inline

Get the file descriptor number associated with this channel.

Returns
>=0 The file descriptor number. < 0 No file desciptor associated with the channel.

Definition at line 276 of file XrdSysIOEvents.hh.

276 {return chFD;}

Referenced by XrdSys::IOEvents::PollE::Exclude(), XrdSys::IOEvents::PollKQ::Exclude(), XrdSys::IOEvents::PollPoll::Exclude(), XrdSys::IOEvents::PollPort::Exclude(), XrdSys::IOEvents::PollE::Include(), XrdSys::IOEvents::PollPoll::Include(), XrdSys::IOEvents::PollPort::Include(), XrdSys::IOEvents::PollerInit::Modify(), XrdSys::IOEvents::PollE::Modify(), XrdSys::IOEvents::PollKQ::Modify(), XrdSys::IOEvents::PollPoll::Modify(), and XrdSys::IOEvents::PollPort::Modify().

+ Here is the caller graph for this function:

◆ SetCallBack()

void XrdSys::IOEvents::Channel::SetCallBack ( CallBack cbP,
void *  cbArg = 0 
)

Set the callback object and argument associated with this channel.

Parameters
cbPPointer to the callback object (see above). The callback object must not be deleted while associated to a channel. A null callback object pointer effectively disables the channel.
cbArgThe argument to be passed to the callback object.

Definition at line 514 of file XrdSysIOEvents.cc.

515 {
516 
517 // We only need to have the channel lock to set the callback. If the object
518 // is in the process of being destroyed, we do nothing.
519 //
520  chMutex.Lock();
521  if (chStat != isDead)
522  {chCB = cbP;
523  chCBA = cbArg;
524  }
525  chMutex.UnLock();
526 }

◆ SetFD()

void XrdSys::IOEvents::Channel::SetFD ( int  fd)

Set a new file descriptor to be associated with this channel. The channel is removed from polling consideration but remains attached to the poller. The new file descriptor is recorded but the channel remains disabled. You must use Enable() to add the file descriptor back to the polling set. This allows you to retract a file descriptor about to be closed without having a new file descriptor handy (e.g., use -1). This facilitates channel re-use.

Parameters
fdThe associated file descriptor number.

Definition at line 532 of file XrdSysIOEvents.cc.

533 {
534  bool isLocked = true;
535 
536 // Obtain the channel lock. If the object is in callback mode we have some
537 // extra work to do. If normal callback then indicate the channel transitioned
538 // to prevent it being automatically re-enabled. If it's being destroyed, then
539 // do nothing. Otherwise, this is a stupid double setFD call.
540 //
541  chMutex.Lock();
542  if (chStat == isDead)
543  {chMutex.UnLock();
544  return;
545  }
546 
547 // This is a tricky deal here because we need to protect ourselves from other
548 // threads as well as the poller trying to do a callback. We first, set the
549 // poller target. This means the channel is no longer ready and callbacks will
550 // be skipped. We then remove the current file descriptor. This may unlock the
551 // channel but at this point that's ok.
552 //
553  if (inPSet)
554  {chPoller = &pollWait;
555  chPollXQ->Detach(this, isLocked, true);
556  if (!isLocked) chMutex.Lock();
557  }
558 
559 // Indicate channel needs to be re-enabled then unlock the channel
560 //
561  Reset(&pollInit, fd);
562  chMutex.UnLock();
563 }

References XrdSys::IOEvents::pollInit, and XrdSys::IOEvents::pollWait.

Friends And Related Function Documentation

◆ Poller

friend class Poller
friend

Definition at line 175 of file XrdSysIOEvents.hh.


The documentation for this class was generated from the following files: