MultiConnectorMixin.mpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief MultiConnectorMixin Boost.Preprocesser external iteration include */
16 
17 #if !BOOST_PP_IS_ITERATING && !defined(MPP_SENF_PPI_MultiConnectorMixin_)
18 #define MPP_SENF_PPI_MultiConnectorMixin_ 1
19 
20 // Custom includes
21 #include <boost/preprocessor/iteration/iterate.hpp>
22 #include <boost/preprocessor/control/if.hpp>
23 #include <boost/preprocessor/facilities/empty.hpp>
24 #include <boost/preprocessor/repetition/enum_params.hpp>
25 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
26 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
27 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
28 #include <boost/type_traits/is_base_of.hpp>
29 #include <boost/mpl/and.hpp>
30 #include <boost/mpl/not.hpp>
31 #include <boost/tuple/tuple.hpp>
32 
33 //-///////////////////////////mpp.p////////////////////////////////////////
34 #elif BOOST_PP_IS_ITERATING //-////////////////////////////////////////////
35 //-////////////////////////////////////////////////////////////////////////
36 // Local Macros
37 
38 // => template <class A0, class A1, ...>
39 #define mpp_TplParams() \
40  BOOST_PP_IF(BOOST_PP_ITERATION(), mpp_TplParams_, BOOST_PP_EMPTY)()
41 #define mpp_TplParams_() \
42  template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
43 
44 // => , class A0, class A1, ...
45 #define mpp_TplParamsKomma() \
46  BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
47 
48 // => A0 const & a0, A1 const & a1, ...
49 #define mpp_FnParams() \
50  BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
51 
52 // => , A0 const & a0, A1 const & a1, ...
53 #define mpp_FnParamsKomma() \
54  BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
55 
56 // => a0, a1, ...
57 #define mpp_CallParams() \
58  BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
59 
60 // => , a0, a1, ...
61 #define mpp_CallParamsKomma() \
62  BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
63 
64 // Same as above but for outer iteration (in nested file iteration)
65 #define mpp_TplParamsKomma2() \
66  BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), class B)
67 #define mpp_FnParams2() \
68  BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, cont & b)
69 #define mpp_FnParamsKomma2() \
70  BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_FRAME_ITERATION(1), B, const & b)
71 #define mpp_CallParams2() \
72  BOOST_PP_ENUM_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
73 #define mpp_CallParamsKomma2() \
74  BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_FRAME_ITERATION(1), b)
75 
76 //-////////////////////////////////////////////////////////////////////////
77 #if BOOST_PP_ITERATION_FLAGS()==1 //-//////////////////////////////////////
78 //-////////////////////////////////////////////////////////////////////////
79 // senf::ppi::module::MultiConnectorMixin member declaration 1..MAX_ARGS
80 
81 mpp_TplParams()
82 ConnectorType_ & newConnector( mpp_FnParams() );
83 
84 //-////////////////////////////////////////////////////////////////////////
85 #elif BOOST_PP_ITERATION_FLAGS()==2 //-////////////////////////////////////
86 //-////////////////////////////////////////////////////////////////////////
87 // senf::ppi namespace member declaration 1..MAX_ARGS
88 
89 // Here the reference to Source::ConnectorType / Target::ConnectorType
90 // works like enable_if, since only MultiConnector modules have those members
91 
92 template <class Source, class Target mpp_TplParamsKomma()>
93 typename boost::enable_if<
94  boost::mpl::and_<
95  senf::ppi::module::detail::IsMulticonnectorSource<Source>,
96  boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
97  typename Source::ConnectorType & >::type
98 connect(Source & source mpp_FnParamsKomma(), Target & target);
99 
100 template <class Source, class Target mpp_TplParamsKomma()>
101 typename boost::enable_if<
102  boost::mpl::and_<
103  boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
104  senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
105  typename Target::ConnectorType & >::type
106 connect(Source & source, Target & target mpp_FnParamsKomma());
107 
108 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
109  0, \
110  SENF_MULTI_CONNECTOR_MAX_ARGS, \
111  SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
112  4 ))
113 #include BOOST_PP_ITERATE()
114 
115 //-////////////////////////////////////////////////////////////////////////
116 #elif BOOST_PP_ITERATION_FLAGS()==4 //-////////////////////////////////////
117 //-////////////////////////////////////////////////////////////////////////
118 // senf::ppi namespace member declaration 1..MAX_ARGS x 1..MAX_ARGS
119 
120 template <class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
121 typename boost::enable_if<
122  boost::mpl::and_<
123  boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
124  boost::is_base_of<connector::InputConnector, typename Target::ConnectorType> >,
125  boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
126 connect(Source & source mpp_FnParamsKomma(), Target & target mpp_FnParamsKomma2());
127 
128 //-////////////////////////////////////////////////////////////////////////
129 #elif BOOST_PP_ITERATION_FLAGS()==8 //-////////////////////////////////////
130 //-////////////////////////////////////////////////////////////////////////
131 // senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..MAX_ARGS
132 
133 template <class Module mpp_TplParamsKomma()>
134 static typename Module::ConnectorType &
135 newConnector(Module & module mpp_FnParamsKomma());
136 
137 //-////////////////////////////////////////////////////////////////////////
138 #elif BOOST_PP_ITERATION_FLAGS()==3 //-////////////////////////////////////
139 //-////////////////////////////////////////////////////////////////////////
140 // Implementation 1..MAX_ARGS
141 
142 //-/////////////////////////////////////////////////////////////////////////////////////////////////
143 // Map container
144 
145 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
146 mpp_TplParams()
147 prefix_ ConnectorType_ &
148 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
149 newConnector(mpp_FnParams())
150 {
151  std::auto_ptr<ConnectorType_> conn (new detail::MultiConnectorWrapper<Self_,ConnectorType_>);
152  KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
153  return * connectors_.insert(key, conn).first->second;
154 }
155 
156 //-/////////////////////////////////////////////////////////////////////////////////////////////////
157 // Vector container
158 
159 template <class Self_, class ConnectorType_, class ContainerType_>
160 mpp_TplParams()
161 prefix_ ConnectorType_ &
162 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
163 newConnector(mpp_FnParams())
164 {
165  connectors_.push_back(new detail::MultiConnectorWrapper<Self_,ConnectorType_>);
166  ConnectorType_ & conn (connectors_.back());
167  try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
168  catch (...) { disconnected(conn); throw; }
169  return conn;
170 }
171 
172 //-/////////////////////////////////////////////////////////////////////////////////////////////////
173 // User managed container
174 
175 template <class Self_, class ConnectorType_>
176 mpp_TplParams()
177 prefix_ ConnectorType_ &
178 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
179 newConnector(mpp_FnParams())
180 {
181  std::auto_ptr<ConnectorType_> cp (new detail::MultiConnectorWrapper<Self_,ConnectorType_>);
182  ConnectorType_ & cref (*cp);
183  static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
184  return cref;
185 }
186 
187 //-/////////////////////////////////////////////////////////////////////////////////////////////////
188 // senf::ppi::connect
189 
190 template <class Source, class Target mpp_TplParamsKomma()>
191 typename boost::enable_if<
192  boost::mpl::and_<
193  senf::ppi::module::detail::IsMulticonnectorSource<Source>,
194  boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorTarget<Target> > >,
195  typename Source::ConnectorType & >::type
196 senf::ppi::connect(Source & source mpp_FnParamsKomma(), Target & target)
197 {
198  typename Source::ConnectorType & c (
199  module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
200  connect(c, target);
201  return c;
202 }
203 
204 template <class Source, class Target mpp_TplParamsKomma()>
205 typename boost::enable_if<
206  boost::mpl::and_<
207  boost::mpl::not_< senf::ppi::module::detail::IsMulticonnectorSource<Source> >,
208  senf::ppi::module::detail::IsMulticonnectorTarget<Target> >,
209  typename Target::ConnectorType & >::type
210 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
211 {
212  typename Target::ConnectorType & c (
213  module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma()));
214  connect(source, c);
215  return c;
216 }
217 
218 //-/////////////////////////////////////////////////////////////////////////////////////////////////
219 // senf::ppi::module::detail::MultiConnectorMixinAccess members
220 
221 template <class Module mpp_TplParamsKomma()>
222 typename Module::ConnectorType &
223 senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector(
224  Module & module mpp_FnParamsKomma())
225 {
226  return module.newConnector(mpp_CallParams());
227 }
228 
229 #define BOOST_PP_ITERATION_PARAMS_2 (4, (\
230  0, \
231  SENF_MULTI_CONNECTOR_MAX_ARGS, \
232  SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
233  5 ))
234 #include BOOST_PP_ITERATE()
235 
236 //-/////////////////////////////////////////////////////////////////////////////////////////////////
237 #elif BOOST_PP_ITERATION_FLAGS()==5 //-////////////////////////////////////
238 //-////////////////////////////////////////////////////////////////////////
239 // Implementation 1..MAX_ARGS x 1..MAX_ARGS
240 
241 template <class Source, class Target mpp_TplParamsKomma() mpp_TplParamsKomma2()>
242 typename boost::enable_if<
243  boost::mpl::and_<
244  boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
245  boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType> >,
246  boost::tuple<typename Source::ConnectorType &, typename Target::ConnectorType &> >::type
247 senf::ppi::connect(Source & source mpp_FnParamsKomma(), Target & target mpp_FnParamsKomma2())
248 {
249  typename Source::ConnectorType & s (
250  module::detail::MultiConnectorMixinAccess::newConnector(source mpp_CallParamsKomma()));
251  typename Target::ConnectorType & t (
252  module::detail::MultiConnectorMixinAccess::newConnector(target mpp_CallParamsKomma2()));
253  connect(s,t);
254  return boost::tie(s,t);
255 }
256 
257 //-////////////////////////////////////////////////////////////////////////
258 #endif //-/////////////////////////////////////////////////////////////////
259 //-////////////////////////////////////////////////////////////////////////
260 // Undefine local Macros
261 
262 #undef mpp_CallParamsKomma2
263 #undef mpp_CallParams2
264 #undef mpp_FnParamsKomma2
265 #undef mpp_FnParams2
266 #undef mpp_TplParamsKomma2
267 #undef mpp_CallParamsKomma
268 #undef mpp_CallParams
269 #undef mpp_FnParamsKomma
270 #undef mpp_FnParams
271 #undef mpp_TplParamsKomma
272 #undef mpp_TplParams_
273 #undef mpp_TplParams
274 
275 //-////////////////////////////////////////////////////////////////////////
276 /*
277  (save-excursion (re-search-backward "^// Undefine local Macros")
278  (forward-line 1) (delete-region (point) (progn (search-forward
279  "//-////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
280  (e (progn (insert (save-excursion (re-search-backward
281  "^// Local Macros") (search-forward "#define") (beginning-of-line)
282  (buffer-substring (point) (progn (search-forward "//-////")
283  (search-backward "#define") (forward-line 1) (point))))) (point))))
284  (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
285  t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
286  "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z0-9_]")
287  (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
288  1))))
289 */
290 //-////////////////////////////////////////////////////////////////////////
291 #endif //-/////////////////////////////////////////////////////////////////
292 //-///////////////////////////mpp.e////////////////////////////////////////
293 
294 
295 // Local Variables:
296 // mode: c++
297 // fill-column: 100
298 // comment-column: 40
299 // c-file-style: "senf"
300 // indent-tabs-mode: nil
301 // ispell-local-dictionary: "american"
302 // compile-command: "scons -u test"
303 // End: