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 public header */
26 #ifndef HH_SENF_PPI_MultiConnectorMixin_
27 #define HH_SENF_PPI_MultiConnectorMixin_ 1
30 #include "../config.hh"
31 #include <boost/ptr_container/ptr_map.hpp>
32 #include <boost/ptr_container/ptr_vector.hpp>
33 #include <boost/mpl/if.hpp>
34 #include "Connectors.hh"
37 #include "MultiConnectorMixin.mpp"
38 #include "MultiConnectorMixin.ih"
39 ///////////////////////////////hh.p////////////////////////////////////////
41 #ifndef SENF_MULTI_CONNECTOR_MAX_ARGS
42 #define SENF_MULTI_CONNECTOR_MAX_ARGS 3
50 // For exposition only.
51 // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
52 // The real implementation includes a boost::enable_if condition in the return value, which is
53 // used to only enable the correct overload: The first overload, if the MultiConnector is an
54 // output, otherwise the second overload.
56 /** \brief Connect MultiConnector source to arbitrary target
58 Additional implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments.
60 \related module::MultiConnectorMixin
62 template <class MultiConnectorSource, class Target, class A1>
63 MultiConnectorSource::ConnectorType & connect(
64 MultiConnectorSource & source, Target & target, A1 const & a1);
66 /** \brief Connect arbitrary source to MultiConnector target
68 Additional implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments.
70 \related module::MultiConnectorMixin
72 template <class Source, class MultiConnectorTarget, class A1>
73 MultiConnectorTarget::ConnectorType & connect(
74 Source & source, MultiConnectorTarget & target, A1 const & a1);
78 // Include 'senf::ppi::namespace member declarations' from MultiConnectorMixin.mpp
79 # define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
81 SENF_MULTI_CONNECTOR_MAX_ARGS, \
82 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
84 # include BOOST_PP_ITERATE()
90 /** \brief Multi connector management
92 This mixin provides a module with support for a runtime configurable number of input or
96 : public senf::ppi::module::MultiConnectorMixin<
97 MyModule, senf::ppi::connector::ActiveInput<> >
99 SENF_PPI_MODULE(MyModule);
101 senf::ppi::connector::PassiveOutput<> output;
106 void connectorSetup(senf::ppi::connector::ActiveInput & input)
108 route(input, output);
109 input.onThrottle(&MyModule::doThrottle);
117 friend class senf::ppi::module::MultiConnectorMixin<
118 MyModule, senf::ppi::connector::ActiveInput<> >
122 Using the MultiConnectorMixin consists of
123 \li inheriting from MultiConnectorMixin
124 \li defining a function \c connectorSetup
125 \li declaring the mixin as a friend
127 The MultiConnectorMixin takes several template arguments
128 \li the name of the derived class, \a Self_
129 \li the type of connector, \a ConnectorType_
130 \li an optional \a KeyType_ if a mapping container is required
131 \li an optional \a ContainerType_ to replace the default \c boost::ptr_vector or \c
134 \section senf_ppi_multiconnector_sequence Sequence/vector based multi connector mixin
136 If no \a KeyType_ is given (or the \a KeyType_ is \c void), the mixin will use a sequence
137 container, by default a \c boost::ptr_vector to store the connectors. In this case, new
138 connectors will be added to the end of the container. The \c connectorSetup() routine
139 however may be used to move the inserted connector to some other location, e.g.
141 container().insert(begin(), container().pop_back().release());
143 which will move the new connector from the end to the beginning.
144 \warning If you throw an exception from \c connectorSetup(), you must do so \e before moving
145 the new connector around since the mixin will remove the last element from the container
148 \par "Example:" senf::ppi::module::PriorityJoin
150 \section senf_ppi_multiconnector_map Map based multi connector mixin
152 If \a KeyType_ is given (and is not \c void), the mixin will use a mapping container, by
153 default a \c boost::ptr_map to store the connectors. The \c connectorSetup() member function
154 must return the key value under which the new connector will be stored. The new connector
155 will this be written to the container only \e after \c connectorSetup() returns.
157 When the returned key is not unique, the new connector will \e replace the old one. If this
158 is not, what you want, either check for an already existing member and throw an exception in
159 \c connectorSetup() or replace the \c boost::ptr_map by a \c boost::ptr_multimap using the
160 fourth template argument to MultiConnectorMixin.
162 \par "Example:" senf::ppi::module::AnnotationRouter
164 \section senf_ppi_multiconnector_connect Connect and additional connectorSetup() arguments
166 When connecting to a module using the MultiConnectorMixin, every new connect call will
167 allocate a new connector
171 senf::ppi::connect(someModule, myModule);
173 Some modules will expect additional arguments to be passed (see below)
177 senf::ppi::connect(mod1, myModule); // index = 0, see below
178 senf::ppi::connect(mod2, myModule, 1); // index = 1, see below
180 To declare these additional arguments, just declare \c connectorSetup() with those
181 additional arguments:
183 void connectorSetup(MyModule::ConnectorType & input, int index=0)
185 container().insert(container().begin()+index, container().pop_back().release());
189 \par "Advanced note:" These additional arguments are always passed by const-reference. If
190 you need to pass a non-const reference, declare the \c connectorSetup() argument as
191 non-const reference and wrap the real argument using \c boost::ref() (The reason for
192 this is known as 'The forwarding problem'
194 template <class Self_,
195 class ConnectorType_,
197 class ContainerType_=typename detail::MultiConnectorDefaultContainer<
198 KeyType_,ConnectorType_>::type>
199 class MultiConnectorMixin
200 : private detail::MultiConnectorSelectBase<ConnectorType_>::type
203 typedef ConnectorType_ ConnectorType; ///< Type of MultiConnector connector
206 typedef ContainerType_ ContainerType; ///< Type of connector container
207 ContainerType_ & connectors(); ///< Get connector container
208 ContainerType_ const & connectors() const; ///< Get connectors container (const)
212 // For exposition only
213 // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
216 ConnectorType_ & newConnector(A1 const & a1);
218 // See above for an additional note regarding the boost::enable_if in the real
221 template <class Source, class Target, class A1>
222 friend Source::ConnectorType & senf::ppi::connect(Source & source,
226 template <class Source, class Target, class A1>
227 friend Target::ConnectorType & senf::ppi::connect(Source & source,
233 // Include 'MultiConnectorMixin member declaration' from MultiConnectorMixin.mpp
234 # define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
236 SENF_MULTI_CONNECTOR_MAX_ARGS, \
237 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
239 # include BOOST_PP_ITERATE()
243 ContainerType_ connectors_;
248 template <class Self_,
249 class ConnectorType_,
250 class ContainerType_>
251 class MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>
252 : private detail::MultiConnectorSelectBase<ConnectorType_>::type
255 typedef ConnectorType_ ConnectorType;
258 typedef ContainerType_ ContainerType;
259 ContainerType_ & connectors();
264 // For exposition only
265 // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
268 ConnectorType_ & newConnector(A1 const & a1);
270 // See above for an additional note regarding the boost::enable_if in the real
273 template <class Source, class Target, class A1>
274 friend Source::ConnectorType & senf::ppi::connect(Source & source,
278 template <class Source, class Target, class A1>
279 friend Target::ConnectorType & senf::ppi::connect(Source & source,
284 // Include 'MultiConnectorMixin member declaration' from MultiConnectorMixin.mpp
285 # define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
287 SENF_MULTI_CONNECTOR_MAX_ARGS, \
288 SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
290 # include BOOST_PP_ITERATE()
292 ContainerType_ connectors_;
299 ///////////////////////////////hh.e////////////////////////////////////////
300 //#include "MultiConnectorMixin.cci"
301 //#include "MultiConnectorMixin.ct"
302 #include "MultiConnectorMixin.cti"
309 // comment-column: 40
310 // c-file-style: "senf"
311 // indent-tabs-mode: nil
312 // ispell-local-dictionary: "american"
313 // compile-command: "scons -u test"