Flow 1.0.0
Flow project: Public API.
|
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>
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... | |
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.
Same as any struct
with no locking done therein.
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:
*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.*this
will now be filled with values parsed from ifstream F
(and default values for any omitted values):Note the default values will come from the current values inside *this
.
opts_desc | The Options_description object into which to load the help information, defaults, and mapping to members of *this . |
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.
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.
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.
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.
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.
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.
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).