SocketPolicy.ih
Go to the documentation of this file.
1 //
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
6 //
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
11 //
12 
13 
14 /** \file
15  \brief Policy Framework internal header
16  */
17 
18 #ifndef IH_SENF_Socket_SocketPolicy_
19 #define IH_SENF_Socket_SocketPolicy_ 1
20 
21 // Custom includes
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>
36 
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>
43 
44 #include <senf/Utils/mpl.hh>
45 #include <senf/Utils/pool_alloc_mixin.hh>
46 
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48 
49 /// \cond disabled
50 // Hide this code from doxygen
51 
52 namespace senf {
53 
54 # define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES )
55 
56 # define SP_DeclareAlias(x1,x2,SomePolicy) \
57  typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
58 
59  BOOST_PP_SEQ_FOR_EACH( SP_DeclareAlias, , SENF_SOCKET_POLICIES )
60 
61 # undef SP_DeclareAlias
62 
63  struct SocketPolicyBase
64  {
65  virtual ~SocketPolicyBase();
66 
67 # define SP_Declare(x1,x2,SomePolicy) \
68  virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () \
69  const = 0;
70 
71  BOOST_PP_SEQ_FOR_EACH( SP_Declare, , SENF_SOCKET_POLICIES )
72 
73 # undef SP_Declare
74  };
75 
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,_)
81 
82  template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
83  struct SocketPolicy
84  : public SocketPolicyBase,
85  public senf::pool_alloc_mixin<
86  SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParms, , SENF_SOCKET_POLICIES ) > >
87  {
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),_); }
93 
94  BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES )
95 # undef SP_DeclarePolicyMember
96 
97  static void checkBaseOf(SocketPolicyBase const & other);
98  };
99 
100 # undef SP_TemplateArgs
101 # undef SP_TemplateParms
102 
103 namespace impl {
104 
105  template <class Base, class Policy, int _>
106  struct MakeSocketPolicy_merge
107  {};
108 
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 )
112 
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)*); \
117  \
118  template <class Base, class Policy> \
119  struct MakeSocketPolicy_merge<Base,Policy,n> \
120  { \
121  typedef SocketPolicy< \
122  BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, \
123  n, \
124  SENF_SOCKET_POLICIES ) \
125  > type; \
126  };
127 
128 # include BOOST_PP_LOCAL_ITERATE()
129 
130 # undef SP_DeclareMakeSocketPolicy_merge_member
131 
132  struct MakeSocketPolicy_fold
133  {
134  template <class Base, class Policy>
135  struct apply
136  : MakeSocketPolicy_merge<Base,
137  Policy,
138  SENF_MPL_RV(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
139  {};
140 
141  template <class Base>
142  struct apply<Base,mpl::nil>
143  {
144  typedef Base type;
145  };
146  };
147 
148  template <class Base, class Vector>
149  struct MakeSocketPolicy_impl
150  {
151  typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy;
152  };
153 
154 # define SP_DeclareArguments(x1,x2,n,SomePolicy) \
155  BOOST_PP_COMMA_IF( n ) \
156  typename Base::SomePolicy *
157 
158  template <class Base>
159  senf::mpl::rv<1> SocketPolicy_checkcompat_(
160  BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) );
161 
162 # undef SP_DeclareArguments
163 
164  template <class Base>
165  senf::mpl::rv<2> SocketPolicy_checkcompat_( ... );
166 
167  template <int Size>
168  struct SocketPolicy_checkcompat
169  : public boost::false_type
170  {};
171 
172  template<>
173  struct SocketPolicy_checkcompat<1>
174  : public boost::true_type
175  {};
176 
177 
178 # define SP_DeclareArguments(x1,x2,n,SomePolicy) \
179  BOOST_PP_COMMA_IF( n ) \
180  static_cast<typename Derived::SomePolicy *>(0)
181 
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 ) )) >
187  {};
188 
189 } // namespace impl
190 
191  template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N,
192  class T,
193  mpl::nil ) >
194  class MakeSocketPolicy
195  : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
196  impl::MakeSocketPolicy_impl<
197  T0,
198  boost::mpl::vector<
199  BOOST_PP_ENUM_SHIFTED_PARAMS(
200  SENF_SOCKET_POLICIES_N, T ) > >,
201  impl::MakeSocketPolicy_impl<
202  SocketPolicy<>,
203  boost::mpl::vector<
204  BOOST_PP_ENUM_PARAMS(
205  SENF_SOCKET_POLICIES_N, T ) > > >::type
206  {};
207 
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>,
214  boost::false_type
215  >::type
216  {};
217 
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* > \
222  {}; \
223  \
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> > \
227  {}; \
228  \
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 > \
232  {};
233 
234  BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES )
235 
236 # undef SP_DefineConditions
237 
238 }
239 
240 /// \endcond
241 
242 //-/////////////////////////////////////////////////////////////////////////////////////////////////
243 #endif
244 
245 
246 // Local Variables:
247 // mode: c++
248 // fill-column: 100
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
254 // End: