PPI: double MultiConnectorMixin connect comments and cleanup
[senf.git] / senf / PPI / MultiConnectorMixin.mpp
1 // $Id$
2 //
3 // Copyright (C) 2009 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.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 MultiConnectorMixin Boost.Preprocesser external iteration include */
25
26 #if !BOOST_PP_IS_ITERATING && !defined(MPP_SENF_PPI_MultiConnectorMixin_)
27 #define MPP_SENF_PPI_MultiConnectorMixin_ 1
28
29 // Custom includes
30 #include <boost/preprocessor/iteration/iterate.hpp>
31 #include <boost/preprocessor/control/if.hpp>
32 #include <boost/preprocessor/facilities/empty.hpp> 
33 #include <boost/preprocessor/repetition/enum_params.hpp>
34 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
35 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
36 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> 
37 #include <boost/type_traits/is_base_of.hpp>
38 #include <boost/mpl/and.hpp>
39 #include <boost/mpl/not.hpp>
40 #include <senf/Utils/type_traits.hh>
41
42 // ///////////////////////////mpp.p////////////////////////////////////////
43 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
44 // ////////////////////////////////////////////////////////////////////////
45 // Local Macros
46
47 // => template <class A0, class A1, ...>
48 #define mpp_TplParams()                                                 \
49     BOOST_PP_IF(BOOST_PP_ITERATION(), mpp_TplParams_, BOOST_PP_EMPTY)()
50 #define mpp_TplParams_()                                                \
51     template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
52
53 // => , class A0, class A1, ...
54 #define mpp_TplParamsKomma()                                            \
55     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
56
57 // => A0 const & a0, A1 const & a1, ...
58 #define mpp_FnParams()                                                  \
59     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
60
61 // => , A0 const & a0, A1 const & a1, ...
62 #define mpp_FnParamsKomma()                                             \
63     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
64
65 // => a0, a1, ...
66 #define mpp_CallParams()                                                \
67     BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
68
69 // => , a0, a1, ...
70 #define mpp_CallParamsKomma()                                           \
71     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
72
73 // Same as above but for outer iteration (in nested file iteration)
74 #define mpp_TplParamsKomma2()                                            \
75     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), class B)
76 #define mpp_FnParams2()                                                  \
77     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, cont & b)
78 #define mpp_FnParamsKomma2()                                             \
79     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & b)
80 #define mpp_CallParams2()                                                \
81     BOOST_PP_ENUM_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
82 #define mpp_CallParamsKomma2()                                           \
83     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
84
85 // ////////////////////////////////////////////////////////////////////////
86 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
87 // ////////////////////////////////////////////////////////////////////////
88 // senf::ppi::module::MultiConnectorMixin member declaration 1..MAX_ARGS
89
90 mpp_TplParams()
91 ConnectorType_ & newConnector( mpp_FnParams() );
92
93 // ////////////////////////////////////////////////////////////////////////
94 #elif BOOST_PP_ITERATION_FLAGS()==9 // ////////////////////////////////////
95 // ////////////////////////////////////////////////////////////////////////
96 // senf::ppi::module::MultiConnectorMixin member declaration 1..2*MAX_ARGS
97
98 template <class Source, class Target mpp_TplParamsKomma()>
99 static std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
100 connect_(Source & source, Target & target mpp_FnParamsKomma());
101
102 // ////////////////////////////////////////////////////////////////////////
103 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
104 // ////////////////////////////////////////////////////////////////////////
105 // senf::ppi namespace member declaration 1..MAX_ARGS
106
107 // Here the reference to Source::ConnectorType / Target::ConnectorType
108 // works like enable_if, since only MultiConnector modules have those members
109
110 template <class Source, class Target mpp_TplParamsKomma()>
111 typename boost::enable_if<
112     boost::mpl::and_<
113         senf::ppi::module::detail::IsMulticonnectorSource<Source>,
114         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
115     typename Source::ConnectorType & >::type
116 connect(Source & source, Target & target mpp_FnParamsKomma());
117
118 template <class Source, class Target mpp_TplParamsKomma()>
119 typename boost::enable_if<
120     boost::mpl::and_<
121         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
122         senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
123     typename Target::ConnectorType & >::type
124 connect(Source & source, Target & target mpp_FnParamsKomma());
125
126 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
127         0, \
128         SENF_MULTI_CONNECTOR_MAX_ARGS, \
129         SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
130         4 ))
131 #include BOOST_PP_ITERATE()
132
133 // ////////////////////////////////////////////////////////////////////////
134 #elif BOOST_PP_ITERATION_FLAGS()==6 // ////////////////////////////////////
135 // ////////////////////////////////////////////////////////////////////////
136 // senf::ppi namespace member declaration 1..2*MAX_ARGS
137
138 template <class Source, class Target mpp_TplParamsKomma()>
139 typename boost::enable_if<
140     boost::mpl::and_<
141         boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
142         boost::is_base_of<connector::InputConnector, typename Target::ConnectorType> >,
143     std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
144 connect(Source & source, Target & target mpp_FnParamsKomma());
145
146 // ////////////////////////////////////////////////////////////////////////
147 #elif BOOST_PP_ITERATION_FLAGS()==4 // ////////////////////////////////////
148 // ////////////////////////////////////////////////////////////////////////
149 // senf::ppi namespace member declaration 1..MAX_ARGS x 1..MAX_ARGS
150
151 namespace detail {
152
153 template <class Fn, class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
154 typename boost::enable_if_c<
155     senf::function_arity<Fn>::value == BOOST_PP_ITERATION()+1,
156     std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
157 connect_(Fn, Source & source, Target & target mpp_FnParamsKomma() mpp_FnParamsKomma2());
158
159 }
160
161 // ////////////////////////////////////////////////////////////////////////
162 #elif BOOST_PP_ITERATION_FLAGS()==8 // ////////////////////////////////////
163 // ////////////////////////////////////////////////////////////////////////
164 // senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..MAX_ARGS
165
166 template <class Module mpp_TplParamsKomma()>
167 static typename Module::ConnectorType & 
168 newConnector(Module & module mpp_FnParamsKomma());
169
170 // ////////////////////////////////////////////////////////////////////////
171 #elif BOOST_PP_ITERATION_FLAGS()==10 // ///////////////////////////////////
172 // ////////////////////////////////////////////////////////////////////////
173 // senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..2*MAX_ARGS
174
175 template <class Source, class Target mpp_TplParamsKomma()>
176 static std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
177 connect(Source & source, Target & target mpp_FnParamsKomma());
178
179 // ////////////////////////////////////////////////////////////////////////
180 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
181 // ////////////////////////////////////////////////////////////////////////
182 // Implementation 1..MAX_ARGS
183
184 ////////////////////////////////////////
185 // Map container
186
187 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
188 mpp_TplParams()
189 prefix_ ConnectorType_ &
190 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
191 newConnector(mpp_FnParams())
192 {
193     std::auto_ptr<ConnectorType_> conn (new ConnectorType_);
194     KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
195     return * connectors_.insert(key, conn).first->second;
196 }
197
198 ////////////////////////////////////////
199 // Vector container
200
201 template <class Self_, class ConnectorType_, class ContainerType_>
202 mpp_TplParams()
203 prefix_ ConnectorType_ &
204 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
205 newConnector(mpp_FnParams())
206 {
207     connectors_.push_back(new ConnectorType_);
208     ConnectorType_ & conn (connectors_.back());
209     try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
210     catch (...) { connectors_.pop_back(); throw; }
211     return conn;
212 }
213
214 ////////////////////////////////////////
215 // User managed container
216
217 template <class Self_, class ConnectorType_>
218 mpp_TplParams()
219 prefix_ ConnectorType_ &
220 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
221 newConnector(mpp_FnParams())
222 {
223     std::auto_ptr<ConnectorType_> cp (new ConnectorType_);
224     ConnectorType_ & cref (*cp);
225     static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
226     return cref;
227 }
228
229 ////////////////////////////////////////
230 // senf::ppi::connect
231
232 template <class Source, class Target mpp_TplParamsKomma()>
233 typename boost::enable_if<
234     boost::mpl::and_<
235         senf::ppi::module::detail::IsMulticonnectorSource<Source>,
236         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
237     typename Source::ConnectorType & >::type
238 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
239 {
240     typename Source::ConnectorType & c (
241         module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
242     connect(c, target);
243     return c;
244 }
245
246 template <class Source, class Target mpp_TplParamsKomma()>
247 typename boost::enable_if<
248     boost::mpl::and_<
249         boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
250         senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
251     typename Target::ConnectorType & >::type
252 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
253 {
254     typename Target::ConnectorType & c (
255         module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma()));
256     connect(source, c);
257     return c;
258 }
259
260 ////////////////////////////////////////
261 // senf::ppi::module::detail::MultiConnectorMixinAccess members
262
263 template <class Module mpp_TplParamsKomma()>
264 typename Module::ConnectorType & 
265 senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector(
266     Module & module mpp_FnParamsKomma())
267 {
268     return module.newConnector(mpp_CallParams());
269 }
270
271 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
272         0, \
273         SENF_MULTI_CONNECTOR_MAX_ARGS, \
274         SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
275         5 ))
276 #include BOOST_PP_ITERATE()
277
278 // ////////////////////////////////////////////////////////////////////////
279 #elif BOOST_PP_ITERATION_FLAGS()==7 // ////////////////////////////////////
280 // ////////////////////////////////////////////////////////////////////////
281 // Implementation 1..2*MAX_ARGS
282
283 ////////////////////////////////////////
284 // Map container
285
286 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
287 template <class Source, class Target mpp_TplParamsKomma()>
288 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
289 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
290 connect_(Source & source, Target & target mpp_FnParamsKomma())
291 {
292     return senf::ppi::detail::connect_(
293         & Self_::connectorSetup, source, target mpp_CallParamsKomma());
294 }
295
296 ////////////////////////////////////////
297 // Vector container
298
299 template <class Self_, class ConnectorType_, class ContainerType_>
300 template <class Source, class Target mpp_TplParamsKomma()>
301 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
302 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
303 connect_(Source & source, Target & target mpp_FnParamsKomma())
304 {
305     return senf::ppi::detail::connect_(
306         & Self_::connectorSetup, source, target mpp_CallParamsKomma());
307 }
308
309 ////////////////////////////////////////
310 // User container
311
312 template <class Self_, class ConnectorType_>
313 template <class Source, class Target mpp_TplParamsKomma()>
314 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
315 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
316 connect_(Source & source, Target & target mpp_FnParamsKomma())
317 {
318     return senf::ppi::detail::connect_(
319         & Self_::connectorSetup, source, target mpp_CallParamsKomma());
320 }
321
322 ////////////////////////////////////////
323 // senf::ppi::connect
324
325 template <class Source, class Target mpp_TplParamsKomma()>
326 typename boost::enable_if<
327     boost::mpl::and_<
328         boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
329         boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType> >,
330     std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
331 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
332 {
333     return module::detail::MultiConnectorMixinAccess::connect(
334         source, target mpp_CallParamsKomma());
335 }
336
337 ////////////////////////////////////////
338 // senf::ppi::module::detail::MultiConnectorMixinAccess members
339
340 template <class Source, class Target mpp_TplParamsKomma()>
341 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
342 senf::ppi::module::detail::MultiConnectorMixinAccess::connect(
343     Source & source, Target & target mpp_FnParamsKomma())
344 {
345     return Source::connect_(source, target mpp_CallParamsKomma());
346 }
347
348 ////////////////////////////////////////////////////////////////////////
349 #elif BOOST_PP_ITERATION_FLAGS()==5 // ////////////////////////////////////
350 // ////////////////////////////////////////////////////////////////////////
351 // Implementation 1..MAX_ARGS x 1..MAX_ARGS
352
353 template <class Fn, class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
354 typename boost::enable_if_c<
355     senf::function_arity<Fn>::value == BOOST_PP_ITERATION()+1,
356     std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
357 senf::ppi::detail::connect_(Fn, Source & source, Target & target 
358                             mpp_FnParamsKomma() mpp_FnParamsKomma2())
359 {
360     typename Source::ConnectorType & s (
361         module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
362     typename Target::ConnectorType & t (
363         module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma2()));
364     connect(s,t);
365     return std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>(s,t);
366 }
367
368 // ////////////////////////////////////////////////////////////////////////
369 #endif // /////////////////////////////////////////////////////////////////
370 // ////////////////////////////////////////////////////////////////////////
371 // Undefine local Macros
372
373 #undef mpp_CallParamsKomma2
374 #undef mpp_CallParams2
375 #undef mpp_FnParamsKomma2
376 #undef mpp_FnParams2
377 #undef mpp_TplParamsKomma2
378 #undef mpp_CallParamsKomma
379 #undef mpp_CallParams
380 #undef mpp_FnParamsKomma
381 #undef mpp_FnParams
382 #undef mpp_TplParamsKomma
383 #undef mpp_TplParams_
384 #undef mpp_TplParams
385             
386 // ////////////////////////////////////////////////////////////////////////
387 /*
388  (save-excursion (re-search-backward "^// Undefine local Macros")
389  (forward-line 1) (delete-region (point) (progn (search-forward
390  "// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
391  (e (progn (insert (save-excursion (re-search-backward 
392  "^// Local Macros") (search-forward "#define") (beginning-of-line)
393  (buffer-substring (point) (progn (search-forward "// ////")
394  (search-backward "#define") (forward-line 1) (point))))) (point))))
395  (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
396  t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
397  "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z0-9_]")
398  (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
399  1))))
400 */
401 // ////////////////////////////////////////////////////////////////////////
402 #endif // /////////////////////////////////////////////////////////////////
403 // ///////////////////////////mpp.e////////////////////////////////////////
404
405 \f
406 // Local Variables:
407 // mode: c++
408 // fill-column: 100
409 // comment-column: 40
410 // c-file-style: "senf"
411 // indent-tabs-mode: nil
412 // ispell-local-dictionary: "american"
413 // compile-command: "scons -u test"
414 // End: