Move include files in debian packge into 'senf' subdirectory
[senf.git] / Socket / SocketPolicy.ih
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Policy Framework internal header
25  */
26
27 #ifndef IH_SocketPolicy_
28 #define IH_SocketPolicy_ 1
29
30 // Custom includes
31 #include <boost/preprocessor/seq/for_each.hpp>
32 #include <boost/preprocessor/seq/for_each_i.hpp>
33 #include <boost/preprocessor/seq/size.hpp>
34 #include <boost/preprocessor/seq/pop_front.hpp>
35 #include <boost/preprocessor/punctuation/comma_if.hpp>
36 #include <boost/preprocessor/repetition/enum_params.hpp>
37 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
38 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
39 #include <boost/preprocessor/cat.hpp>
40 #include <boost/preprocessor/seq/elem.hpp>
41 #include <boost/preprocessor/arithmetic/dec.hpp>
42 #include <boost/preprocessor/iteration/local.hpp>
43 #include <boost/preprocessor/control/if.hpp>
44 #include <boost/preprocessor/comparison/equal.hpp>
45
46 #include <boost/type_traits.hpp>
47 #include <boost/mpl/vector.hpp>
48 #include <boost/mpl/fold.hpp>
49 #include <boost/mpl/if.hpp>
50 #include <boost/mpl/and.hpp>
51 #include <boost/utility.hpp> // for enable_if
52
53 #include "../Utils/mpl.hh"
54 #include "../Utils/pool_alloc_mixin.hh"
55
56 ///////////////////////////////ih.p////////////////////////////////////////
57
58 /// \cond disabled
59 // Hide this code from doxygen
60
61 namespace senf {
62
63 #   define SENF_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SENF_SOCKET_POLICIES )
64
65 #   define SP_DeclareAlias(x1,x2,SomePolicy)                                                      \
66         typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy);
67
68     BOOST_PP_SEQ_FOR_EACH( SP_DeclareAlias, , SENF_SOCKET_POLICIES )
69
70 #   undef SP_DeclareAlias
71
72     struct SocketPolicyBase
73     {
74         virtual ~SocketPolicyBase() {}
75
76 #       define SP_Declare(x1,x2,SomePolicy)                                                       \
77             virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) ()         \
78                 const = 0;
79
80         BOOST_PP_SEQ_FOR_EACH( SP_Declare, , SENF_SOCKET_POLICIES )
81
82 #       undef SP_Declare
83     };
84
85 #   define SP_TemplateArgs(x1,x2,n,SomePolicy)                                                    \
86         BOOST_PP_COMMA_IF( n )                                                                    \
87         class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base)
88 #   define SP_TemplateParms(x1,x2,n,SomePolicy)                                                   \
89         BOOST_PP_COMMA_IF( n ) BOOST_PP_CAT(SomePolicy,_)
90
91     template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
92     struct SocketPolicy
93         : public SocketPolicyBase,
94           public senf::pool_alloc_mixin< 
95               SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParms, , SENF_SOCKET_POLICIES ) > >
96     {
97 #   define SP_DeclarePolicyMember(x1,x2,SomePolicy)                                               \
98         typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy;                                            \
99         SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_);                                  \
100         BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const               \
101             { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); }
102
103         BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SENF_SOCKET_POLICIES )
104 #   undef SP_DeclarePolicyMember
105
106         static void checkBaseOf(SocketPolicyBase const & other);
107     };
108
109 #   undef SP_TemplateArgs
110 #   undef SP_TemplateParms
111
112 namespace impl {
113
114     struct nil {};
115
116     template <class Base, class Policy, int _>
117     struct MakeSocketPolicy_merge
118     {};
119
120 #   define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy)                              \
121         BOOST_PP_COMMA_IF( m )                                                                    \
122         BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy )
123
124 #    define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SENF_SOCKET_POLICIES_N ) )
125 #    define BOOST_PP_LOCAL_MACRO(n)                                                               \
126         senf::mpl::rv<n> MakeSocketPolicy_merge_(                                                 \
127             BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SENF_SOCKET_POLICIES ),Base)*);                   \
128                                                                                                   \
129         template <class Base, class Policy>                                                       \
130         struct MakeSocketPolicy_merge<Base,Policy,n>                                              \
131         {                                                                                         \
132             typedef SocketPolicy<                                                                 \
133                BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member,                  \
134                                         n,                                                        \
135                                         SENF_SOCKET_POLICIES )                                    \
136                > type;                                                                            \
137         };
138
139 #   include BOOST_PP_LOCAL_ITERATE()
140
141 #   undef SP_DeclareMakeSocketPolicy_merge_member
142
143     struct MakeSocketPolicy_fold
144     {
145         template <class Base, class Policy>
146         struct apply
147             : MakeSocketPolicy_merge<Base,
148                                      Policy,
149                                      SENF_MPL_RV(MakeSocketPolicy_merge_(static_cast<Policy*>(0)))>
150         {};
151
152         template <class Base>
153         struct apply<Base,nil>
154         {
155             typedef Base type;
156         };
157     };
158
159     template <class Base, class Vector>
160     struct MakeSocketPolicy_impl
161     {
162         typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy;
163     };
164
165 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)                                                \
166         BOOST_PP_COMMA_IF( n )                                                                    \
167         typename Base::SomePolicy *
168
169     template <class Base>
170     senf::mpl::rv<1> SocketPolicy_checkcompat_(
171         BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) );
172
173 #   undef SP_DeclareArguments
174
175     template <class Base>
176     senf::mpl::rv<2> SocketPolicy_checkcompat_( ... );
177
178     template <int Size>
179     struct SocketPolicy_checkcompat
180         : public boost::false_type
181     {};
182
183     template<>
184     struct SocketPolicy_checkcompat<1>
185         : public boost::true_type
186     {};
187
188
189 #   define SP_DeclareArguments(x1,x2,n,SomePolicy)                                                \
190         BOOST_PP_COMMA_IF( n )                                                                    \
191         static_cast<typename Derived::SomePolicy *>(0)
192
193     template <class Base, class Derived>
194     struct SocketPolicy_compatibility
195         : public SocketPolicy_checkcompat< SENF_MPL_RV(
196             SocketPolicy_checkcompat_<Base>(
197                 BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SENF_SOCKET_POLICIES ) )) >
198     {};
199
200 } // namespace impl
201
202     template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N, 
203                                                     class T, 
204                                                     senf::impl::nil ) >
205     class MakeSocketPolicy
206         : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
207                                   impl::MakeSocketPolicy_impl< 
208                                       T0, 
209                                       boost::mpl::vector< 
210                                           BOOST_PP_ENUM_SHIFTED_PARAMS( 
211                                               SENF_SOCKET_POLICIES_N, T ) > >,
212                                   impl::MakeSocketPolicy_impl< 
213                                       SocketPolicy<>,
214                                       boost::mpl::vector< 
215                                           BOOST_PP_ENUM_PARAMS( 
216                                               SENF_SOCKET_POLICIES_N, T ) > > >::type
217     {};
218
219     template <class BasePolicy, class DerivedPolicy>
220     struct SocketPolicyIsBaseOf
221         : public boost::mpl::if_< 
222               boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >,
223                                 boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >,
224               impl::SocketPolicy_compatibility<BasePolicy,DerivedPolicy>,
225               boost::false_type 
226           >::type
227     {};
228
229 #   define SP_DefineConditions(x1,x2,SomePolicy)                                                  \
230         template <class Policy, class Trait>                                                      \
231         struct BOOST_PP_CAT(SomePolicy,Is)                                                        \
232             : public boost::is_convertible< typename Policy::SomePolicy*, Trait* >                \
233         {};                                                                                       \
234                                                                                                   \
235         template <class Policy, class Trait>                                                      \
236         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is)                                       \
237             : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait> >                \
238         {};                                                                                       \
239                                                                                                   \
240         template <class Policy, class Trait>                                                      \
241         struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot)                                    \
242             : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)<Policy,Trait>::value >     \
243         {};
244
245     BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SENF_SOCKET_POLICIES )
246
247 #   undef SP_DefineConditions
248
249 }
250
251 /// \endcond
252
253 ///////////////////////////////ih.e////////////////////////////////////////
254 #endif
255
256 \f
257 // Local Variables:
258 // mode: c++
259 // fill-column: 100
260 // c-file-style: "senf"
261 // indent-tabs-mode: nil
262 // ispell-local-dictionary: "american"
263 // compile-command: "scons -u test"
264 // comment-column: 40
265 // End: