Flow 1.0.0
Flow project: Public API.
Public Types | Public Member Functions | Public Attributes | List of all members
flow::net_flow::Node_options Struct Reference

A set of low-level options affecting a single Flow Node, including Peer_socket objects and other objects subsequently generated by that Flow Node. More...

#include <options.hpp>

Collaboration diagram for flow::net_flow::Node_options:
[legend]

Public Types

using Options_description = Peer_socket_options::Options_description
 Short-hand for boost.program_options config options description. See setup_config_parsing().
 
using Fine_duration = Peer_socket_options::Fine_duration
 A time duration, with fine precision.
 

Public Member Functions

 Node_options ()
 Constructs a Node_options with values equal to those used by Node when the Node creator chooses not to supply custom options.
 
void setup_config_parsing (Options_description *opts_desc)
 Modifies a boost.program_options options description object to enable subsequent parsing of a command line or config file into the data members of this object, as well printing a help message about these options to an ostream. More...
 

Public Attributes

bool m_st_capture_interrupt_signals_internally
 If and only if this is true, the Node will detect SIGINT and SIGTERM (or your OS's version thereof); upon seeing such a signal, it will fire Node::interrupt_all_waits(), which will interrupt all blocking operations, conceptually similarly to POSIX's EINTR. More...
 
size_t m_st_low_lvl_max_buf_size
 The max size to ask the OS to set our UDP socket's receive buffer to in order to minimize loss if we can't process datagrams fast enough. More...
 
Fine_duration m_st_timer_min_period
 A time period such that the boost.asio timer implementation for this platform is able to accurately able to schedule events within this time period or greater. More...
 
unsigned int m_dyn_max_packets_per_main_loop_iteration
 The UDP net-stack may deliver 2 or more datagrams to the Flow Node at the same time. More...
 
size_t m_dyn_low_lvl_max_packet_size
 Any incoming low-level (UDP) packet will be truncated to this size. More...
 
bool m_dyn_guarantee_one_low_lvl_in_buf_per_socket
 This very inside-baseball setting controls the allocation/copy behavior of the UDP receive-deserialize operation sequence. More...
 
Peer_socket_options m_dyn_sock_opts
 The set of per-Peer_socket options in this per-Node set of options. More...
 

Detailed Description

A set of low-level options affecting a single Flow Node, including Peer_socket objects and other objects subsequently generated by that Flow Node.

Typically these values can be left at defaults, and thus the net_flow user normally need not deal with these objects. However, if low-level tuning of Flow internals is needed, you can use this struct.

This is just a simple struct with a couple of utilities to serialize (to ostream) and deserialize (from a config file or command line) the values in the struct; it is not connected to any other object (for example, it can exist with no Node).

You may read from and write to members of this struct at will, and no checking will be performed; moreover, doing so will have no effect other than the field being read or written.

Fields are validated and potentially take effect, however, when you pass a Node_options object to Node. Node always copies the given Node_options and never saves a reference to it. All of that applies equally to Peer_socket_options.

Node_options contains a Peer_socket_options m_dyn_sock_opts (a very similar, in spirit, struct) within it. Options stored within that are per-flow::net_flow::Peer_socket options. For example, m_st_low_lvl_max_buf_size applies to the entire Node at all times and is stored directly in *this (as there is only one UDP buffer for the entire Node); whereas max-block-size can be different for each individual Peer_socket and is thus stored in this->m_dyn_sock_opts. See Node::listen() and Node::connect() for how per-socket options are distributed to subsequent sockets as connections are made.

The struct, when default-constructed, contains sane default values as used by Node when not provided with a Node_options object. Alternatively, you can get a Node's existing set of options via Node::options().

After obtaining a Node_options either way, you may assign values to it manually.

Alternatively, you can fill it parsing a config file or command line using boost.program_options (which makes it a snap) with the help of Node_options::setup_config_parsing(), which will provide a program_options-suitable Options_description object to enable this parsing. You may conversely print Options_description to an ostream (e.g., cout) for full help text on the meaning of each option and the defaults.

You may also print a filled Node_options itself to an ostream for the current settings stored in that object.

Thready safety

Same as any struct with no locking done therein.

See also
Node constructor, Node::set_options(), Node::listen(), Node::connect().
Peer_socket::set_options(), Peer_socket::options().
Peer_socket_options.

Member Function Documentation

◆ setup_config_parsing()

void flow::net_flow::Node_options::setup_config_parsing ( Options_description opts_desc)

Modifies a boost.program_options options description object to enable subsequent parsing of a command line or config file into the data members of this object, as well printing a help message about these options to an ostream.

In particular, after executing this method:

  • If you output *opts_desc to an ostream, the ostream will get a detailed description of each option, its symbolic name (for config file or command line), and its value if the config file or command line omits this option (the default). This default will equal to the value of that particular option in a default-constructed Node_options.
  • If you perform something like the following code snippet, then *this will now be filled with values parsed from ifstream F (and default values for any omitted values):
namespace opts = boost::program_options;
Node_options flow_opts;
opts::options_description opts_desc;
std::ifstream F(...);
flow_opts.setup_config_parsing(&opts_desc);
opts::variables_map cfg_vars;
opts::store(opts::parse_config_file(F, *opts_desc), cfg_vars);
opts::notify(cfg_vars);
A set of low-level options affecting a single Flow Node, including Peer_socket objects and other obje...
Definition: options.hpp:449
void setup_config_parsing(Options_description *opts_desc)
Modifies a boost.program_options options description object to enable subsequent parsing of a command...
Definition: options.cpp:146

Note the default values will come from the current values inside *this.

Parameters
opts_descThe Options_description object into which to load the help information, defaults, and mapping to members of *this.

Member Data Documentation

◆ m_dyn_guarantee_one_low_lvl_in_buf_per_socket

bool flow::net_flow::Node_options::m_dyn_guarantee_one_low_lvl_in_buf_per_socket

This very inside-baseball setting controls the allocation/copy behavior of the UDP receive-deserialize operation sequence.

When enabled, there is exactly one input buffer large enough to hold any one serialized incoming packet; any deserialized data (including DATA and ACK payloads) are stored in separately allocated per-packet buffers; and and the input buffer is repeatedly reused without reallocation. When disabled, however, at least some packet types (most notably DATA) will use the zero-copy principle, having the deserializer take ownership of the input buffer and access pieces inside it as post-deserialization values (most notably the DATA payload); in this case the input buffer has to be reallocated between UDP reads. As of this writing the former behavior seems to be somewhat faster, especially if low-lvl-max-packet-size is unnecessarily large; but arguably the zero-copy behavior may become faster if some implementation details related to this change. So this switch seemed worth keeping.

◆ m_dyn_low_lvl_max_packet_size

size_t flow::net_flow::Node_options::m_dyn_low_lvl_max_packet_size

Any incoming low-level (UDP) packet will be truncated to this size.

This should be well above per-socket max-block-size (# of bytes of user payload per DATA packet). There will only be one buffer of this size in memory at a time, so no need to be too stingy, but on the other hand certain allocation/deallocation behavior may cause performance drops if this unnecessarily large.

◆ m_dyn_max_packets_per_main_loop_iteration

unsigned int flow::net_flow::Node_options::m_dyn_max_packets_per_main_loop_iteration

The UDP net-stack may deliver 2 or more datagrams to the Flow Node at the same time.

To lower overhead and increase efficiency, Flow will process all such datagrams – and any more that may arrive during this processing – before preparing any resulting outgoing messages, such as acknowledgments or more data packets. In high-speed conditions this may result in excessive burstiness of outgoing traffic. This option's value places a limit on the number of datagrams to process before constructing and sending any resulting outgoing messages to prevent this burstiness. If 0, there is no limit.

◆ m_dyn_sock_opts

Peer_socket_options flow::net_flow::Node_options::m_dyn_sock_opts

The set of per-Peer_socket options in this per-Node set of options.

This represents the per-socket options each subsequent socket generated in the corresponding Node will get, unless user specifies a custom set of such options.

Note that, in the context of the per-Node options set, this is dynamic; any per-socket option (even a static one) must be changeable in the global per-Node options set, as otherwise it would just be a regular per-Node data member in Node_options, as it could never change anyway, so no point in having it be per-Peer_socket.

◆ m_st_capture_interrupt_signals_internally

bool flow::net_flow::Node_options::m_st_capture_interrupt_signals_internally

If and only if this is true, the Node will detect SIGINT and SIGTERM (or your OS's version thereof); upon seeing such a signal, it will fire Node::interrupt_all_waits(), which will interrupt all blocking operations, conceptually similarly to POSIX's EINTR.

If this is true, the user may register their own signal handler(s) (for any purpose whatsoever) using boost::asio::signal_set. However, behavior is undefined if the program registers signal handlers via any other API, such as sigaction() or signal(). If you need to set up such a non-signal_set signal handler, AND you require EINTR-like behavior, then (1) set this option to false; (2) trap SIGINT and SIGTERM yourself; (3) in your handlers for the latter, simply call Node::interrupt_all_waits(). Similarly, if you want custom behavior regarding Node::interrupt_all_waits(), feel free to call it whenever you want (not necessarily even from a signal handler), and set this to false. However, if a typical, common-sense behavior is what you're after – and either don't need additional signal handling or are OK with using signal_set for it – then setting this to true is a good option.

◆ m_st_low_lvl_max_buf_size

size_t flow::net_flow::Node_options::m_st_low_lvl_max_buf_size

The max size to ask the OS to set our UDP socket's receive buffer to in order to minimize loss if we can't process datagrams fast enough.

This should be as high as possible while being "acceptable" in terms of memory. However, the OS will probably have its own limit and may well pick a limit that is the minimum of that limit and this value.

◆ m_st_timer_min_period

Fine_duration flow::net_flow::Node_options::m_st_timer_min_period

A time period such that the boost.asio timer implementation for this platform is able to accurately able to schedule events within this time period or greater.

If you select 0, the code will decide what this value is based on the platform, but its logic for this may or may not be correct (actually it will probably be correct but possibly too conservative [large], causing timer coarseness in mechanisms like the rather critical packet pacing).


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