switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Socket / SocketPolicy.ih
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Policy Framework internal header
30  */
31
32 #ifndef IH_SENF_Socket_SocketPolicy_
33 #define IH_SENF_Socket_SocketPolicy_ 1
34
35 // Custom includes
36 #include <boost/preprocessor/seq/for_each.hpp>
37 #include <boost/preprocessor/seq/for_each_i.hpp>
38 #include <boost/preprocessor/seq/size.hpp>
39 #include <boost/preprocessor/seq/pop_front.hpp>
40 #include <boost/preprocessor/punctuation/comma_if.hpp>
41 #include <boost/preprocessor/repetition/enum_params.hpp>
42 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
43 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
44 #include <boost/preprocessor/cat.hpp>
45 #include <boost/preprocessor/seq/elem.hpp>
46 #include <boost/preprocessor/arithmetic/dec.hpp>
47 #include <boost/preprocessor/iteration/local.hpp>
48 #include <boost/preprocessor/control/if.hpp>
49 #include <boost/preprocessor/comparison/equal.hpp>
50
51 #include <boost/type_traits.hpp>
52 #include <boost/mpl/vector.hpp>
53 #include <boost/mpl/fold.hpp>
54 #include <boost/mpl/if.hpp>
55 #include <boost/mpl/and.hpp>
56 #include <boost/utility.hpp> // for enable_if
57
58 #include <senf/Utils/mpl.hh>
59 #include <senf/Utils/pool_alloc_mixin.hh>
60
61 //-/////////////////////////////////////////////////////////////////////////////////////////////////
62
63 /// \cond disabled
64 // Hide this code from doxygen
65
66 namespace senf {
67
68 #   define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES )
69
70 #   define SP_DeclareAlias(x1,x2,SomePolicy)                                                      \
71         typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
72
73     BOOST_PP_SEQ_FOR_EACH( SP_DeclareAlias, , SENF_SOCKET_POLICIES )
74
75 #   undef SP_DeclareAlias
76
77     struct SocketPolicyBase
78     {
79         virtual ~SocketPolicyBase();
80
81 #       define SP_Declare(x1,x2,SomePolicy)                                                       \
82             virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) ()         \
83                 const = 0;
84
85         BOOST_PP_SEQ_FOR_EACH( SP_Declare, , SENF_SOCKET_POLICIES )
86
87 #       undef SP_Declare
88     };
89
90 #   define SP_TemplateArgs(x1,x2,n,SomePolicy)                                                    \
91         BOOST_PP_COMMA_IF( n )                                                                    \
92         class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base)
93 #   define SP_TemplateParms(x1,x2,n,SomePolicy)                                                   \
94         BOOST_PP_COMMA_IF( n ) BOOST_PP_CAT(SomePolicy,_)
95
96     template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
97     struct SocketPolicy
98         : public SocketPolicyBase,
99           public senf::pool_alloc_mixin<
100               SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParms, , SENF_SOCKET_POLICIES ) > >
101     {
102 #   define SP_DeclarePolicyMember(x1,x2,SomePolicy)                                               \
103         typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy;                                            \
104         SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_);                                  \
105         BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const               \
106             { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
107
108         BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES )
109 #   undef SP_DeclarePolicyMember
110
111         static void checkBaseOf(SocketPolicyBase const & other);
112     };
113
114 #   undef SP_TemplateArgs
115 #   undef SP_TemplateParms
116
117 namespace impl {
118
119     template <class Base, class Policy, int _>
120     struct MakeSocketPolicy_merge
121     {};
122
123 #   define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy)                              \
124         BOOST_PP_COMMA_IF( m )                                                                    \
125         BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy )
126
127 #    define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) )
128 #    define BOOST_PP_LOCAL_MACRO(n)                                                               \
129         senf::mpl::rv<n> MakeSocketPolicy_merge_(                                                 \
130             BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*);                   \
131                                                                                                   \
132         template <class Base, class Policy>                                                       \
133         struct MakeSocketPolicy_merge<Base,Policy,n>                                              \
134         {                                                                                         \
135             typedef SocketPolicy<                                                                 \
136                BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member,                  \
137                                         n,                                                        \
138                                         SENF_SOCKET_POLICIES )                                    \
139                > type;                                                                            \
140         };
141
142 #   include BOOST_PP_LOCAL_ITERATE()
143
144 #   undef SP_DeclareMakeSocketPolicy_merge_member
145
146     struct MakeSocketPolicy_fold
147     {
148         template <class Base, class Policy>
149         struct apply
150             : MakeSocketPolicy_merge<Base,
151                                      Policy,
152                                      SENF_MPL_RV(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
153         {};
154
155         template <class Base>
156         struct apply<Base,mpl::nil>
157         {
158             typedef Base type;
159         };
160     };
161
162     template <class Base, class Vector>
163     struct MakeSocketPolicy_impl
164     {
165         typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy;
166     };
167
168 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)                                                \
169         BOOST_PP_COMMA_IF( n )                                                                    \
170         typename Base::SomePolicy *
171
172     template <class Base>
173     senf::mpl::rv<1> SocketPolicy_checkcompat_(
174         BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) );
175
176 #   undef SP_DeclareArguments
177
178     template <class Base>
179     senf::mpl::rv<2> SocketPolicy_checkcompat_( ... );
180
181     template <int Size>
182     struct SocketPolicy_checkcompat
183         : public boost::false_type
184     {};
185
186     template<>
187     struct SocketPolicy_checkcompat<1>
188         : public boost::true_type
189     {};
190
191
192 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)                                                \
193         BOOST_PP_COMMA_IF( n )                                                                    \
194         static_cast<typename Derived::SomePolicy *>(0)
195
196     template <class Base, class Derived>
197     struct SocketPolicy_compatibility
198         : public SocketPolicy_checkcompat< SENF_MPL_RV(
199             SocketPolicy_checkcompat_<Base>(
200                 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) >
201     {};
202
203 } // namespace impl
204
205     template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N,
206                                                     class T,
207                                                     mpl::nil ) >
208     class MakeSocketPolicy
209         : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
210                                   impl::MakeSocketPolicy_impl<
211                                       T0,
212                                       boost::mpl::vector<
213                                           BOOST_PP_ENUM_SHIFTED_PARAMS(
214                                               SENF_SOCKET_POLICIES_N, T ) > >,
215                                   impl::MakeSocketPolicy_impl<
216                                       SocketPolicy<>,
217                                       boost::mpl::vector<
218                                           BOOST_PP_ENUM_PARAMS(
219                                               SENF_SOCKET_POLICIES_N, T ) > > >::type
220     {};
221
222     template <class BasePolicy, class DerivedPolicy>
223     struct SocketPolicyIsBaseOf
224         : public boost::mpl::if_<
225               boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >,
226                                 boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >,
227               impl::SocketPolicy_compatibility<BasePolicy,DerivedPolicy>,
228               boost::false_type
229           >::type
230     {};
231
232 #   define SP_DefineConditions(x1,x2,SomePolicy)                                                  \
233         template <class Policy, class Trait>                                                      \
234         struct BOOST_PP_CAT(SomePolicy,Is)                                                        \
235             : public boost::is_convertible< typename Policy::SomePolicy*, Trait* >                \
236         {};                                                                                       \
237                                                                                                   \
238         template <class Policy, class Trait>                                                      \
239         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is)                                       \
240             : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait> >                \
241         {};                                                                                       \
242                                                                                                   \
243         template <class Policy, class Trait>                                                      \
244         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot)                                    \
245             : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait>::value >     \
246         {};
247
248     BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES )
249
250 #   undef SP_DefineConditions
251
252 }
253
254 /// \endcond
255
256 //-/////////////////////////////////////////////////////////////////////////////////////////////////
257 #endif
258
259 \f
260 // Local Variables:
261 // mode: c++
262 // fill-column: 100
263 // c-file-style: "senf"
264 // indent-tabs-mode: nil
265 // ispell-local-dictionary: "american"
266 // compile-command: "scons -u test"
267 // comment-column: 40
268 // End: