XRootD
Loading...
Searching...
No Matches
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)

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

Referenced by XrdCl::PollerBuiltIn::Finalize(), XrdCl::PollerBuiltIn::RemoveSocket(), and XrdCl::PollerBuiltIn::Stop().

+ Here is the call graph for this function:
+ Here is the caller 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.

Referenced by XrdCl::PollerBuiltIn::EnableReadNotification(), XrdCl::PollerBuiltIn::EnableWriteNotification(), XrdCl::PollerBuiltIn::RemoveSocket(), and XrdCl::PollerBuiltIn::Stop().

+ Here is the caller graph for this function:

◆ 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::EnableReadNotification(), XrdCl::PollerBuiltIn::EnableWriteNotification(), and 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::PollE::Modify(), XrdSys::IOEvents::PollerInit::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 Symbol 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: