/** \mainpage The SENF Socket Library
- The Socket library provides a high level and object oriented
- abstraction of the BSD socket API. The abstraction is based on
- several concepts:
-
- \li The basic visible interface is a \link handle_group handle
- object \endlink
- \li The socket interface relies on a \link policy_group policy
- framework \endlink to configure it's functionality
- \li The rest of the socket API is accessible using a classic
- inheritance hierarchy of \link protocol_group protocol classes
- \endlink
-
- The handle/body architecture provides automatic reference counted
- management of socket instances, the policy framework provides
- highly efficient access to the most important socket functions
- (like reading and writing) and the inheritance hierarchy provides
- convenient access to the multitude of special and protocol
- dependent options.
-
- \see \ref usage \n
+ The Socket library provides a high level and object oriented abstraction of the BSD socket
+ API. The abstraction is based on several concepts:
+
+ \li The basic visible interface is a \link handle_group handle object \endlink
+ \li The socket interface relies on a \link policy_group policy framework \endlink to configure
+ it's functionality
+ \li The rest of the socket API is accessible using a classic inheritance hierarchy of \link
+ protocol_group protocol classes \endlink
+
+ The handle/body architecture provides automatic reference counted management of socket
+ instances, the policy framework provides highly efficient access to the most important socket
+ functions (like reading and writing) and the inheritance hierarchy provides convenient access to
+ the multitude of special and protocol dependent options.
+
+ \see \ref structure \n
+ \ref usage \n
\ref handle_group \n
\ref policy_group \n
\ref protocol_group \n
\ref implementation
*/
+/** \page structure Overview of the Socket Library Structure
+
+ \image html Handle.png
+
+ This diagram tries to give a structural overview of the Socket Library, it does \e not directly
+ show, how the library is implemented. This will be explained later.
+
+ The outside interface to the library is a Handle object. This is the only object, the library
+ user directly interacts with. Every handle references some socket. This is like the ordinary
+ POSIX API: the file descriptor (also called file handle, an integer number) references a socket
+ structure which lives in kernel space. In this library, the Handle object (which is not a simple
+ integer any more but an object) references the Socket (which is part of the
+ implementation). Several handles may reference the same Socket. In contrast to the kernel API,
+ the library employs reference counting to release a socket when the last Handle to it goes out
+ of scope.
+
+ The behavior of a Socket is defined by it's Protocol. It is divided into two parts: the
+ <em>policy interface</em> and the <em>protocol interface</em>. Together they provide the
+ complete API for a specific type of Socket as defined by the Protocol. The <em>policy
+ interface</em> provides highly efficient access to the most frequently used operations whereas
+ the <em>protocol interface</em> completes the interface by providing a complete set of all
+ protocol specific operations not found in the policy interface. This structure allows us to
+ combine the benefits of two design methodologies: The policy interface utilizes a policy based
+ design technique and is highly efficient albeit more complex to implement, whereas the protocol
+ interface is based on a more common inheritance architecture which is not as optimized for
+ performance but much simpler to implement. We reduce the complexity of the implementation by
+ reducing the policy interface to a minimal sensible subset of the complete API.
+
+ \section over_policy The Policy Interface
+
+ The policy of a Socket consists of several parts, called <em>policy axis</em>. Each axis
+ corresponds to one specific interface aspect of the Socket. The exact meaning of the policy axis
+ are defined elsewhere (see \ref policy_group). The Protocol will always provide a complete set
+ of <em>policy classes</em>, one for each axis.
+
+ This <em>complete socket policy</em> defines the policy interface of the protocol. This
+ interface is carried over into the Handle. The socket policy as defined in the Handle however
+ may be <em>incomplete</em>. This mans, that the \e accessible interface of the Socket depends on
+ the type of Handle used. The inherent interface does not change but the view of this interface
+ does if the Handle does not provide the \e complete policy interface. This feature is very
+ important. It allows to define generic Handle types. A generic Handle with an incompletely
+ defined policy can point to an arbitrary Socket as long as all those policy axis which \e are
+ defined match those defined in that Socket's protocol. Using such a generic handle decouples the
+ implementation parts using this handle from the other socket aspects (e.g. you may define a
+ generic socket handle for TCP based communication leaving the addressingPolicy undefined which
+ makes your code independent of the type of addressing, IPv4 or IPv6).
+
+ \section over_protocol The Protocol Interface
+
+ The protocol interface is provided by a set of <em>protocol facets</em>. Each facet provides a
+ part of the interface. Whereas the policy interface is strictly defined (the number and type of
+ policy axis is fixed and also the possible members provided by the policy interface is fixed),
+ the protocol interface is much more flexible. Any member needed to provide a complete API for
+ the specific protocol may be defined, the number and type of facets combined to provide the
+ complete interface is up to the Protocol implementor. This flexibility is necessary to provide a
+ complete API for every possible protocol.
+
+ However this flexibility comes at a cost: To access the protocol interface the user must know
+ the exact protocol of the socket. With other words, the protocol is only accessible if the
+ handle you use is a protocol specific handle. A protocol specific Handle differs from a generic
+ Handle in two ways: It always \e must have a complete policy and it has an additional reference
+ to the protocol type of the socket. This reference gives access to the complete policy
+ interface.
+
+ \section over_impl Implementation of the Socket Libarary Structure
+
+ In the Implementation, the socket policy is identified by an instance of the senf::SocketPolicy
+ template. The Socket representation is internally represented in a senf::SocketBody which is not
+ outside visible. The Handle is provided by a hierarchy of handle templates. Each Handle template
+ uses template arguments for the policy and/or protocol as needed (see \ref handle_group).
+
+ The protocol interface is implemented using inheritance: The Protocol class inherits from each
+ protocol facet using multiple (virtual public) inheritance. The Protocol class therefore
+ provides the complete protocol API in a unified (see \ref protocol_group).
+
+ The Handle references the policy and the protocol only via it's template argument, the
+ information is part of the type. This information is not available as a data member in the
+ Handle object.
+ */
+
/** \page usage Using the Socket Library
- Whenever you use the socket library, what you will be dealing with
- are FileHandle derived instances. The socket library relies
- on reference counting to automatically manage the underlying
- socket representation. This frees you of having to manage the
- socket lifetime explicitly.
+ Whenever you use the socket library, what you will be dealing with are FileHandle derived
+ instances. The socket library relies on reference counting to automatically manage the
+ underlying socket representation. This frees you of having to manage the socket lifetime
+ explicitly.
\section usage_create Creating a Socket Handle
- To create a new socket handle (opening a socket), you will need to
- use ProtocolClientSocketHandle or
- ProtocolServerSocketHandle. You will probably not use these
- templates as is but use proper typedefs (for example
- TCPv4ClientSocketHandle or PacketSocketHandle). The
- documentation for these socket handles are found in the protocol
- class (for example TCPv4SocketProtocol or
- PacketProtocol).
+ To create a new socket handle (opening a socket), you will need to use
+ ProtocolClientSocketHandle or ProtocolServerSocketHandle. You will probably not use these
+ templates as is but use proper typedefs (for example TCPv4ClientSocketHandle or
+ PacketSocketHandle). The documentation for these socket handles are found in the protocol class
+ (for example TCPv4SocketProtocol or PacketProtocol).
\section usage_reusable Writing Reusable Components
- To make your code more flexible, you should not pass around your
- socket in this form. Most of your code will be using only a small
- subset of the ProtocolClientSocketHandle or
- ProtocolServerSocketHandle API.
+ To make your code more flexible, you should not pass around your socket in this form. Most of
+ your code will be using only a small subset of the ProtocolClientSocketHandle or
+ ProtocolServerSocketHandle API.
- If instead of using the
- fully specified handle type you use a more incomplete type, you
- allow your code to be used with all sockets which fulfill the
- minimal requirements of your code. These types are based on the
- ClientSocketHandle and ServerSocketHandle templates which implement
- the policy interface without providing the concrete protocol interface.
- To use those templates you may define a special reduced policy or handle for
- your code. By giving only an incomplete policy you thereby reduce the
- interface to that required by your module:
+ If instead of using the fully specified handle type you use a more incomplete type, you allow
+ your code to be used with all sockets which fulfill the minimal requirements of your code. These
+ types are based on the ClientSocketHandle and ServerSocketHandle templates which implement the
+ policy interface without providing the concrete protocol interface. To use those templates you
+ may define a special reduced policy or handle for your code. By giving only an incomplete policy
+ you thereby reduce the interface to that required by your module:
\code
typedef ClientSocketHandle<
\endcode
- This defines \c MyReadableHandle as a ClientSocketHandle
- which will have only read functionality. Your code expects a
- stream interface (in contrast to a packet or datagram based
- interface). You will not have \c write or \c readfrom members. \c
- write will be disabled since the WritePolicy is unknown, \c
- readfrom will be disabled since a socket with the
- ConnectedCommunicationPolicy does not have a \c readfrom
- member.
+ This defines \c MyReadableHandle as a ClientSocketHandle which will have only read
+ functionality. Your code expects a stream interface (in contrast to a packet or datagram based
+ interface). You will not have \c write or \c readfrom members. \c write will be disabled since
+ the WritePolicy is unknown, \c readfrom will be disabled since a socket with the
+ ConnectedCommunicationPolicy does not have a \c readfrom member.
*/
/** \page extend Extending the Library
- There are two layers, on which the socket library can be
- extended: On the protocol layer and on the policy layer. Extending
- the protocol layer is quite simple and works as long as the
- desired protocol does use the same BSD API used by the standard
- internet protocols as implemented in the standard policies
- (i.e. it uses ordinary read() and write() or rcvfrom() or sendto()
- calls and so on).
+ There are two layers, on which the socket library can be extended: On the protocol layer and on
+ the policy layer. Extending the protocol layer is quite simple and works as long as the desired
+ protocol does use the same BSD API used by the standard internet protocols as implemented in the
+ standard policies (i.e. it uses ordinary read() and write() or rcvfrom() or sendto() calls and
+ so on).
- If however the implementation of a policy feature needs to be
- changed, a new policy class has to be written. This also is not
- very complicated however the integration is more complex.
+ If however the implementation of a policy feature needs to be changed, a new policy class has to
+ be written. This also is not very complicated however the integration is more complex.
\section extend_protocol Writing a new protocol class
- Most protocols can be implemented by just implementing a new
- protocol class. The protocol class must be derived from
- ConcreteSocketProtocol and takes the socket policy (as
- created by MakeSocketPolicy) as a template argument. See the
- documentation of this class for the interface.
-
- \attention You may want to use multiple inheritance as it is used
- in the implementation of the standard protocols (See \ref
- protocol_group). You must however be extra careful to ensure, that
- every class ultimately has SocketPolicy as a public \e
- virtual base.
-
- After the protocol class has been defined, you will probably want to
- provide typedefs for the new protocol sockets. If the new protocol
- is connection oriented, this will be like
+ Most protocols can be implemented by just implementing a new protocol class. The protocol class
+ must be derived from ConcreteSocketProtocol and takes the socket policy (as created by
+ MakeSocketPolicy) as a template argument. See the documentation of this class for the interface.
+
+ \attention You may want to use multiple inheritance as it is used in the implementation of the
+ standard protocols (See \ref protocol_group). You must however be extra careful to ensure, that
+ every class ultimately has SocketPolicy as a public \e virtual base.
+
+ After the protocol class has been defined, you will probably want to provide typedefs for the
+ new protocol sockets. If the new protocol is connection oriented, this will be like
\code
typedef ProtocolClientSocketHandle<MyProtocolClass> MyProtocolClientSocketHandle;
typedef ProtocolServerSocketHandle<MyProtocolClass> MyProtocolServerSocketHandle;
\section extend_policy Extending the policy framework
- If you have to extend the policy framework, you will need to be
- aware of some important limitations of the socket library:
-
- \li When you define a new policy for some axis, this new policy
- <em>must not</em> be derived from one of the existing concrete
- policy classes (except of course the respective policy axis
- base class). This is important since the policy type is \e not
- polymorphic. The policy to be used is selected by the compiler
- using the \e static type, which is exactly what is desired,
- since this allows calls to be efficiently inlined.
-
- \li Therefore, extending the policy framework will make the new
- socket probably \e incompatible with generic code which relies
- on the policy axis which is extended. Example: If you write a
- new write policy because your protocol does not use ordinary
- write() system calls but some protocol specific API, Then any
- generic function relying on WritablePolicy will \e not
- work with the new socket, since the socket does \e not have
- this policy, it has some other kind of write policy.
-
- Therefore you need to be careful of what you are doing. The first
- step is to find out, which policy you will have to implement. For
- this, find the ClientSocketHandle and/or
- ServerSocketHandle members you want to change (see \ref
- ClientSocketHandle and \ref ServerSocketHandle). Not
- all policy axis directly contribute to the SocketHandle
- interface. However, some policy members additionally depend on
- other policy axis (example: AddressingPolicy::connect is only
- defined if the communication policy is
+ If you have to extend the policy framework, you will need to be aware of some important
+ limitations of the socket library:
+
+ \li When you define a new policy for some axis, this new policy <em>must not</em> be derived
+ from one of the existing concrete policy classes (except of course the respective policy
+ axis base class). This is important since the policy type is \e not polymorphic. The policy
+ to be used is selected by the compiler using the \e static type, which is exactly what is
+ desired, since this allows calls to be efficiently inlined.
+
+ \li Therefore, extending the policy framework will make the new socket probably \e incompatible
+ with generic code which relies on the policy axis which is extended. Example: If you write a
+ new write policy because your protocol does not use ordinary write() system calls but some
+ protocol specific API, Then any generic function relying on WritablePolicy will \e not work
+ with the new socket, since the socket does \e not have this policy, it has some other kind
+ of write policy.
+
+ Therefore you need to be careful of what you are doing. The first step is to find out, which
+ policy you will have to implement. For this, find the ClientSocketHandle and/or
+ ServerSocketHandle members you want to change (see \ref ClientSocketHandle and \ref
+ ServerSocketHandle). Not all policy axis directly contribute to the SocketHandle
+ interface. However, some policy members additionally depend on other policy axis (example:
+ AddressingPolicy::connect is only defined if the communication policy is
ConnectedCommunication).
\see policy_group
<table class="glossary">
- <tr><td>policy</td> <td>collection of policy classes, one for each
- policy axis, instantiation of the SocketPolicy template</td></tr>
+ <tr><td>policy</td> <td>collection of policy classes, one for each policy axis, instantiation of
+ the SocketPolicy template</td></tr>
- <tr><td>policy axis</td> <td>one aspect defined in the socket
- policy, typedef and member of the SocketPolicy template</td></tr>
+ <tr><td>policy axis</td> <td>one aspect defined in the socket policy, typedef and member of the
+ SocketPolicy template</td></tr>
- <tr><td>policy class</td> <td>implementation of a single policy
- axis, class derived from the axis base class</td></tr>
+ <tr><td>policy class</td> <td>implementation of a single policy axis, class derived from the
+ axis base class</td></tr>
- <tr><td>complete policy</td> <td>socket policy where each
- axis is specified completely</td></tr>
+ <tr><td>complete policy</td> <td>socket policy where each axis is specified completely</td></tr>
- <tr><td>incomplete policy</td> <td>socket policy, where at
- least one axis is not fully specified</td></tr>
+ <tr><td>incomplete policy</td> <td>socket policy, where at least one axis is not fully
+ specified</td></tr>
- <tr><td>protocol class</td> <td>definition of a protocol as a
- class, class inheriting from ConcreteSocketProtocol.</td></tr>
+ <tr><td>protocol class</td> <td>definition of a protocol as a class, class inheriting from
+ ConcreteSocketProtocol.</td></tr>
- <tr><td>protocol facet</td> <td>a class providing some subset of
- the protocol interface, class derived from SocketProtocol but not
- from ConcreteSocketProtocol</td></tr>
+ <tr><td>protocol facet</td> <td>a class providing some subset of the protocol interface, class
+ derived from SocketProtocol but not from ConcreteSocketProtocol</td></tr>
<tr><td>policy interface</td> <td>interface directly provided by
- ClientSocketHandle/ServerSocketHandle and defined through the
- policy</td>
+ ClientSocketHandle/ServerSocketHandle and defined through the policy</td>
- <tr><td>protocol interface</td> <td>interface provided by the
- protocol class and accessible via the
- ProtocolClientSocketHandle::protocol()/ProtocolServerSocketHandle::protocol()
+ <tr><td>protocol interface</td> <td>interface provided by the protocol class and accessible via
+ the ProtocolClientSocketHandle::protocol()/ProtocolServerSocketHandle::protocol()
member</td></tr>
</table>
\section impl_notes Arbitrary Implementation Notes
- \li The implementation tries to isolate the library user as much
- as possible from the system header files since those headers
- define a lot of define symbols and introduce a host of symbols
- into the global namespace. This is, why some classes define
- their own \c enum types to replace system defined define
- constants. This also precludes inlining some functionality.
-
- \li To reduce overhead, template functions/members which are
- more than one-liners are often implemented in terms of a
- non-template function/member. This is also used to further the
- isolation from system headers as defined above (template code
- must always be included into every compilation unit together
- with all headers need for the implementation).
+ \li The implementation tries to isolate the library user as much as possible from the system
+ header files since those headers define a lot of define symbols and introduce a host of
+ symbols into the global namespace. This is, why some classes define their own \c enum types
+ to replace system defined define constants. This also precludes inlining some functionality.
+
+ \li To reduce overhead, template functions/members which are more than one-liners are often
+ implemented in terms of a non-template function/member. This is also used to further the
+ isolation from system headers as defined above (template code must always be included into
+ every compilation unit together with all headers need for the implementation).
*/
}
/** \file
\brief Policy Framework public header
- \todo We should probably remove BufferingPolicy from the
- interface, it does not make much sense (how did I come to
- include it ??)
-
- \todo Do we want to support separate read and write policies. This
- allows to treat pipes within this framework however, is this
- worth the effort?
-
- \idea Creating a new Socket will create 4 (!) new instances (The
- handle, the body, the policy and the protocol) of which 3
- (argh) (body, policy and protocol) live on the heap. This is
- expensive. We should convert all the policy classes to
- singletons and assign the same instance to all socket bodies
- with the same policy. This would reduce the number of heap
+ \todo We should probably remove BufferingPolicy from the interface, it does not make much sense
+ (how did I come to include it ??)
+
+ \todo Do we want to support separate read and write policies. This allows to treat pipes within
+ this framework however, is this worth the effort?
+
+ \idea Creating a new Socket will create 4 (!) new instances (The handle, the body, the policy
+ and the protocol) of which 3 (argh) (body, policy and protocol) live on the heap. This is
+ expensive. We should convert all the policy classes to singletons and assign the same
+ instance to all socket bodies with the same policy. This would reduce the number of heap
allocations per socket handle to two.
*/
\section policy_group_introduction Introduction to the Policy Framework
- The policy framework conceptually implements a list of parallel
- inheritance hierarchies each covering a specific interface aspect
- of the socket handle. The socket handle itself only provides
- minimal functionality. All further functionality is relayed to a
- policy class, or more precisely, to a group of policy classes, one
- for each policy axis. The policy axis are
+ The policy framework conceptually implements a list of parallel inheritance hierarchies each
+ covering a specific interface aspect of the socket handle. The socket handle itself only
+ provides minimal functionality. All further functionality is relayed to a policy class, or more
+ precisely, to a group of policy classes, one for each policy axis. The policy axis are
- <dl>
- <dt><em>addressingPolicy</em></dt>
- <dd>configures, whether a socket is
- addressable and if so, configures the address type</dd>
+ <dl><dt><em>addressingPolicy</em></dt><dd>configures, whether a socket is addressable and if
+ so, configures the address type</dd>
- <dt><em>framingPolicy</em></dt>
- <dd>configures the type of framing the socket provides: either no
- framing providing a simple i/o stream or packet framing</dd>
+ <dt><em>framingPolicy</em></dt> <dd>configures the type of framing the socket provides: either
+ no framing providing a simple i/o stream or packet framing</dd>
- <dt><em>communicationPolicy</em></dt>
- <dd>configures,if and how the communication partner is
+ <dt><em>communicationPolicy</em></dt><dd>configures,if and how the communication partner is
selected</dd>
- <dt><em>readPolicy</em></dt>
- <dd>configures the readability of the socket</dd>
+ <dt><em>readPolicy</em></dt><dd>configures the readability of the socket</dd>
- <dt><em>writePolicy</em></dt>
- <dd>configures the writability of the socket</dd>
+ <dt><em>writePolicy</em></dt><dd>configures the writability of the socket</dd>
- <dt><em>bufferingPolicy</em></dt>
- <dd>configures, if and how buffering is configured for a socket</dd>
- </dl>
+ <dt><em>bufferingPolicy</em></dt><dd>configures, if and how buffering is configured for a
+ socket</dd> </dl>
- In a concrete policy, each of these policy axis is assigned a value,
- the policy value. This value is identified by a class type. For example,
- possible values for <em>framingPolicy</em> are <tt>DatagramFramingPolicy</tt>
- or <tt>StreamFramingPolicy</tt> which are classes derived from the axis
- base class <tt>FramingPolicyBase</tt>. This base class doubles as
- <tt>UnspecifiedFramingPolicy</tt> (which is just a typedef alias).
- If a policy axis is assigned this Unspecified type, the axis is left
- unspecified, the policy will be incomplete.
+ The template senf::SocketPolicy combines these policy axis to form a concrete socket policy. In
+ a concrete policy, each of these policy axis is assigned a value, the policy value. This value
+ is identified by a class type, a policy class. E.g. possible values for <em>framingPolicy</em>
+ are <tt>DatagramFramingPolicy</tt> or <tt>StreamFramingPolicy</tt> which are classes derived
+ from the axis base class <tt>FramingPolicyBase</tt>. This base class also doubles as
+ <tt>UnspecifiedFramingPolicy</tt> (which is just a typedef alias). If a policy axis is assigned
+ this Unspecified type, the axis is left unspecified, the concrete policy will be incomplete.
- The senf::SocketPolicy tempalte defines the complete policy of a socket. It
- combines a set of policy classes, one for each policy
- axis as described above. Together, they define the behavior of a socket handle. The
- socket handle instances do not implement any socket functionality
- themselves instead defering the implementation to the policy
- classes. The SocketHandle interface is therefore \e not
- implemented using virtual members, all important socket functions
- can be inlined by the compiler to create highly efficient code.
-
- A SocketPolicy can be incomplete. In this case it does \e not
- completely specify the socket interface, it leaves some aspects
- open. A SocketHandle based on such a policy will have a reduced
- interface: It will only support those members for wich the
- corresponding policies are defined.
-
- Two SocketHandle's with different policies can be \e
- compatible. If they are, the more derived SocketHandle can be
- converted (assigned to) the more basic SocketHandle.
-
- \doc Example (concrete policy, incomplete policy, compatibility/assignment)
+ The senf::SocketPolicy template defines the behavior of a socket handle. The socket handle
+ instances do not implement any socket functionality themselves instead defering the
+ implementation to the policy classes. The SocketHandle interface is therefore \e not implemented
+ using virtual members, all important socket functions can be inlined by the compiler to create
+ highly efficient code.
+
+ A senf::SocketPolicy instance can be incomplete. In this case it does \e not completely specify
+ the socket interface, it leaves some aspects open by assigning the Unspecified value to one or
+ more of the policy axis. A senf::SocketHandle based on such a policy will have a reduced
+ interface: It will only support those members for wich the corresponding policies are defined.
+
+ To build a senf::SocketPolicy instance the senf::MakeSocketPolicy helper is provided. This
+ helper template takes any number (it is really limited to 6 Arguments but more arguments don't
+ make sense) of policy classes as it's argument. The MakeSocketPolicy helper will take the
+ arguments in the order they are specified and for each argument will check to which axis the
+ policy class belongs (by checking the base classes of that class) and assign it to the correct
+ policy axis in the senf::SocketPolicy template. If any policy axis are not specified, they are
+ defaulted to their corresponding Unspecified value. This helper frees you to specify the policy
+ classes in any order. An additional feature is, that you may specify a complete policy as a
+ first argument. This policy will then be used to provide default values for unspecified axis.
+
+ Two senf::SocketHandle's with different policies can be \e compatible. If they are, the more
+ specific SocketHandle can be converted (assigned to) the more basic SocketHandle. A SocketHandle
+ is more specific then another SocketHandle if the policy of the former is more specific then
+ that of the latter which means, that for each policy axis separately, the value of that axis of
+ the more specific policy is derived from or the same as the value of that axis in the more basic
+ policy. This is like converting a derived class pointer to a base class pointer, only it happens
+ separately but at the same time for each policy axis:
+
+ \code
+ // This defines an incomplete policy where addressingPolicy, writePolicy and bufferingPolicy
+ // are unspecified
+ typedef senf::MakeSocketPolicy<
+ senf::StreamFramingPolicy,
+ senf::ConnectedCommunicationPolicy,
+ senf::ReadablePolicy
+ >::policy MyReadableSocketPolicy
+
+ typedef senf::ClientSocketHandle<MyReadableSocketPolicy> MyReadableHandle;
+
+ // TCPv4ClientSocketHandle is a socket handle with the policy equivalent to
+ // senf::MakeSocketPolicy<
+ // INet4AddressingPolicy,
+ // StreamFramingPolicy,
+ // ConnectedCommunicationPolicy,
+ // ReadablePolicy,
+ // WritablePolicy,
+ // SocketBufferingPolicy>::policy
+ senf::TCPv4ClientSocketHandle tcpHandle (...);
+
+ MyReadableHandle myHandle (tcpHandle); // Conversion to more basic socket handle
+ \endcode
\section policy_group_details The Policy Framework Classes
- \doc Policy should be Axis here. Make clear, that this information is only
- needed when extending the library.
+ In the following discussion, deeper insight into C++ and especially the concepts of template
+ meta-programming are needed. Hoewever, this information is only needed if you want to write new
+ policy classes or want to use the policy framework explicitly for your own involved
+ optimizations ... or if you are just plain curious :-)
In the following discussion we will use the following conventions:
- \li \e Policy is one or \c AddressingPolicy, \c FramingPolicy, \c
- CommunicationPolicy, \c ReadPolicy, \c WritePolicy or \c
- BufferingPolicy
- \li \e socketPolicy is any socket policy (that is, an
- instantiation of the SocketPolicy template)
- \li \e trait is an any policy class (that is, any class derived
- from one of the axis base classes)
-
- Each axis is comprised of a number of classes and templates (all
- in namespace senf of course):
-
- <dl>
- <dt>\e Policy \c Base (ex: AddressingPolicyBase)</dt>
- <dd>Baseclass of all policies in this axis</dd>
-
- <dt>\c Unspecified \e Policy (ex: \ref UnspecifiedAddressingPolicy)</dt>
- <dd>An alias (typedef) for \e Policy \c Base</dd>
-
- <dt>\e Policy \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)</dt>
- <dd>A template metafunction returning \c boost::true_type, if \e
- trait (any class derived from \e Policy \c Base) is a compatible
- policy value of the given \e socketPolicy</dd>
-
- <dt>\c If \e Policy \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)</dt>
- <dd>This is a combination of \e Policy \c Is and \c boost::enable_if</dd>
-
- <dt>\c If \e Policy \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)</dt>
- <dd>The inverse of above</dd>
- </dl>
-
- These classes form the basis of the policy framework. To bind the
- policy axis together, there are some more classes and templates.
-
- <dl>
- <dt>\c class \c SocketPolicyBase</dt>
- <dd>This class is the base class of the SocketPolicy template. It
- is used to validate, that a class is really a SocketPolicy (by
- checking, that it derives from SocketPolicyBase. This is simpler
- than chacking the template directly).</dd>
-
- <dt>\c template \c SocketPolicy < \e addressingPolicy, \e
- framingPolicy, \e communicationPolicy, \e readPolicy, \e
- writePolicy, \e bufferingPolicy ></dt>
- <dd>This is the central SocketPolicy template. It combines a
- complete set of policy classes, one for each axis.</dd>
-
- <dt>\c template \c MakeSocketPolicy < \e args ></dt>
- <dd>\c MakeSocketPolicy is a template metafunction which
- simplifies building SocketPolicy instantiations. It takes any
- number (ok, up to a maximum of 6) of policy classes as an
- argument (in any order). It will sort these arguments into the
- SocketPolicy template arguments. If for some axis no class is
- specified, it's slot will be filled with \c Unspecified \e
- Policy. Additionally, the first Argument may optionally be ab
- arbitrary SocketPolicy. It will provide default values for
- unspecified axis</dd>
-
- <dt>\c template \c SocketPolicyIsBaseOf < \e base, \e derived ></dt>
- <dd>This template metafunction will check, wether the socket
- policy \e derived is convertible to \e base. This means, that for
- each axis, the corresponding policy class in \e derived must be
- derived or be the same as the one on \e base.</dd>
- </dl>
-
- \implementation All these classes are created automatically. The
- \c SENF_SOCKET_POLICIES makro is a Boost.Preprocessor style
- sequence listing all policy axis. The Boost.Preprocessor library
+ \li \e Axis is one or \c AddressingPolicy, \c FramingPolicy, \c CommunicationPolicy, \c
+ ReadPolicy, \c WritePolicy or \c BufferingPolicy
+ \li \e socketPolicy is any socket policy (that is, an instantiation of the SocketPolicy
+ template)
+ \li \e trait is an any policy class (that is, any class derived from one of the axis base
+ classes)
+
+ Each axis is comprised of a number of classes and templates (all in namespace senf of course):
+
+ <dl><dt>\e Axis \c Base (ex: AddressingPolicyBase)</dt><dd>Baseclass of all policies in this
+ axis</dd>
+
+ <dt>\c Unspecified \e Axis (ex: \ref UnspecifiedAddressingPolicy)</dt> <dd>An alias (typedef)
+ for \e Axis \c Base</dd>
+
+ <dt>\e Axis \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)</dt> <dd>A template
+ metafunction returning \c boost::true_type, if \e trait (any class derived from \e Axis \c
+ Base) is a compatible policy value of the given \e socketPolicy</dd>
+
+ <dt>\c If \e Axis \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)</dt> <dd>This
+ is a combination of \e Axis \c Is and \c boost::enable_if</dd>
+
+ <dt>\c If \e Axis \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)</dt>
+ <dd>The inverse of above</dd> </dl>
+
+ These classes form the basis of the policy framework. To bind the policy axis together, there
+ are some more classes and templates.
+
+ <dl><dt>\c class \c SocketPolicyBase</dt> <dd>This class is the base class of the SocketPolicy
+ template. It is used to validate, that a class is really a SocketPolicy (by checking, that it
+ derives from SocketPolicyBase. This is simpler than chacking the template directly).</dd>
+
+ <dt>\c template \c SocketPolicy < \e addressingPolicy, \e framingPolicy, \e communicationPolicy,
+ \e readPolicy, \e writePolicy, \e bufferingPolicy ></dt> <dd>This is the central SocketPolicy
+ template. It combines a complete set of policy classes, one for each axis.</dd>
+
+ <dt>\c template \c MakeSocketPolicy < \e args ></dt> <dd>\c MakeSocketPolicy is a template
+ metafunction which simplifies building SocketPolicy instantiations. It takes any number (ok, up
+ to a maximum of 6) of policy classes as an argument (in any order). It will sort these arguments
+ into the SocketPolicy template arguments. If for some axis no class is specified, it's slot will
+ be filled with \c Unspecified \e Axis. Additionally, the first Argument may optionally be ab
+ arbitrary SocketPolicy. It will provide default values for unspecified axis</dd>
+
+ <dt>\c template \c SocketPolicyIsBaseOf < \e base, \e derived ></dt> <dd>This template
+ metafunction will check, wether the socket policy \e derived is convertible to \e base. This
+ means, that for each axis, the corresponding policy class in \e derived must be derived or be
+ the same as the one on \e base.</dd> </dl>
+
+ \implementation All these classes are created automatically. The \c SENF_SOCKET_POLICIES makro
+ is a Boost.Preprocessor style sequence listing all policy axis. The Boost.Preprocessor library
is then used to generate the respective classes.
\section policy_implement Implementing Policy Classes
- To define a new policy class, derive from the corresponding base
- class for your policy axies. The only policy axis which might
- possibly need to be extended are the addressing policy
- (AddressingPolicyBase) and the buffering policy
- (BufferingPolicyBase). See the Documentation of these classes for
- more information on which members can be implemented.
-
- All members you define must be static. For any of the policy
- classes, you must only define those members which are supported by
- your implementation. If you leave out a member you automatically
- disable the corresponding functionality in the
- ClientSocketHandle/ServerSocketHandle interface.
-
- The member prototypes given in the base class documentation only
- specify the call signature not the way, the member must be defined
- (FileHandle really is not a FileHandle but an arbitrary
+ To define a new policy class, derive from the corresponding base class for your policy
+ axies. The only policy axis which might possibly need to be extended are the addressing policy
+ (AddressingPolicyBase) and the buffering policy (BufferingPolicyBase). See the Documentation of
+ these classes for more information on which members can be implemented.
+
+ All members you define must be static. For any of the policy classes, you must only define those
+ members which are supported by your implementation. If you leave out a member you automatically
+ disable the corresponding functionality in the ClientSocketHandle/ServerSocketHandle interface.
+
+ The member prototypes given in the base class documentation only specify the call signature not
+ the way, the member must be defined (FileHandle really is not a FileHandle but an arbitrary
SocketHandle).
- If the existence of a member depends on other policies, you should
- use the <code>If</code><i>SomePolicy</i><code>Is</code> and
- <code>If</code><i>SomePolicy</i><code>IsNot</code> templates to
- dynamically enable/disable the member depending on some other
- policy:
+ If the existence of a member depends on other policies, you should use the
+ <code>If</code><i>SomePolicy</i><code>Is</code> and
+ <code>If</code><i>SomePolicy</i><code>IsNot</code> templates to dynamically enable/disable the
+ member depending on some other policy:
\code
struct ExampleAddressingPolicy
};
\endcode
- The \c connect member in this example will only be enabled, it
- the communication policy of the socket handle is
- ConnectedCommunicationPolicy (or a derived type). See <a
- href="http://www.boost.org/libs/utility/enable_if.html">Boost.Enable_If</a>
- for a discussion of the third argument (\c
- senf::ConnectedCommunicationPolicyIs is based on the \c
- boost::enable_if template).
+ The \c connect member in this example will only be enabled, it the communication policy of the
+ socket handle is ConnectedCommunicationPolicy (or a derived type). See <a
+ href="http://www.boost.org/libs/utility/enable_if.html">Boost.Enable_If</a> for a discussion of
+ the third argument (\c senf::ConnectedCommunicationPolicyIs is based on the \c boost::enable_if
+ template).
\see \ref extend_policy \n
<a class="ext" href="http://www.boost.org/libs/utility/enable_if.html">The Boost enable_if utility</a> \n
<a class="ext" href="http://www.boost.org/libs/mpl/doc/index.html">The Boost.MPL library</a> \n
<a class="ext" href="http://www.boost.org/libs/preprocessor/doc/index.html">The Boost.Preprocessor library</a>
- \idea We could combine all the \e Policy \c Is templates into a
- single template. Since the \e trait argument will automatically
- specify the axis to be used, it is not necessary to specify that
- axis in the tempalte functor's name. We could even combine this
- with \c SocketPolicyIsBaseOf.
+ \idea We could combine all the \e Axis \c Is templates into a single template. Since the \e
+ trait argument will automatically specify the axis to be used, it is not necessary to specify
+ that axis in the tempalte functor's name. We could even combine this with \c
+ SocketPolicyIsBaseOf.
*/
/** \defgroup policy_impl_group Policy Implementation classes
/// \addtogroup policy_group
/// @{
- // This may be adapted to change the supported policies (however,
- // ClientSocketHandle and ServerSocketHandle will probably have to
- // be adjusted accordingly)
+ // This may be adapted to change the supported policies (however, ClientSocketHandle and
+ // ServerSocketHandle will probably have to be adjusted accordingly)
/** \brief List all policy axis
/** \brief Check single policy axis
- This template is an example of the \e Policy \c Is family of
+ This template is an example of the \e Axis \c Is family of
tempalte metafunctions. It will check, wether \c Trait is a
valid compatible Policy class of \c SocketPolicy. \c Trait
must be derived from AddressingPolicyBase (respectively \i
/** \brief Enable template overload depending on policy value
- This template is an exmaple of the \c If \e Policy \c Is
+ This template is an exmaple of the \c If \e Axis \c Is
family of templates. It is used like <a class="ext"
href="http://www.boost.org/libs/utility/enable_if.html">Boost.enable_if</a>
to enable a templated overload only, if the AddressingPolicy
- of \e Policy is compatible with \c Trait (that is the
+ of \e Axis is compatible with \c Trait (that is the
AddressingPolicy of \c Policy is derived from \c Trait).
\see policy_group
A SocketPolicy can be complete or incomplete. An incomplete
SocketPolicy will have at least one axis set to \c Undefined
- \e Policy (or a generic derived class which is used to group
+ \e Axis (or a generic derived class which is used to group
some other policies but does not (completely) define the
policy behavior). A complete SocketPolicy will have a
concrete definition of the desired behavior for each policy
SocketPolicy instantiation. It takes any number (that is up to
6) of Policy classes as arguments in any Order. It will create
a SocketPolicy from these policy classes. Any axis not
- specified will be left as \c Unspecified \e Policy.
+ specified will be left as \c Unspecified \e Axis.
\see policy_group
*/