4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief MultiConnectorMixin Boost.Preprocesser external iteration include */
26 #if !BOOST_PP_IS_ITERATING && !defined(MPP_SENF_PPI_MultiConnectorMixin_)
27 #define MPP_SENF_PPI_MultiConnectorMixin_ 1
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 <boost/tuple/tuple.hpp>
41 #include <senf/Utils/type_traits.hh>
43 // ///////////////////////////mpp.p////////////////////////////////////////
44 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
45 // ////////////////////////////////////////////////////////////////////////
48 // => template <class A0, class A1, ...>
49 #define mpp_TplParams() \
50 BOOST_PP_IF(BOOST_PP_ITERATION(), mpp_TplParams_, BOOST_PP_EMPTY)()
51 #define mpp_TplParams_() \
52 template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
54 // => , class A0, class A1, ...
55 #define mpp_TplParamsKomma() \
56 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
58 // => A0 const & a0, A1 const & a1, ...
59 #define mpp_FnParams() \
60 BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
62 // => , A0 const & a0, A1 const & a1, ...
63 #define mpp_FnParamsKomma() \
64 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
67 #define mpp_CallParams() \
68 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
71 #define mpp_CallParamsKomma() \
72 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
74 // Same as above but for outer iteration (in nested file iteration)
75 #define mpp_TplParamsKomma2() \
76 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), class B)
77 #define mpp_FnParams2() \
78 BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, cont & b)
79 #define mpp_FnParamsKomma2() \
80 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & b)
81 #define mpp_CallParams2() \
82 BOOST_PP_ENUM_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
83 #define mpp_CallParamsKomma2() \
84 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
86 // ////////////////////////////////////////////////////////////////////////
87 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
88 // ////////////////////////////////////////////////////////////////////////
89 // senf::ppi::module::MultiConnectorMixin member declaration 1..MAX_ARGS
92 ConnectorType_ & newConnector( mpp_FnParams() );
94 // ////////////////////////////////////////////////////////////////////////
95 #elif BOOST_PP_ITERATION_FLAGS()==9 // ////////////////////////////////////
96 // ////////////////////////////////////////////////////////////////////////
97 // senf::ppi::module::MultiConnectorMixin member declaration 1..2*MAX_ARGS
99 template <class Source, class Target mpp_TplParamsKomma()>
100 static boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &>
101 connect_(Source & source, Target & target mpp_FnParamsKomma());
103 // ////////////////////////////////////////////////////////////////////////
104 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
105 // ////////////////////////////////////////////////////////////////////////
106 // senf::ppi namespace member declaration 1..MAX_ARGS
108 // Here the reference to Source::ConnectorType / Target::ConnectorType
109 // works like enable_if, since only MultiConnector modules have those members
111 template <class Source, class Target mpp_TplParamsKomma()>
112 typename boost::enable_if<
114 senf::ppi::module::detail::IsMulticonnectorSource<Source>,
115 boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
116 typename Source::ConnectorType & >::type
117 connect(Source & source, Target & target mpp_FnParamsKomma());
119 template <class Source, class Target mpp_TplParamsKomma()>
120 typename boost::enable_if<
122 boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
123 senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
124 typename Target::ConnectorType & >::type
125 connect(Source & source, Target & target mpp_FnParamsKomma());
127 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
129 SENF_MULTI_CONNECTOR_MAX_ARGS, \
130 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
132 #include BOOST_PP_ITERATE()
134 // ////////////////////////////////////////////////////////////////////////
135 #elif BOOST_PP_ITERATION_FLAGS()==6 // ////////////////////////////////////
136 // ////////////////////////////////////////////////////////////////////////
137 // senf::ppi namespace member declaration 1..2*MAX_ARGS
139 template <class Source, class Target mpp_TplParamsKomma()>
140 typename boost::enable_if<
142 boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
143 boost::is_base_of<connector::InputConnector, typename Target::ConnectorType> >,
144 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
145 connect(Source & source, Target & target mpp_FnParamsKomma());
147 // ////////////////////////////////////////////////////////////////////////
148 #elif BOOST_PP_ITERATION_FLAGS()==4 // ////////////////////////////////////
149 // ////////////////////////////////////////////////////////////////////////
150 // senf::ppi namespace member declaration 1..MAX_ARGS x 1..MAX_ARGS
154 template <class Fn, class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
155 typename boost::enable_if_c<
156 senf::function_arity<Fn>::value == BOOST_PP_ITERATION()+1,
157 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
158 connect_(Fn, Source & source, Target & target mpp_FnParamsKomma() mpp_FnParamsKomma2());
162 // ////////////////////////////////////////////////////////////////////////
163 #elif BOOST_PP_ITERATION_FLAGS()==8 // ////////////////////////////////////
164 // ////////////////////////////////////////////////////////////////////////
165 // senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..MAX_ARGS
167 template <class Module mpp_TplParamsKomma()>
168 static typename Module::ConnectorType &
169 newConnector(Module & module mpp_FnParamsKomma());
171 // ////////////////////////////////////////////////////////////////////////
172 #elif BOOST_PP_ITERATION_FLAGS()==10 // ///////////////////////////////////
173 // ////////////////////////////////////////////////////////////////////////
174 // senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..2*MAX_ARGS
176 template <class Source, class Target mpp_TplParamsKomma()>
177 static boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &>
178 connect(Source & source, Target & target mpp_FnParamsKomma());
180 // ////////////////////////////////////////////////////////////////////////
181 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
182 // ////////////////////////////////////////////////////////////////////////
183 // Implementation 1..MAX_ARGS
185 ////////////////////////////////////////
188 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
190 prefix_ ConnectorType_ &
191 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
192 newConnector(mpp_FnParams())
194 std::auto_ptr<ConnectorType_> conn (new ConnectorType_);
195 KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
196 return * connectors_.insert(key, conn).first->second;
199 ////////////////////////////////////////
202 template <class Self_, class ConnectorType_, class ContainerType_>
204 prefix_ ConnectorType_ &
205 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
206 newConnector(mpp_FnParams())
208 connectors_.push_back(new ConnectorType_);
209 ConnectorType_ & conn (connectors_.back());
210 try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
211 catch (...) { connectors_.pop_back(); throw; }
215 ////////////////////////////////////////
216 // User managed container
218 template <class Self_, class ConnectorType_>
220 prefix_ ConnectorType_ &
221 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
222 newConnector(mpp_FnParams())
224 std::auto_ptr<ConnectorType_> cp (new ConnectorType_);
225 ConnectorType_ & cref (*cp);
226 static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
230 ////////////////////////////////////////
231 // senf::ppi::connect
233 template <class Source, class Target mpp_TplParamsKomma()>
234 typename boost::enable_if<
236 senf::ppi::module::detail::IsMulticonnectorSource<Source>,
237 boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
238 typename Source::ConnectorType & >::type
239 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
241 typename Source::ConnectorType & c (
242 module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
247 template <class Source, class Target mpp_TplParamsKomma()>
248 typename boost::enable_if<
250 boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
251 senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
252 typename Target::ConnectorType & >::type
253 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
255 typename Target::ConnectorType & c (
256 module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma()));
261 ////////////////////////////////////////
262 // senf::ppi::module::detail::MultiConnectorMixinAccess members
264 template <class Module mpp_TplParamsKomma()>
265 typename Module::ConnectorType &
266 senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector(
267 Module & module mpp_FnParamsKomma())
269 return module.newConnector(mpp_CallParams());
272 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
274 SENF_MULTI_CONNECTOR_MAX_ARGS, \
275 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
277 #include BOOST_PP_ITERATE()
279 // ////////////////////////////////////////////////////////////////////////
280 #elif BOOST_PP_ITERATION_FLAGS()==7 // ////////////////////////////////////
281 // ////////////////////////////////////////////////////////////////////////
282 // Implementation 1..2*MAX_ARGS
284 ////////////////////////////////////////
287 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
288 template <class Source, class Target mpp_TplParamsKomma()>
289 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &>
290 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
291 connect_(Source & source, Target & target mpp_FnParamsKomma())
293 return senf::ppi::detail::connect_(
294 & Self_::connectorSetup, source, target mpp_CallParamsKomma());
297 ////////////////////////////////////////
300 template <class Self_, class ConnectorType_, class ContainerType_>
301 template <class Source, class Target mpp_TplParamsKomma()>
302 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &>
303 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
304 connect_(Source & source, Target & target mpp_FnParamsKomma())
306 return senf::ppi::detail::connect_(
307 & Self_::connectorSetup, source, target mpp_CallParamsKomma());
310 ////////////////////////////////////////
313 template <class Self_, class ConnectorType_>
314 template <class Source, class Target mpp_TplParamsKomma()>
315 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &>
316 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
317 connect_(Source & source, Target & target mpp_FnParamsKomma())
319 return senf::ppi::detail::connect_(
320 & Self_::connectorSetup, source, target mpp_CallParamsKomma());
323 ////////////////////////////////////////
324 // senf::ppi::connect
326 template <class Source, class Target mpp_TplParamsKomma()>
327 typename boost::enable_if<
329 boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
330 boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType> >,
331 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
332 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
334 return module::detail::MultiConnectorMixinAccess::connect(
335 source, target mpp_CallParamsKomma());
338 ////////////////////////////////////////
339 // senf::ppi::module::detail::MultiConnectorMixinAccess members
341 template <class Source, class Target mpp_TplParamsKomma()>
342 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &>
343 senf::ppi::module::detail::MultiConnectorMixinAccess::connect(
344 Source & source, Target & target mpp_FnParamsKomma())
346 return Source::connect_(source, target mpp_CallParamsKomma());
349 ////////////////////////////////////////////////////////////////////////
350 #elif BOOST_PP_ITERATION_FLAGS()==5 // ////////////////////////////////////
351 // ////////////////////////////////////////////////////////////////////////
352 // Implementation 1..MAX_ARGS x 1..MAX_ARGS
354 template <class Fn, class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
355 typename boost::enable_if_c<
356 senf::function_arity<Fn>::value == BOOST_PP_ITERATION()+1,
357 boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
358 senf::ppi::detail::connect_(Fn, Source & source, Target & target
359 mpp_FnParamsKomma() mpp_FnParamsKomma2())
361 typename Source::ConnectorType & s (
362 module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
363 typename Target::ConnectorType & t (
364 module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma2()));
366 return boost::tie(s,t);
369 // ////////////////////////////////////////////////////////////////////////
370 #endif // /////////////////////////////////////////////////////////////////
371 // ////////////////////////////////////////////////////////////////////////
372 // Undefine local Macros
374 #undef mpp_CallParamsKomma2
375 #undef mpp_CallParams2
376 #undef mpp_FnParamsKomma2
378 #undef mpp_TplParamsKomma2
379 #undef mpp_CallParamsKomma
380 #undef mpp_CallParams
381 #undef mpp_FnParamsKomma
383 #undef mpp_TplParamsKomma
384 #undef mpp_TplParams_
387 // ////////////////////////////////////////////////////////////////////////
389 (save-excursion (re-search-backward "^// Undefine local Macros")
390 (forward-line 1) (delete-region (point) (progn (search-forward
391 "// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
392 (e (progn (insert (save-excursion (re-search-backward
393 "^// Local Macros") (search-forward "#define") (beginning-of-line)
394 (buffer-substring (point) (progn (search-forward "// ////")
395 (search-backward "#define") (forward-line 1) (point))))) (point))))
396 (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
397 t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
398 "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z0-9_]")
399 (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
402 // ////////////////////////////////////////////////////////////////////////
403 #endif // /////////////////////////////////////////////////////////////////
404 // ///////////////////////////mpp.e////////////////////////////////////////
410 // comment-column: 40
411 // c-file-style: "senf"
412 // indent-tabs-mode: nil
413 // ispell-local-dictionary: "american"
414 // compile-command: "scons -u test"