1. nanomsgxx-polling(7)
  2. nanomsgxx
  3. nanomsgxx-polling(7)

NAME

nanomsgxx-polling - Nanomsgxx Polling

DESCRIPTION

The nanomsg C API provides a powerful polling system that is mirrored on POSIX's polling interface. C++ though doesn't have any sort of interface for polling events on file descriptors in the standard library, so nanomsgxx comes with its own API for polling on nanomsg sockets instead of integrating with an existing one.
The wrapper is very small and mostly is syntaxing sugar on top of the C API.

ENTRIES

Polling is done by passing a vector or nnxx::poll_entry objects to the nnxx::poll function, such objects are defined as:

class poll_entry : public nn_pollfd {
public:
  poll_entry() noexcept;
  poll_entry(int socket, int events) noexcept;
  poll_entry(socket &socket, int events) noexcept;

  void clear() noexcept;
  void set(int socket, int events) noexcept;
  void set(socket &socket, int events) noexcept;

  bool is(const socket &s) const noexcept;
  bool recv_ready() const noexcept;
  bool send_ready() const noexcept;
};

They are simple descriptors associtating sockets to a set of events that we wnat to wait for and will get filled with events that happened while calling nnxx::poll. They inherit from nn_pollfd for compatibility with the C API, and simply add some useful operations.
Read nn_poll's documentation to learn more about how the polling mechanism works.

POLL

nnxx::poll is available in different versions that makes it easy to use in multiple situations. The two main interfaces are as follow:

poll_vector  poll(poll_vector &&, <timeout>, <flags>);
poll_vector &poll(poll_vector  &, <timeout>, <flags>);

The first version accepts a temporary vector object that is used for polling the entries it contains and will be returned by the function with a move operation, so no extra memory will be allocated.

The second version accepts a reference to a vector object allocated somewhere else in the program. Based on the use case one may find useful to use one version or the other.

The vector returned by nnxx::poll has its entries set with whatever events have been found on the sockets, the entries then should be iterated and checked to verify which events are available for which socket.
nanomsgxx comes with two useful functions, nnxx::recv_ready and nnxx::send_ready, that return iterable objects that will filter entries that were marked by nnxx::poll as ready for receiving or sending messages.
Here's an usage example:

nnxx::socket s1 { /* ... */ };
nnxx::socket s2 { /* ... */ };

// ...

// Polling the socket, nnxx::poll_vector can be initialized from a
// std::initializer_list<nnxx::poll_entry>
nnxx::poll_vector entries = nnxx::poll({
    { s1, nnxx::EV_POLLIN },
    { s2, nnxx::EV_POLLIN | nnxx::EV_POLLOUT },
  });

for (auto e : nnxx::recv_ready(entries)) {
  // All entries enumerated here won't block on a receive operation.
}

for (auto e : nnxx::send_ready(entries)) {
  // All entries enumerated here won't block on a send operation.
}

The C API uses NN_POLIN and NN_POLOUT as event flags, so nanomsgxx should have named its constants nnxx::POLLIN and nnxx::POLLOUT, but these names are macros defined on POSIX systems supporting the poll interface and would cause compilation to fail. That's why nanomsgxx uses nnxx::EV_POLLIN and nnxx::EV_POLLOUT instead.

Polling is by nature a blocking operation, so the API has to provides a way to set a timeout that will give the hand back to the program in case nothing happens for a while because we may have to do some other things once in a while.

As described in the design section, exceptions are used to report timeouts in the nanomsgxx API.
A timeout can be specified as second argument to the nnxx::poll function, it may be give as a std::chrono::duration (if we want to set how long the function should wait), or as a std::chrono::time_point (if we want to set when the function should return).
Here's how we'd handle a timeout:

nnxx::poll_vector entries;

// ...

try {
  // Polls for events, waits at most one second.
  entries = nnxx::poll({
      { s1, nnxx::EV_POLLIN },
      { s2, nnxx::EV_POLLIN | nnxx::EV_POLLOUT },
    },
    std::chrono::second(1));
}
catch (const nnxx::timeout_error &) {
  // Nothing happened for more than one second.
}

SEE ALSO

nnxx::poll(3)
nanomsgxx(7)
nanomsgxx-sockets(7)
nanomsg(7)

AUTHORS

Achille Roussel

  1. achille.roussel@gmail.com
  2. May 2014
  3. nanomsgxx-polling(7)