From: g0dil Date: Thu, 1 Mar 2007 10:15:40 +0000 (+0000) Subject: Added Socket Library overview documentation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=e069f918a83434f6f6fe6656013340f2ec2492c4;p=senf.git Added Socket Library overview documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@210 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/Handle.dia b/Socket/Handle.dia new file mode 100644 index 0000000..251f3f1 Binary files /dev/null and b/Socket/Handle.dia differ diff --git a/Socket/Mainpage.dox b/Socket/Mainpage.dox index 8f8f736..76334f6 100644 --- a/Socket/Mainpage.dox +++ b/Socket/Mainpage.dox @@ -2,26 +2,22 @@ namespace senf { /** \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 @@ -29,41 +25,113 @@ namespace senf { \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 + policy interface and the protocol interface. Together they provide the + complete API for a specific type of Socket as defined by the Protocol. The policy + interface provides highly efficient access to the most frequently used operations whereas + the protocol interface 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 policy axis. 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 policy classes, one for each axis. + + This complete socket policy 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 incomplete. 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 protocol facets. 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< @@ -74,49 +142,38 @@ namespace senf { \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 MyProtocolClientSocketHandle; typedef ProtocolServerSocketHandle MyProtocolServerSocketHandle; @@ -124,35 +181,28 @@ namespace senf { \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 - must not 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 must not 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 @@ -162,35 +212,31 @@ namespace senf { - + - + - + - + - + - + - + + ClientSocketHandle/ServerSocketHandle and defined through the policy -
policy collection of policy classes, one for each - policy axis, instantiation of the SocketPolicy template
policy collection of policy classes, one for each policy axis, instantiation of + the SocketPolicy template
policy axis one aspect defined in the socket - policy, typedef and member of the SocketPolicy template
policy axis one aspect defined in the socket policy, typedef and member of the + SocketPolicy template
policy class implementation of a single policy - axis, class derived from the axis base class
policy class implementation of a single policy axis, class derived from the + axis base class
complete policy socket policy where each - axis is specified completely
complete policy socket policy where each axis is specified completely
incomplete policy socket policy, where at - least one axis is not fully specified
incomplete policy socket policy, where at least one axis is not fully + specified
protocol class definition of a protocol as a - class, class inheriting from ConcreteSocketProtocol.
protocol class definition of a protocol as a class, class inheriting from + ConcreteSocketProtocol.
protocol facet a class providing some subset of - the protocol interface, class derived from SocketProtocol but not - from ConcreteSocketProtocol
protocol facet a class providing some subset of the protocol interface, class + derived from SocketProtocol but not from ConcreteSocketProtocol
policy interface interface directly provided by - ClientSocketHandle/ServerSocketHandle and defined through the - policy
protocol interface interface provided by the - protocol class and accessible via the - ProtocolClientSocketHandle::protocol()/ProtocolServerSocketHandle::protocol() +
protocol interface interface provided by the protocol class and accessible via + the ProtocolClientSocketHandle::protocol()/ProtocolServerSocketHandle::protocol() member
@@ -204,19 +250,15 @@ namespace senf { \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). */ } diff --git a/Socket/SConscript b/Socket/SConscript index 5baedce..56ae5d4 100644 --- a/Socket/SConscript +++ b/Socket/SConscript @@ -19,4 +19,5 @@ SENFSCons.Doxygen(env, extra_sources = [ env.Dia2Png('FhHierarchy.dia'), env.Dia2Png('SocketPolicy.dia'), env.Dia2Png('Protocols.dia'), + env.Dia2Png('Handle.dia'), ]) diff --git a/Socket/SocketPolicy.hh b/Socket/SocketPolicy.hh index 6ef2981..507eafd 100644 --- a/Socket/SocketPolicy.hh +++ b/Socket/SocketPolicy.hh @@ -23,20 +23,16 @@ /** \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. */ @@ -46,166 +42,167 @@ \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 -
-
addressingPolicy
-
configures, whether a socket is - addressable and if so, configures the address type
+
addressingPolicy
configures, whether a socket is addressable and if + so, configures the address type
-
framingPolicy
-
configures the type of framing the socket provides: either no - framing providing a simple i/o stream or packet framing
+
framingPolicy
configures the type of framing the socket provides: either + no framing providing a simple i/o stream or packet framing
-
communicationPolicy
-
configures,if and how the communication partner is +
communicationPolicy
configures,if and how the communication partner is selected
-
readPolicy
-
configures the readability of the socket
+
readPolicy
configures the readability of the socket
-
writePolicy
-
configures the writability of the socket
+
writePolicy
configures the writability of the socket
-
bufferingPolicy
-
configures, if and how buffering is configured for a socket
-
+
bufferingPolicy
configures, if and how buffering is configured for a + socket
- 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 framingPolicy are DatagramFramingPolicy - or StreamFramingPolicy which are classes derived from the axis - base class FramingPolicyBase. This base class doubles as - UnspecifiedFramingPolicy (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 framingPolicy + are DatagramFramingPolicy or StreamFramingPolicy which are classes derived + from the axis base class FramingPolicyBase. This base class also doubles as + UnspecifiedFramingPolicy (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 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): - -
-
\e Policy \c Base (ex: AddressingPolicyBase)
-
Baseclass of all policies in this axis
- -
\c Unspecified \e Policy (ex: \ref UnspecifiedAddressingPolicy)
-
An alias (typedef) for \e Policy \c Base
- -
\e Policy \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)
-
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
- -
\c If \e Policy \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)
-
This is a combination of \e Policy \c Is and \c boost::enable_if
- -
\c If \e Policy \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)
-
The inverse of above
-
- - These classes form the basis of the policy framework. To bind the - policy axis together, there are some more classes and templates. - -
-
\c class \c SocketPolicyBase
-
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).
- -
\c template \c SocketPolicy < \e addressingPolicy, \e - framingPolicy, \e communicationPolicy, \e readPolicy, \e - writePolicy, \e bufferingPolicy >
-
This is the central SocketPolicy template. It combines a - complete set of policy classes, one for each axis.
- -
\c template \c MakeSocketPolicy < \e args >
-
\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
- -
\c template \c SocketPolicyIsBaseOf < \e base, \e derived >
-
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.
-
- - \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): + +
\e Axis \c Base (ex: AddressingPolicyBase)
Baseclass of all policies in this + axis
+ +
\c Unspecified \e Axis (ex: \ref UnspecifiedAddressingPolicy)
An alias (typedef) + for \e Axis \c Base
+ +
\e Axis \c Is < \e socketPolicy, \e trait > (ex: AddressingPolicyIs)
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
+ +
\c If \e Axis \c Is < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIs)
This + is a combination of \e Axis \c Is and \c boost::enable_if
+ +
\c If \e Axis \c IsNot < \e socketPolicy, \e trait > (ex: IfAddressingPolicyIsNot)
+
The inverse of above
+ + These classes form the basis of the policy framework. To bind the policy axis together, there + are some more classes and templates. + +
\c class \c SocketPolicyBase
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).
+ +
\c template \c SocketPolicy < \e addressingPolicy, \e framingPolicy, \e communicationPolicy, + \e readPolicy, \e writePolicy, \e bufferingPolicy >
This is the central SocketPolicy + template. It combines a complete set of policy classes, one for each axis.
+ +
\c template \c MakeSocketPolicy < \e args >
\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
+ +
\c template \c SocketPolicyIsBaseOf < \e base, \e derived >
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.
+ + \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 IfSomePolicyIs and - IfSomePolicyIsNot 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 + IfSomePolicyIs and + IfSomePolicyIsNot templates to dynamically enable/disable the + member depending on some other policy: \code struct ExampleAddressingPolicy @@ -217,24 +214,21 @@ }; \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 Boost.Enable_If - 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 Boost.Enable_If for a discussion of + the third argument (\c senf::ConnectedCommunicationPolicyIs is based on the \c boost::enable_if + template). \see \ref extend_policy \n The Boost enable_if utility \n The Boost.MPL library \n The Boost.Preprocessor library - \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 @@ -260,9 +254,8 @@ namespace senf { /// \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 @@ -448,7 +441,7 @@ namespace senf { /** \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 @@ -462,11 +455,11 @@ namespace senf { /** \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 Boost.enable_if 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 @@ -517,7 +510,7 @@ namespace senf { 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 @@ -550,7 +543,7 @@ namespace senf { 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 */ diff --git a/doclib/Doxyfile.global b/doclib/Doxyfile.global index dc70184..b959702 100644 --- a/doclib/Doxyfile.global +++ b/doclib/Doxyfile.global @@ -7,7 +7,8 @@ INPUT_FILTER = "$(TOPDIR)/doclib/filter.pl" ALIASES = "fixme=\xrefitem fixme \"Fix\" \"Fixmes\"" \ "idea=\xrefitem idea \"Idea\" \"Ideas\"" \ - "implementation=\par \"Implementation note:\"" + "implementation=\par \"Implementation note:\"" \ + "doc=\xrefitem doc \"Documentation request\" \"Documentation Requests\"" REPEAT_BRIEF = YES ALWAYS_DETAILED_SEC = YES MULTILINE_CPP_IS_BRIEF = YES