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 <senf/Utils/type_traits.hh>
42 // ///////////////////////////mpp.p////////////////////////////////////////
43 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
44 // ////////////////////////////////////////////////////////////////////////
47 #define mpp_TplParams() \
49 BOOST_PP_ITERATION(), \
52 #define mpp_TplParams_() \
53 template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
55 #define mpp_TplParamsKomma() \
56 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
57 #define mpp_FnParams() \
58 BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
59 #define mpp_FnParamsKomma() \
60 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
61 #define mpp_CallParams() \
62 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
63 #define mpp_CallParamsKomma() \
64 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
66 // Same as above but for outer loop in nested loops
67 #define mpp_TplParamsKomma2() \
68 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), class B)
69 #define mpp_FnParams2() \
70 BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & a)
71 #define mpp_FnParamsKomma2() \
72 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & b)
73 #define mpp_CallParams2() \
74 BOOST_PP_ENUM_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
75 #define mpp_CallParamsKomma2() \
76 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
78 // ////////////////////////////////////////////////////////////////////////
79 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
80 // ////////////////////////////////////////////////////////////////////////
81 // MultiConnectorMixin member declaration
84 ConnectorType_ & newConnector( mpp_FnParams() );
86 // ////////////////////////////////////////////////////////////////////////
87 #elif BOOST_PP_ITERATION_FLAGS()==9 // //////////////////////////////////////
88 // ////////////////////////////////////////////////////////////////////////
89 // MultiConnectorMixin member declaration
91 template <class Source, class Target mpp_TplParamsKomma()>
92 static std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
93 connect_(Source & source, Target & target mpp_FnParamsKomma());
95 // ////////////////////////////////////////////////////////////////////////
96 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
97 // ////////////////////////////////////////////////////////////////////////
98 // senf::ppi namespace member declaration
100 // Here the reference to Source::ConnectorType / Target::ConnectorType
101 // works like enable_if, since only MultiConnector modules have those members
103 template <class Source, class Target mpp_TplParamsKomma()>
104 typename boost::enable_if<
106 senf::ppi::module::detail::is_multiconnector_source<Source>,
107 boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_target<Target> > >,
108 typename Source::ConnectorType & >::type
109 connect(Source & source, Target & target mpp_FnParamsKomma());
111 template <class Source, class Target mpp_TplParamsKomma()>
112 typename boost::enable_if<
114 boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_source<Source> >,
115 senf::ppi::module::detail::is_multiconnector_target<Target> >,
116 typename Target::ConnectorType & >::type
117 connect(Source & source, Target & target mpp_FnParamsKomma());
119 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
121 SENF_MULTI_CONNECTOR_MAX_ARGS, \
122 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
124 #include BOOST_PP_ITERATE()
126 // ////////////////////////////////////////////////////////////////////////
127 #elif BOOST_PP_ITERATION_FLAGS()==6 // ////////////////////////////////////
128 // ////////////////////////////////////////////////////////////////////////
129 // senf::ppi namespace member declaration (nested)
131 template <class Source, class Target mpp_TplParamsKomma()>
132 typename boost::enable_if<
134 boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
135 boost::is_base_of<connector::InputConnector, typename Target::ConnectorType> >,
136 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
137 connect(Source & source, Target & target mpp_FnParamsKomma());
139 // ////////////////////////////////////////////////////////////////////////
140 #elif BOOST_PP_ITERATION_FLAGS()==4 // ////////////////////////////////////
141 // ////////////////////////////////////////////////////////////////////////
142 // senf::ppi::detail namespace member declaration (nested iteration)
146 template <class Fn, class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
147 typename boost::enable_if_c<
148 senf::function_arity<Fn>::value == BOOST_PP_ITERATION()+1,
149 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
150 connect_(Fn, Source & source, Target & target mpp_FnParamsKomma() mpp_FnParamsKomma2());
154 // ////////////////////////////////////////////////////////////////////////
155 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
156 // ////////////////////////////////////////////////////////////////////////
159 ////////////////////////////////////////
162 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
164 prefix_ ConnectorType_ &
165 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
166 newConnector(mpp_FnParams())
168 std::auto_ptr<ConnectorType_> conn (new ConnectorType_);
169 KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
170 return * connectors_.insert(key, conn).first->second;
173 ////////////////////////////////////////
176 template <class Self_, class ConnectorType_, class ContainerType_>
178 prefix_ ConnectorType_ &
179 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
180 newConnector(mpp_FnParams())
182 connectors_.push_back(new ConnectorType_);
183 ConnectorType_ & conn (connectors_.back());
184 try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
185 catch (...) { connectors_.pop_back(); throw; }
189 ////////////////////////////////////////
190 // User managed container
192 template <class Self_, class ConnectorType_>
194 prefix_ ConnectorType_ &
195 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
196 newConnector(mpp_FnParams())
198 std::auto_ptr<ConnectorType_> cp (new ConnectorType_);
199 ConnectorType_ & cref (*cp);
200 static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
204 ////////////////////////////////////////
205 // senf::ppi::module::detail::MultiConnectorMixinAccess members
207 template <class Module mpp_TplParamsKomma()>
208 typename Module::ConnectorType &
209 senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector(
210 Module & module mpp_FnParamsKomma())
212 return module.newConnector(mpp_CallParams());
215 template <class Source, class Target mpp_TplParamsKomma()>
216 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
217 senf::ppi::module::detail::MultiConnectorMixinAccess::connect(
218 Source & source, Target & target mpp_FnParamsKomma())
220 return Source::connect_(source, target mpp_CallParamsKomma());
223 ////////////////////////////////////////
224 // senf::ppi::connect
226 template <class Source, class Target mpp_TplParamsKomma()>
227 typename boost::enable_if<
229 senf::ppi::module::detail::is_multiconnector_source<Source>,
230 boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_target<Target> > >,
231 typename Source::ConnectorType & >::type
232 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
234 typename Source::ConnectorType & c (
235 module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
240 template <class Source, class Target mpp_TplParamsKomma()>
241 typename boost::enable_if<
243 boost::mpl::not_< senf::ppi::module::detail::is_multiconnector_source<Source> >,
244 senf::ppi::module::detail::is_multiconnector_target<Target> >,
245 typename Target::ConnectorType & >::type
246 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
248 typename Target::ConnectorType & c (
249 module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma()));
254 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
256 SENF_MULTI_CONNECTOR_MAX_ARGS, \
257 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
259 #include BOOST_PP_ITERATE()
261 // ////////////////////////////////////////////////////////////////////////
262 #elif BOOST_PP_ITERATION_FLAGS()==5 // ////////////////////////////////////
263 // ////////////////////////////////////////////////////////////////////////
264 // Implementation for nested iteration
266 template <class Fn, class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
267 typename boost::enable_if_c<
268 senf::function_arity<Fn>::value == BOOST_PP_ITERATION()+1,
269 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
270 senf::ppi::detail::connect_(Fn, Source & source, Target & target
271 mpp_FnParamsKomma() mpp_FnParamsKomma2())
273 typename Source::ConnectorType & s (
274 module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
275 typename Target::ConnectorType & t (
276 module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma2()));
278 return std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>(s,t);
281 // ////////////////////////////////////////////////////////////////////////
282 #elif BOOST_PP_ITERATION_FLAGS()==7 // ////////////////////////////////////
283 // ////////////////////////////////////////////////////////////////////////
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())
292 return senf::ppi::detail::connect_(
293 & Self_::connectorSetup, source, target mpp_CallParamsKomma());
296 template <class Self_, class ConnectorType_, class ContainerType_>
297 template <class Source, class Target mpp_TplParamsKomma()>
298 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
299 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
300 connect_(Source & source, Target & target mpp_FnParamsKomma())
302 return senf::ppi::detail::connect_(
303 & Self_::connectorSetup, source, target mpp_CallParamsKomma());
306 template <class Self_, class ConnectorType_>
307 template <class Source, class Target mpp_TplParamsKomma()>
308 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
309 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
310 connect_(Source & source, Target & target mpp_FnParamsKomma())
312 return senf::ppi::detail::connect_(
313 & Self_::connectorSetup, source, target mpp_CallParamsKomma());
316 template <class Source, class Target mpp_TplParamsKomma()>
317 typename boost::enable_if<
319 boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
320 boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType> >,
321 std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
322 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
324 return module::detail::MultiConnectorMixinAccess::connect(
325 source, target mpp_CallParamsKomma());
328 // ////////////////////////////////////////////////////////////////////////
329 #elif BOOST_PP_ITERATION_FLAGS()==8 // ////////////////////////////////////
330 // ////////////////////////////////////////////////////////////////////////
331 // senf::ppi::module::detail::MultiConnectorMixinAccess members
333 template <class Module mpp_TplParamsKomma()>
334 static typename Module::ConnectorType &
335 newConnector(Module & module mpp_FnParamsKomma());
337 template <class Source, class Target mpp_TplParamsKomma()>
338 static std::pair<typename Source::ConnectorType &, typename Target::ConnectorType &>
339 connect(Source & source, Target & target mpp_FnParamsKomma());
341 // ////////////////////////////////////////////////////////////////////////
342 #endif // /////////////////////////////////////////////////////////////////
343 // ////////////////////////////////////////////////////////////////////////
344 // Undefine local Macros
346 #undef mpp_CallParamsKomma2
347 #undef mpp_CallParams2
348 #undef mpp_FnParamsKomma2
350 #undef mpp_TplParamsKomma2
351 #undef mpp_CallParamsKomma
352 #undef mpp_CallParams
353 #undef mpp_FnParamsKomma
355 #undef mpp_TplParamsKomma
356 #undef mpp_TplParams_
359 // ////////////////////////////////////////////////////////////////////////
361 (save-excursion (re-search-backward "^// Undefine local Macros")
362 (forward-line 1) (delete-region (point) (progn (search-forward
363 "// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
364 (e (progn (insert (save-excursion (re-search-backward
365 "^// Local Macros") (search-forward "#define") (beginning-of-line)
366 (buffer-substring (point) (progn (search-forward "// ////")
367 (search-backward "#define") (forward-line 1) (point))))) (point))))
368 (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
369 t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
370 "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z0-9_]")
371 (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
374 // ////////////////////////////////////////////////////////////////////////
375 #endif // /////////////////////////////////////////////////////////////////
376 // ///////////////////////////mpp.e////////////////////////////////////////
382 // comment-column: 40
383 // c-file-style: "senf"
384 // indent-tabs-mode: nil
385 // ispell-local-dictionary: "american"
386 // compile-command: "scons -u test"