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  }
346 // It is now safe to release the storage
347 //
348  IF_TRACE(Delete,chFD,"chan="<< std::hex<<(void *)this<< std::dec);
349  delete this;
350 }
#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 356 of file XrdSysIOEvents.cc.

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

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

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

◆ 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 513 of file XrdSysIOEvents.cc.

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

◆ 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 531 of file XrdSysIOEvents.cc.

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

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: