Flow 1.0.0
Flow project: Full implementation reference.
|
Represents the remote endpoint of a Flow-protocol connection; identifies the UDP endpoint of the remote Node and the logical Flow-protocol port within that Node. More...
#include <endpoint.hpp>
Public Member Functions | |
size_t | hash () const |
Hash value of this Remote_endpoint for unordered_*<> . More... | |
Public Attributes | |
util::Udp_endpoint | m_udp_endpoint |
UDP address (IP address/UDP port) where the Node identified by this endpoint bound its low-level UDP socket. More... | |
flow_port_t | m_flow_port = 0 |
The logical Flow port within the Node for the particular connection identified by this endpoint. More... | |
Related Functions | |
(Note that these are not member functions.) | |
std::ostream & | operator<< (std::ostream &os, const Remote_endpoint &endpoint) |
Prints string representation of the given Remote_endpoint to the given ostream . More... | |
bool | operator== (const Remote_endpoint &lhs, const Remote_endpoint &rhs) |
Whether lhs is equal to rhs . More... | |
size_t | hash_value (const Remote_endpoint &remote_endpoint) |
Free function that returns remote_endpoint.hash() ; has to be a free function named hash_value for boost.hash to pick it up. More... | |
Represents the remote endpoint of a Flow-protocol connection; identifies the UDP endpoint of the remote Node and the logical Flow-protocol port within that Node.
In particular when performing Node::connect(), one must supply a Remote_endpoint. Constuct this via direct member initialization.
When performing Node::listen(), on the other hand, a Remote_endpoint is unnecessary; the UDP endpoint has already been supplied when starting the overall Node, so only the Flow-protocol port number is needed by Node::listen().
Since the components of a Remote_endpoint should be freely readable and modifiable, I forewent the usual accessors/mutators and simply made those components public data members.
net_flow
, so it belongs there, not here on this humble struct
.)struct
members (see http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197). The same would apply to a potentially great number of other non-virtual
methods (including operators) of other struct
s and classes that could be implemented without friend
, so really pursuing this approach could touch quite a few things. I won't repeat Meyers' reasoning; see the link. I find the reasoning mostly compelling. To summarize his final suggestions: An operation on a type should be a free function if ALL of the following holds: it is not virtual
by nature; AND: it is <<
or >>
, and/or its would-be left operand would require type conversions, and/or it can be implemented entirely via the type's publicly exposed interface. We already follow the advice for <<
and >>
(if only because we apply it to stream ops, and for that it just makes sense, <<
especially, since the stream is the left-most operand there, so it has to be a free function in that case – and thus also for >>
for consistency). The type conversion is not a common thing for this library; so that leaves non-virtual
operations (which is most of them) that can be implemented via public APIs only (which is probaby common for struct
s like Remote_endpoint, though we generally try not to have lots of struct
methods in the first place... usually). Before rushing headlong into this project, consider a few more things, though. 1, Doxygen wouldn't pick up the relation between a non-friend free function dealing with struct
or class C
and C
itself; so verbosity/error-proneness would increase by having to add a Doxygen relatesalso
special command to each free function; otherwise documentation becomes less readable (and there's no way to enforce this by having Doxygen fail without this being done, somehow). 2, in the C
-returning-static-member-of-C
pattern, usually in our code it would call a private C
constructor, meaning it would require friend
to make it a free function, meaning it breaks Meyers' own rule and thus should be left a member. 3, Meyers tends to place very little value on brevity as its own virtue. If you find that following the above rule in some case seems to be significantly increasing code complexity/size, maybe it's best to leave it alone. (I am thinking of Low_lvl_packet and its sub-types like Ack_packet: they are struct
s but not typical ones, with complex APIs; making those APIs free function when non-virtual
sounds like a rather hairy change that "feels" like it would reduce simplicity and may increase size, at least due to all the necessary 'splaining in the comments.) All that said, this is perhaps worth pursuing (in the pursuit of stylistic perfection) – but surgically and first-do-no-harm-edly. Oh, also, constructors don't count for this and should continue to remain constructors and not some free functions stuff (should be obvious why, but just in case you get any ideas...).friend
). In fact, hash_value()
and Remote_endpoint::hash() are such a pair. Assuming one does not forget Doxygen's relatesalso
command, it would be easy and concise to just get rid of the member and simply move its implementation directly into the free function. After all, people are meant to use the free function anyway, so why the middle-man method? In this example, hash_value()
would directly compute the hash, and Remote_endpoint::hash() would not exist; but the former would include a Doxygen relatesalso Remote_endpoint
command to ensure properly linked generated documentation. Definition at line 92 of file endpoint.hpp.
size_t flow::net_flow::Remote_endpoint::hash | ( | ) | const |
Hash value of this Remote_endpoint for unordered_*<>
.
Definition at line 24 of file endpoint.cpp.
References m_flow_port, and m_udp_endpoint.
Referenced by hash_value().
|
related |
Free function that returns remote_endpoint.hash()
; has to be a free function named hash_value
for boost.hash to pick it up.
remote_endpoint | Object to hash. |
remote_endpoint.hash()
. Definition at line 70 of file endpoint.cpp.
References hash().
|
related |
Prints string representation of the given Remote_endpoint to the given ostream
.
os | Stream to which to write. |
endpoint | Endpoint to serialize. |
os
. Definition at line 65 of file endpoint.cpp.
References m_flow_port, and m_udp_endpoint.
|
related |
Whether lhs
is equal to rhs
.
lhs | Object to compare. |
rhs | Object to compare. |
Definition at line 60 of file endpoint.cpp.
References m_flow_port, and m_udp_endpoint.
flow_port_t flow::net_flow::Remote_endpoint::m_flow_port = 0 |
The logical Flow port within the Node for the particular connection identified by this endpoint.
Definition at line 99 of file endpoint.hpp.
Referenced by hash(), operator<<(), and operator==().
util::Udp_endpoint flow::net_flow::Remote_endpoint::m_udp_endpoint |
UDP address (IP address/UDP port) where the Node identified by this endpoint bound its low-level UDP socket.
Definition at line 97 of file endpoint.hpp.
Referenced by flow::net_flow::Node::connect_worker(), hash(), operator<<(), and operator==().