DUDS
Distributed Update of Data from Something
duds::os::linux::Poller Class Reference

A simple C++ interface to using Linux's epoll functions. More...

#include <Poller.hpp>

Inheritance diagram for duds::os::linux::Poller:
Collaboration diagram for duds::os::linux::Poller:

Classes

struct  ResponderRecord
 Holds a PollResponder object and its associated file descriptor. More...
 

Public Member Functions

 Poller (int reserveSize=0)
 Constructs a new Poller and obtains a file descriptor for use with epoll. More...
 
 Poller (Poller &&p)
 A move constructor; not thread-safe. More...
 
 ~Poller ()
 Closes the internal file desciptor used with epoll. More...
 
void add (const PollResponderSptr &prs, int fd, int events=EPOLLIN)
 Adds a PollResponder to check for events on a file descriptor. More...
 
Polleroperator= (Poller &&p) noexcept
 Move assignment. More...
 
void remove (int fd)
 Removes the entry for the given file descriptor. More...
 
int respond ()
 Responds to events that are already waiting. More...
 
int wait (std::chrono::milliseconds timeout)
 Waits up to the specified time for events, and processes events immediately. More...
 
int wait ()
 Waits indefinitely for events, only returning after an event is received. More...
 

Static Public Attributes

static constexpr int maxEvents = 32
 The maximum number of events that will be read by a single call to wait(std::chrono::milliseconds). More...
 

Private Types

typedef std::vector< ResponderRecordResponderVec
 Type that holds PollResponder objects and their associated file descriptors. More...
 

Private Attributes

std::mutex block
 Used to allow for thread-safe operation. More...
 
int epfd
 The file descriptor provided by epoll_create(). More...
 
std::vector< int > flist
 Free spot list. More...
 
ResponderVec responders
 The responders and their file descriptors. More...
 

Detailed Description

A simple C++ interface to using Linux's epoll functions.

This class is mostly thread-safe. It is intended for handling events on one thread at a time, but events may be added and removed from multiple threads, even while waiting on events. A Poller object must not be destructed if it is waiting on events.

File descriptors are not managed by this class. They must be usable if given to add(). Once give to add(), file descriptors must not be closed until after given to remove() or the Poller has been destructed. The Poller does not take responsibility for this, or for closing the descriptors. Failure to remove a file descriptor prior to closing it may result in epoll_ctl() not being able to remove the descriptor, while epoll_wait() may still receive events from the underlying kernel object. The Poller will handle this as gracefully as possible, but calls to wait() may end early without handling events because it received an event from a closed file descriptor.

Author
Jeff Jackowski
Examples:
bppmenu.cpp.

Definition at line 117 of file Poller.hpp.

Member Typedef Documentation

◆ ResponderVec

Type that holds PollResponder objects and their associated file descriptors.

Definition at line 138 of file Poller.hpp.

Constructor & Destructor Documentation

◆ Poller() [1/2]

duds::os::linux::Poller::Poller ( int  reserveSize = 0)

Constructs a new Poller and obtains a file descriptor for use with epoll.

Parameters
reserveSizeThe size to reserve in the internal vectors. If the maximum number of responders are known, passing in that value here may limit vector resizing.
Exceptions
PollerCreateErrorepoll_create() failed.

Definition at line 19 of file Poller.cpp.

◆ Poller() [2/2]

duds::os::linux::Poller::Poller ( Poller &&  p)

A move constructor; not thread-safe.

Definition at line 32 of file Poller.cpp.

◆ ~Poller()

duds::os::linux::Poller::~Poller ( )

Closes the internal file desciptor used with epoll.

Does nothing to the file descriptors used by the Responder functions.

Precondition
This Poller is not waiting on events in another thread.
Warning
The destructor must not be invoked while wait() is running on another thread. Doing so will result in wait() attempting to use members after the object is destructed.

Definition at line 39 of file Poller.cpp.

Member Function Documentation

◆ add()

void duds::os::linux::Poller::add ( const PollResponderSptr prs,
int  fd,
int  events = EPOLLIN 
)

Adds a PollResponder to check for events on a file descriptor.

The function uses a free list to run in O(1) time (excluding epoll_ctl()), but it will need to allocate memory if the responders vector isn't large enough.

Precondition
The file descriptor fd is not already added to this Poller.
Parameters
prsA shared pointer to the object that will be informed when an event on the file descriptor occurs. The same object may be used with multiple file descriptors. Internally, a std::weak_ptr to the object will be kept to avoid giving the Poller any responsibility for the memory or life-span of the PollResponder object.
fdThe file descriptor. remove() should be called with this descriptor prior to closing the file. Destruction of prs will not automatically remove the entry made by add().
eventsSee the documentation for epoll_ctl() and epoll_event::events. The defulat is for data availble for reading without blocking.
Exceptions
PollerErrorepoll_ctl() reported an error.

Definition at line 54 of file Poller.cpp.

Referenced by duds::os::linux::EvdevInput::usePoller().

◆ operator=()

Poller & duds::os::linux::Poller::operator= ( Poller &&  p)
noexcept

Move assignment.

Must not be called if p.wait() is running on another thread.

Definition at line 44 of file Poller.cpp.

◆ remove()

void duds::os::linux::Poller::remove ( int  fd)

Removes the entry for the given file descriptor.

This requires a search of a vector, so it runs in O(n) time (excluding epoll_ctl()).

Precondition
fd is not yet closed.
Parameters
fdThe file descriptor. If the file is already closed, the PollResponder entry will be removed, but epoll_ctl() might not remove the file from its interest list. If the kernel object previously referenced by the file still exists, epoll_wait() will continue to report events on the file.
Exceptions
PollerErrorepoll_ctl() reported an error.
PollerLacksFileDescriptorEither this Poller has no entry for the given file descriptor, or epoll_ctl failed to remove it from its interest list.

Definition at line 83 of file Poller.cpp.

◆ respond()

int duds::os::linux::Poller::respond ( )
inline

Responds to events that are already waiting.

Same as calling wait(std::chrono::milliseconds(0)).

See also
wait(std::chrono::milliseconds).

Definition at line 278 of file Poller.hpp.

◆ wait() [1/2]

int duds::os::linux::Poller::wait ( std::chrono::milliseconds  timeout)

Waits up to the specified time for events, and processes events immediately.

Up to maxEvents events may be recorded in a single call; this maximum was chosen arbitrarily. If more events are availble, the additional events will be immediately handled on the next call to wait().

Before the PollResponder::respond() functions can be invoked, they must be found within the internal vector responders. Data registered with epoll allows the PollResponder object corresponding to an event to be found in O(1) time. The weak pointer to the PollResponder object is converted to a shared pointer. If this does not result in an existing object, the event will be ignored.

The PollResponder::respond() functions are called in the order that the associated events were reported by epoll_wait(). Any thrown exceptions are caught and ignored. This behavior may change to allow the exceptions to be reported.

Warning
This function is not thread-safe. While add() and remove() may be called from multiple threads while wait() is running, only one thread at a time can call wait successfully.
Parameters
timeoutThe maximum amount of time to wait for events to occur. The function will begin processing events as soon as they are available, and returns after processing. A value of zero will handle events that are already queued without waiting for more. A value of -1 will wait indefinitely.
Returns
The number of events handled. If zero, the function either waited the maximum amount of time, or a reported event lacked a corresponding PollResponder object. Returns -1 if epoll_wait() reports EINTR (interrupted system call).
Exceptions
PollerErrorepoll_wait() reported an error other than EINTR.

Definition at line 129 of file Poller.cpp.

◆ wait() [2/2]

int duds::os::linux::Poller::wait ( )
inline

Waits indefinitely for events, only returning after an event is received.

A received event will not be handled if there is no corresponding PollResponder object, but this function will still return. Same as calling wait(std::chrono::milliseconds(-1)).

See also
wait(std::chrono::milliseconds).

Definition at line 270 of file Poller.hpp.

Member Data Documentation

◆ block

std::mutex duds::os::linux::Poller::block
private

Used to allow for thread-safe operation.

Definition at line 151 of file Poller.hpp.

Referenced by add(), operator=(), remove(), wait(), and ~Poller().

◆ epfd

int duds::os::linux::Poller::epfd
private

The file descriptor provided by epoll_create().

Definition at line 155 of file Poller.hpp.

Referenced by add(), operator=(), Poller(), remove(), wait(), and ~Poller().

◆ flist

std::vector<int> duds::os::linux::Poller::flist
private

Free spot list.

Definition at line 147 of file Poller.hpp.

Referenced by add(), operator=(), Poller(), and remove().

◆ maxEvents

constexpr int duds::os::linux::Poller::maxEvents = 32
static

The maximum number of events that will be read by a single call to wait(std::chrono::milliseconds).

Definition at line 161 of file Poller.hpp.

Referenced by wait().

◆ responders

ResponderVec duds::os::linux::Poller::responders
private

The responders and their file descriptors.

A vector is used to allow O(1) lookups when responding to events.

Definition at line 143 of file Poller.hpp.

Referenced by add(), operator=(), Poller(), remove(), and wait().


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