25.5ToandFromaNetwork 405
return (info);
}
#define MEMBER(name, desc)
introspection::member_instance(&self_t::name, #name, desc),
Listing 25.5. The INTROSPECTION macro implementation.
This keeps the namespace of the introspected type (such as UserInfo) clean,
only introducing the
typedef self_t and the member_info() member function.
Access to each member of the structure is done using pointer-to-member syntax.
However, the actual pointer to member does not need to be dereferenced because
template metaprogramming can pick it apart and turn it into an offset-and-
typecast construct, to save run-time CPU cycles.
25.5ToandFromaNetwork
When you receive a piece of data from a network, you need to instantiate the
right data type, based on what the received packet is. Once the data type is dis-
patched, you have to correctly destroy the instance again, freeing up any addi-
tional memory used by members of types such as string or list. The introspection
mechanism of this gem builds this into the
member_access_base type, giving
you the
size() function to let you know how much memory to allocate, and
create() and destroy() functions to manage the lifetime of the structure in-
stance.
Additionally, the gem provides the
PROTOCOL() and PDU() macros to allow
definition of a suite of related data types. Each data type added with the
PDU()
macro is given a small integer ID, which you can use on the network to identify
which kind of packet is being sent. Given the
PROTOCOL instance, you can map a
type to an ID and an ID to a type using the
protocol_t type members code()
(to get the integer code for a type) and
type() (to get the type_info_base for a
code).
On top of this, you can build a type-safe protocol packet dispatcher, where
each dispatcher is selected by the appropriate type. End to end, the networking
API then uses the actual structure type to select which code to prefix the packet
with and serialize the structure to a sequence of bytes using the serialization from
the
INTROSPECTION() macro. It then sends this data to the other end, prefixed by
the size of the packet. The receiving end first decodes the integer of the packet
type and then selects the appropriate unpacker type instance based on the code.