TSDuck v3.44-4659
MPEG Transport Stream Toolkit
Loading...
Searching...
No Matches
ts::NonBlockingDevice Class Reference

Base class for devices, files, or sockets which can work in non-blocking mode. More...

#include <tsNonBlockingDevice.h>

Inheritance diagram for ts::NonBlockingDevice:
Collaboration diagram for ts::NonBlockingDevice:

Classes

class  AncillaryData
 Virtual base class for ancillary data in IOSB. More...
 
class  IOSB
 This structure indicates the status of a non-blocking I/O. More...
 

Public Member Functions

 NonBlockingDevice (Report *report=nullptr, bool non_blocking=false)
 Constructor.
 
 NonBlockingDevice (ReporterBase *delegate, bool non_blocking=false)
 Constructor.
 
virtual ~NonBlockingDevice () override
 Destructor.
 
bool isNonBlocking () const
 Check if the device is in non-blocking mode.
 
bool muteReport (bool mute)
 Temporarily mute the associated report.
 
Reportreport () const
 Access the Report which is associated with this object.
 
bool setNonBlocking (bool non_blocking)
 Set the device in non-blocking mode.
 
ReportsetReport (Report *report)
 Associate this object with another Report to log errors.
 
ReporterBasesetReport (ReporterBase *delegate)
 Associate this object with another ReporterBase to log errors.
 

Static Public Member Functions

static int SilentLevel (bool silent)
 Compute a log severity level from a "silent" parameter.
 

Protected Member Functions

virtual bool allowSetNonBlocking () const
 Check that the non-blocking mode can be set.
 
bool checkNonBlocking (bool non_blocking, const UChar *opname)
 Check the blocking mode of a device.
 
bool checkNonBlocking (IOSB *iosb, const UChar *opname)
 Check the blocking mode of a device.
 
bool setSystemNonBlocking (SysSocketType fd, bool non_blocking)
 Convenience method to set a system file descriptor or socket handle in non-blocking mode.
 

Detailed Description

Base class for devices, files, or sockets which can work in non-blocking mode.

The methods from this class should not be used by applications. They should be used only by "reactive classes", which work in combination with an event dispatcher.

The exact meaning of "non-blocking" depends on the type of device and the operating system. This is why this class shall be used by specialized classes which exactly know what they are doing.

There are two distinct I/O models:

  • Non-blocking I/O (UNIX).
  • Asynchronous I/O (Windows).

Differences in semantics:

  • On UNIX systems (Linux, macOS, BSD), non-blocking means that a read or write operation fails if it cannot be immediately served. The corresponding error is EAGAIN.
  • On Windows systems, non-blocking means using "overlapped" I/O. For anyone with a basic system culture, this means "asynchronous" I/O. An asynchronous I/O operation can either immediately succeed or fail with error ERROR_IO_PENDING, meaning that the operation executes in the background.

Differences in usage:

  • Execution logic: On UNIX systems, an event dispatcher notifies the applications when an I/O may be "possible". When notified, the application shall repeatedly read or write all possible data, until an EAGAIN error indicates that no more I/O is immediately possible. On Windows systems, the application starts an I/O and control immediately returns. The I/O data exchange continues in the background. The event dispatcher notifies the application when the I/O completes.
  • Data buffer usage: On UNIX, an I/O is either immediate or failed. On Windows, the I/O is in progress as long as it is not completed. This means that, on Windows, I/O buffers which are used for read or write must be available during the asynchronous phase of the I/O, because the data can come in or go out at any time. On UNIX systems, on the contrary, no buffer is used while waiting for some I/O to become possible.

Important differences in canceling I/O and closing file descriptors or handles:

  • On UNIX, a non-blocking I/O is either immediate or failed. No I/O is ever "in progress". Closing a file descriptor is possible at any time without restriction.
  • On Windows, a pending I/O can be canceled either explicitly or as the result of closing the device handle. In that case, the I/O completion is notified later with an I/O error status. This means that the I/O data buffer and IOSB (see below) shall remain valid as long as this corresponding I/O completion has not been received. It is of the utmost importance that the application keeps track of all pending asynchronous I/O and always waits for the reception of all corresponding I/O completions before releasing the memory for the data buffers, including when closing the device handle.

Constructor & Destructor Documentation

◆ NonBlockingDevice() [1/2]

ts::NonBlockingDevice::NonBlockingDevice ( Report report = nullptr,
bool  non_blocking = false 
)
inlineexplicit

Constructor.

Parameters
[in]reportWhere to report errors. The report object must remain valid as long as this object exists or setReport() is used with another Report object. If report is null, log messages are discarded.
[in]non_blockingIt true, the device is initially set in non-blocking mode.

◆ NonBlockingDevice() [2/2]

ts::NonBlockingDevice::NonBlockingDevice ( ReporterBase delegate,
bool  non_blocking = false 
)
inlineexplicit

Constructor.

Parameters
[in]delegateUse the report of another ReporterBase. If delegate is null, log messages are discarded.
[in]non_blockingIt true, the device is initially set in non-blocking mode.

Member Function Documentation

◆ setNonBlocking()

bool ts::NonBlockingDevice::setNonBlocking ( bool  non_blocking)

Set the device in non-blocking mode.

Important: Usually, this method must be called before opening the device, whatever it means. Otherwise it is ignored and the device blocking mode is unchanged.

Parameters
[in]non_blockingIt true, the device is set in non-blocking mode.
Returns
True on success, false if the device is already open and the non-blocking mode is unchanged.

◆ isNonBlocking()

bool ts::NonBlockingDevice::isNonBlocking ( ) const
inline

Check if the device is in non-blocking mode.

Returns
True if the device is in non-blocking mode, false otherwise.
See also
setNonBlocking()

◆ checkNonBlocking() [1/2]

bool ts::NonBlockingDevice::checkNonBlocking ( bool  non_blocking,
const UChar opname 
)
protected

Check the blocking mode of a device.

Called by subclass methods which are explicitly called in blocking or non-blocking mode.

Parameters
[in]non_blockingThe required non-blocking mode.
[in]opnameName of the operation, for the error message.
Returns
True on success, false on error.

◆ checkNonBlocking() [2/2]

bool ts::NonBlockingDevice::checkNonBlocking ( IOSB iosb,
const UChar opname 
)
protected

Check the blocking mode of a device.

Called by subclass methods which are explicitly called in blocking or non-blocking mode.

Parameters
[in,out]iosbAddress of an IOSB structure. If non-null, we are in non-blocking mode. When null, we are in blocking mode. When non-null, pending is reset to false and overlap is zeroed.
[in]opnameName of the operation, for the error message.
Returns
True on success, false on error.

◆ allowSetNonBlocking()

virtual bool ts::NonBlockingDevice::allowSetNonBlocking ( ) const
protectedvirtual

Check that the non-blocking mode can be set.

Must be implemented by subclasses which do not support setting the non-blocking in certain states, such as after being opened. The default implementation always allows setting the non-blocking mode.

Returns
True if setting the non-blocking mode is allowed, false otherwise.

Reimplemented in ts::Socket.

◆ setSystemNonBlocking()

bool ts::NonBlockingDevice::setSystemNonBlocking ( SysSocketType  fd,
bool  non_blocking 
)
protected

Convenience method to set a system file descriptor or socket handle in non-blocking mode.

Parameters
[in]fdSystem file descriptor (UNIX) or socket handle (Windows). On Windows, non-socket devices shall be opened with flag FILE_FLAG_OVERLAPPED instead of using this method.
[in]non_blockingIt true, the device is set in non-blocking mode.
Returns
True on success, false on error.

◆ report()

Report & ts::ReporterBase::report ( ) const
inherited

Access the Report which is associated with this object.

Can be called from another thread only if the Report object is thread-safe.

Returns
A reference to the associated report.

◆ setReport() [1/2]

Report * ts::ReporterBase::setReport ( Report report)
inherited

Associate this object with another Report to log errors.

Parameters
[in]reportWhere to report errors. The report object must remain valid as long as this object exists or setReport() is used with another Report object. If report is null, log messages are discarded.
Returns
The address of the previous Report object or a null pointer if there was none.

◆ setReport() [2/2]

ReporterBase * ts::ReporterBase::setReport ( ReporterBase delegate)
inherited

Associate this object with another ReporterBase to log errors.

Parameters
[in]delegateUse the report of another ReporterBase. If delegate is null, the previous explicit Report is used..
Returns
The address of the previous ReporterBase object or a null pointer if there was none.

◆ muteReport()

bool ts::ReporterBase::muteReport ( bool  mute)
inherited

Temporarily mute the associated report.

Parameters
[in]muteIt true, report() will return a null report (log messages are discarded), until muteReport() is invoked again with mute set to false.
Returns
Previous state of the mute field.

◆ SilentLevel()

static int ts::ReporterBase::SilentLevel ( bool  silent)
inlinestaticinherited

Compute a log severity level from a "silent" parameter.

Some subclass methods have a "silent" parameter to avoid reporting errors which may be insignificant, typically when closing a device after an error, in which case the close operation may produce other errors if the previous error left the device in an inconsistent state. While those errors should not be displayed as errors, we still display them at debug level.

Parameters
[in]silentIf true, do not report errors, report debug messages instead.
Returns
Error when silent is false, Debug otherwise.

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