socket representation. This frees you of having to manage the
socket lifetime explicitly.
+ \section socket_hierarchy The FileHandle hierarchy
+
+ \image html FhHierarchy.png
+
+ The senf::FileHandle class is the base of a hierarchy of socket
+ handle classes (realized as templates). These classes provide an
+ interface to the complete socket API. While going down the
+ inheritance hierarchy, the interface will be more and more
+ complete.
+
+ The most complete interface is provided by
+ senf::ProtocolClientSocketHandle and
+ senf::ProtocolServerSocketHandle. The template Arguments specifies
+ the Protocol class of the underlying socket type. These are the
+ \e only classes having public constructors and are therefore the
+ only classes, which may be created by the library user. You will
+ normally use these classes by naming a specific socket typedef
+ (e.g. senf::TCPv4ClientSocketHandle).
+
+ However, to aid writing flexible and generic code, the socket
+ library provides the senf::ClientSocketHandle and
+ senf::ServerSocketHandle class templates. These templates
+ implement a family of closely related classes based on the
+ specification of the socket policy. This policy specification may
+ be \e incomplete (see below). Instances of
+ senf::ClientSocketHandle/senf::ServerSocketHandle can be assigned
+ and converted to different ClientSocketHandle/ServerSocketHandle
+ types as long as the policy specifications are compatible.
+
\attention It is very important, to (almost) always pass the socket
handle <em>by value</em>. The socket handle is a very lightweight
class and designed to be used like an ordinary built-in type. This
is very important in combination with the policy interface.
\section policy_framework The policy framework
+
+ \image html SocketPolicy.png
The policy framework conceptually implements a list of parallel
inheritance hierarchies each covering a specific interface aspect
<dd>configures, if and how buffering is configured for a socket</dd>
</dl>
+ Every Policy value is identified by a class type. The policy types
+ themselves built an inheritance hierarchy for each policy
+ axis. For each policy axis, the root of this tree is the class
+ named '<tt>(axis name)Base</tt>' (e.g. \p FramingPolicyBase or \p
+ CommunicationPolicyBase) which is aliased to '<tt>Unspecified(axis
+ name)</tt>' (e.g. \p UnspecifiedFramingPolicy or \p
+ UnspecifiedCommunicationPolicy).
+
+ The senf::SocketPolicy template combines a set of policy classes,
+ one for each policy axis. Together, they define the behavior of a
+ socket handle. The socket handle instances do net implement any
+ socket functionality themselves, instead defering the
+ implementation to the socket classes. The interface is therefore
+ \e not implemented using virtual members, all important socket
+ functions can be inlined by the compiler to create highly
+ efficient code.
+
+ Two SocketPolicy instances are considered compatible, if all
+ policy axis are compatible. A policy axis is compatible, if one
+ policy class is either the same as the other or derived from
+ it. Two SocketHandle instances can be converted into each other,
+ as long as the SocketPolicies are compatible.
+
+ \section policy_interface The policy interface
+
+ The socket handle classes and templates only implement the most
+ important socket API methods. To access the complete API, the
+ protocol interface is provided. Access to the protocol interface
+ is only possible via senf::ProtocolClientSocketHandle and
+ senf::ProtocolServerSocketHandle which have the necessary \c
+ protocol() member. This member returns a reference to the protocol
+ class instance which contains members covering all the API
+ function snot found in the SocketHandle interface. The protocol
+ interface is specific to the protocol. It's implementation is
+ quite free. Every protocol class will define the complete and
+ specific socket policy of it's socket handle.
*/
/** \page extend Extending the Library
/** \page implementation Implementation notes
- \image html "../../SocketLibrary-classes.png" Class hierarchy
+ \image html SocketLibrary-classes.png
*/
-
\f
// Local Variables:
// mode: c++
SENFSCons.Doxygen(env, extra_sources = [
env.Dia2Png('SocketLibrary-classes.dia'),
+ env.Dia2Png('FhHierarchy.dia'),
+ env.Dia2Png('SocketPolicy.dia'),
])
#define SP_TemplateArgs(x1,x2,n,SomePolicy) BOOST_PP_COMMA_IF(n) class BOOST_PP_CAT(SomePolicy,_)
#define SP_TemplateParams(x1,x2,n,SomePolicy) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(SomePolicy,_)
-template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SATLIB_SOCKET_POLICIES ) >
-prefix_ void senf::SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParams, , SATLIB_SOCKET_POLICIES ) >::
+template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
+prefix_ void senf::SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParams, , SENF_SOCKET_POLICIES ) >::
checkBaseOf(SocketPolicyBase const & other)
{
# define SP_CheckPolicy(x1,x2,SomePolicy) (void) dynamic_cast<SomePolicy const &>(other.BOOST_PP_CAT(the,SomePolicy)());
- BOOST_PP_SEQ_FOR_EACH( SP_CheckPolicy, , SATLIB_SOCKET_POLICIES )
+ BOOST_PP_SEQ_FOR_EACH( SP_CheckPolicy, , SENF_SOCKET_POLICIES )
# undef SP_CheckPolicy
}
// be adjusted accordingly). However, AddressingPolicy MUST always
// be the first Policy member ...
-# define SATLIB_SOCKET_POLICIES \
+# define SENF_SOCKET_POLICIES \
(AddressingPolicy) \
(FramingPolicy) \
(CommunicationPolicy) \
namespace senf {
-# define SATLIB_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SATLIB_SOCKET_POLICIES )
+# define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES )
// This REALLY is bad ... but we just need an Address member in
// AddressingPolicyBase as long as ClientSocketHandle /
{ virtual ~ BOOST_PP_CAT(SomePolicy,Base) () {} }; \
typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
- BOOST_PP_SEQ_FOR_EACH( SP_DeclareBase, , BOOST_PP_SEQ_POP_FRONT( SATLIB_SOCKET_POLICIES ) )
+ BOOST_PP_SEQ_FOR_EACH( SP_DeclareBase, , BOOST_PP_SEQ_POP_FRONT( SENF_SOCKET_POLICIES ) )
# undef SP_DeclareBase
virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \
{ return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
- BOOST_PP_SEQ_FOR_EACH( SP_DeclareTypedef, , SATLIB_SOCKET_POLICIES )
+ BOOST_PP_SEQ_FOR_EACH( SP_DeclareTypedef, , SENF_SOCKET_POLICIES )
# undef SP_DeclareTypedef
};
BOOST_PP_COMMA_IF( n ) \
class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base)
- template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SATLIB_SOCKET_POLICIES ) >
+ template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
struct SocketPolicy
: public SocketPolicyBase
{
BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \
{ return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
- BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SATLIB_SOCKET_POLICIES )
+ BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES )
# undef SP_DeclarePolicyMember
static void checkBaseOf(SocketPolicyBase const & other);
BOOST_PP_COMMA_IF( m ) \
BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy )
-# define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SATLIB_SOCKET_POLICIES_N ) )
+# define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) )
# define BOOST_PP_LOCAL_MACRO(n) \
- SocketPolicy_rv<n> MakeSocketPolicy_merge_(BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SATLIB_SOCKET_POLICIES ),Base)*); \
+ SocketPolicy_rv<n> MakeSocketPolicy_merge_(BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*); \
\
template <class Base, class Policy> \
struct MakeSocketPolicy_merge<Base,Policy,sizeof(SocketPolicy_rv<n>)> \
{ \
typedef SocketPolicy< \
- BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, n, SATLIB_SOCKET_POLICIES ) \
+ BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, n, SENF_SOCKET_POLICIES ) \
> type; \
};
template <class Base>
SocketPolicy_rv<1> SocketPolicy_checkcompat_(
- BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SATLIB_SOCKET_POLICIES ) );
+ BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) );
# undef SP_DeclareArguments
template <class Base>
SocketPolicy_rv<2> SocketPolicy_checkcompat_(
- BOOST_PP_ENUM_PARAMS( SATLIB_SOCKET_POLICIES_N, void * BOOST_PP_INTERCEPT ) );
+ BOOST_PP_ENUM_PARAMS( SENF_SOCKET_POLICIES_N, void * BOOST_PP_INTERCEPT ) );
template <int Size>
struct SocketPolicy_checkcompat
struct SocketPolicy_compatibility
: public SocketPolicy_checkcompat< sizeof(
SocketPolicy_checkcompat_<Base>(
- BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SATLIB_SOCKET_POLICIES ) )) >
+ BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) >
{};
} // namespace impl
- template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SATLIB_SOCKET_POLICIES_N, class T, senf::impl::nil ) >
+ template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N, class T, senf::impl::nil ) >
class MakeSocketPolicy
: public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
- impl::MakeSocketPolicy_impl< T0, boost::mpl::vector< BOOST_PP_ENUM_SHIFTED_PARAMS( SATLIB_SOCKET_POLICIES_N, T ) > >,
+ impl::MakeSocketPolicy_impl< T0, boost::mpl::vector< BOOST_PP_ENUM_SHIFTED_PARAMS( SENF_SOCKET_POLICIES_N, T ) > >,
impl::MakeSocketPolicy_impl< SocketPolicy<>,
- boost::mpl::vector< BOOST_PP_ENUM_PARAMS( SATLIB_SOCKET_POLICIES_N, T ) > > >::type
+ boost::mpl::vector< BOOST_PP_ENUM_PARAMS( SENF_SOCKET_POLICIES_N, T ) > > >::type
{};
template <class BasePolicy, class DerivedPolicy>
: public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait>::value > \
{};
- BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SATLIB_SOCKET_POLICIES )
+ BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES )
# undef SP_DefineConditions
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
-IMAGE_PATH =
+IMAGE_PATH = .
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
def StandardTargets(env):
all = env.Alias('all')
- env.Clean(all, [ '.sconsign', '.sconf_temp', 'config.log', 'ChangeLog.bak', '.clean'
- ] + glob.glob("*~"))
+ env.Clean(all, [ '.sconsign', '.sconf_temp', 'config.log' ])
env.Depends(all, '.')
def GlobalTargets(env):
return objects
-def DoxyGlob(exclude=[]):
- sources = [ f
- for ext in ("cci", "ct", "cti", "h", "hh", "ih", "mmc", "dox")
- for f in glob.glob("*."+ext)
- if f not in exclude ]
- return sources
-
-def Doxygen(env, doxyfile="Doxyfile", extra_sources = []):
+def Doxygen(env, doxyfile = "Doxyfile", extra_sources = []):
docs = env.Doxygen(doxyfile)
# The last target is the (optional) tagfile
if os.path.basename(str(docs[-1])) != '.stamp':