2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
15 \brief Policy Framework internal header
18 #ifndef IH_SENF_Socket_SocketPolicy_
19 #define IH_SENF_Socket_SocketPolicy_ 1
22 #include <boost/preprocessor/seq/for_each.hpp>
23 #include <boost/preprocessor/seq/for_each_i.hpp>
24 #include <boost/preprocessor/seq/size.hpp>
25 #include <boost/preprocessor/seq/pop_front.hpp>
26 #include <boost/preprocessor/punctuation/comma_if.hpp>
27 #include <boost/preprocessor/repetition/enum_params.hpp>
28 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
29 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
30 #include <boost/preprocessor/cat.hpp>
31 #include <boost/preprocessor/seq/elem.hpp>
32 #include <boost/preprocessor/arithmetic/dec.hpp>
33 #include <boost/preprocessor/iteration/local.hpp>
34 #include <boost/preprocessor/control/if.hpp>
35 #include <boost/preprocessor/comparison/equal.hpp>
37 #include <boost/type_traits/is_convertible.hpp>
38 #include <boost/mpl/vector.hpp>
39 #include <boost/mpl/fold.hpp>
40 #include <boost/mpl/if.hpp>
41 #include <boost/mpl/and.hpp>
42 #include <boost/utility/enable_if.hpp>
44 #include <senf/Utils/mpl.hh>
45 #include <senf/Utils/pool_alloc_mixin.hh>
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
50 // Hide this code from doxygen
54 # define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES )
56 # define SP_DeclareAlias(x1,x2,SomePolicy) \
57 typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
59 BOOST_PP_SEQ_FOR_EACH( SP_DeclareAlias, , SENF_SOCKET_POLICIES )
61 # undef SP_DeclareAlias
63 struct SocketPolicyBase
65 virtual ~SocketPolicyBase();
67 # define SP_Declare(x1,x2,SomePolicy) \
68 virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () \
71 BOOST_PP_SEQ_FOR_EACH( SP_Declare, , SENF_SOCKET_POLICIES )
76 # define SP_TemplateArgs(x1,x2,n,SomePolicy) \
77 BOOST_PP_COMMA_IF( n ) \
78 class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base)
79 # define SP_TemplateParms(x1,x2,n,SomePolicy) \
80 BOOST_PP_COMMA_IF( n ) BOOST_PP_CAT(SomePolicy,_)
82 template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
84 : public SocketPolicyBase,
85 public senf::pool_alloc_mixin<
86 SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParms, , SENF_SOCKET_POLICIES ) > >
88 # define SP_DeclarePolicyMember(x1,x2,SomePolicy) \
89 typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy; \
90 SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); \
91 BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \
92 { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
94 BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES )
95 # undef SP_DeclarePolicyMember
97 static void checkBaseOf(SocketPolicyBase const & other);
100 # undef SP_TemplateArgs
101 # undef SP_TemplateParms
105 template <class Base, class Policy, int _>
106 struct MakeSocketPolicy_merge
109 # define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy) \
110 BOOST_PP_COMMA_IF( m ) \
111 BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy )
113 # define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) )
114 # define BOOST_PP_LOCAL_MACRO(n) \
115 senf::mpl::rv<n> MakeSocketPolicy_merge_( \
116 BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*); \
118 template <class Base, class Policy> \
119 struct MakeSocketPolicy_merge<Base,Policy,n> \
121 typedef SocketPolicy< \
122 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, \
124 SENF_SOCKET_POLICIES ) \
128 # include BOOST_PP_LOCAL_ITERATE()
130 # undef SP_DeclareMakeSocketPolicy_merge_member
132 struct MakeSocketPolicy_fold
134 template <class Base, class Policy>
136 : MakeSocketPolicy_merge<Base,
138 SENF_MPL_RV(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
141 template <class Base>
142 struct apply<Base,mpl::nil>
148 template <class Base, class Vector>
149 struct MakeSocketPolicy_impl
151 typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy;
154 # define SP_DeclareArguments(x1,x2,n,SomePolicy) \
155 BOOST_PP_COMMA_IF( n ) \
156 typename Base::SomePolicy *
158 template <class Base>
159 senf::mpl::rv<1> SocketPolicy_checkcompat_(
160 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) );
162 # undef SP_DeclareArguments
164 template <class Base>
165 senf::mpl::rv<2> SocketPolicy_checkcompat_( ... );
168 struct SocketPolicy_checkcompat
169 : public boost::false_type
173 struct SocketPolicy_checkcompat<1>
174 : public boost::true_type
178 # define SP_DeclareArguments(x1,x2,n,SomePolicy) \
179 BOOST_PP_COMMA_IF( n ) \
180 static_cast<typename Derived::SomePolicy *>(0)
182 template <class Base, class Derived>
183 struct SocketPolicy_compatibility
184 : public SocketPolicy_checkcompat< SENF_MPL_RV(
185 SocketPolicy_checkcompat_<Base>(
186 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) >
191 template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N,
194 class MakeSocketPolicy
195 : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
196 impl::MakeSocketPolicy_impl<
199 BOOST_PP_ENUM_SHIFTED_PARAMS(
200 SENF_SOCKET_POLICIES_N, T ) > >,
201 impl::MakeSocketPolicy_impl<
204 BOOST_PP_ENUM_PARAMS(
205 SENF_SOCKET_POLICIES_N, T ) > > >::type
208 template <class BasePolicy, class DerivedPolicy>
209 struct SocketPolicyIsBaseOf
210 : public boost::mpl::if_<
211 boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >,
212 boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >,
213 impl::SocketPolicy_compatibility<BasePolicy,DerivedPolicy>,
218 # define SP_DefineConditions(x1,x2,SomePolicy) \
219 template <class Policy, class Trait> \
220 struct BOOST_PP_CAT(SomePolicy,Is) \
221 : public boost::is_convertible< typename Policy::SomePolicy*, Trait* > \
224 template <class Policy, class Trait> \
225 struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is) \
226 : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait> > \
229 template <class Policy, class Trait> \
230 struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot) \
231 : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait>::value > \
234 BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES )
236 # undef SP_DefineConditions
242 //-/////////////////////////////////////////////////////////////////////////////////////////////////
249 // c-file-style: "senf"
250 // indent-tabs-mode: nil
251 // ispell-local-dictionary: "american"
252 // compile-command: "scons -u test"
253 // comment-column: 40