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 Poller, and XrdSys::IOEvents::pollInit.

Here is the call graph for this function:

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)

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

Referenced by Delete(), 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 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)

References allEvents, Disable(), IF_TRACE, XrdSys::IOEvents::pollWait, TRACE_MOD, and TRACE_NOD.

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

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

References allEvents, CPP_ATOMIC_LOAD, Enable(), 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 Enable(), XrdCl::PollerBuiltIn::EnableReadNotification(), XrdCl::PollerBuiltIn::EnableWriteNotification(), and XrdCl::PollerBuiltIn::Start().

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

◆ Poller

friend class Poller
friend

Definition at line 175 of file XrdSysIOEvents.hh.

References Poller.

Referenced by Channel(), Delete(), and Poller.


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