PPI: Add user container support to MultiConnectorMixin
[senf.git] / 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
39 // ///////////////////////////mpp.p////////////////////////////////////////
40 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
41 // ////////////////////////////////////////////////////////////////////////
42 // Local Macros
43
44 #define mpp_TplParams()                                                 \
45     BOOST_PP_IF(                                                        \
46         BOOST_PP_ITERATION(),                                           \
47         mpp_TplParams_,                                                 \
48         BOOST_PP_EMPTY)()
49 #define mpp_TplParams_()                                                \
50     template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
51     
52 #define mpp_TplParamsKomma()                                            \
53     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class A)
54 #define mpp_FnParams()                                                  \
55     BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
56 #define mpp_FnParamsKomma()                                             \
57     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, const & a)
58 #define mpp_CallParams()                                                \
59     BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a)
60 #define mpp_CallParamsKomma()                                           \
61     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)
62
63 // ////////////////////////////////////////////////////////////////////////
64 #if BOOST_PP_ITERATION_FLAGS()==1 // //////////////////////////////////////
65 // ////////////////////////////////////////////////////////////////////////
66 // MultiConnectorMixin member declaration
67
68 mpp_TplParams()
69 ConnectorType_ & newConnector( mpp_FnParams() );
70
71 template <class Source, class Target mpp_TplParamsKomma()>
72 friend typename boost::enable_if<
73         boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
74         typename Source::ConnectorType & >::type
75     senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma());
76
77 template <class Source, class Target mpp_TplParamsKomma()>
78 friend typename boost::enable_if<
79         boost::is_base_of<connector::InputConnector, typename Target::ConnectorType>,
80         typename Target::ConnectorType & >::type
81     senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma());
82
83 // ////////////////////////////////////////////////////////////////////////
84 #elif BOOST_PP_ITERATION_FLAGS()==2 // ////////////////////////////////////
85 // ////////////////////////////////////////////////////////////////////////
86 // senf::ppi namespace member declaration
87
88 template <class Source, class Target mpp_TplParamsKomma()>
89 typename boost::enable_if<
90     boost::is_base_of<connector::OutputConnector, typename Source::ConnectorType>,
91     typename Source::ConnectorType & >::type
92 connect(Source & source, Target & target mpp_FnParamsKomma());
93
94 template <class Source, class Target mpp_TplParamsKomma()>
95 typename boost::enable_if<
96     boost::is_base_of<connector::InputConnector, typename Target::ConnectorType>,
97     typename Target::ConnectorType & >::type
98 connect(Source & source, Target & target mpp_FnParamsKomma());
99
100 // ////////////////////////////////////////////////////////////////////////
101 #elif BOOST_PP_ITERATION_FLAGS()==3 // ////////////////////////////////////
102 // ////////////////////////////////////////////////////////////////////////
103 // Implementation
104
105 ////////////////////////////////////////
106 // Map container
107
108 template <class Self_, class ConnectorType_, class KeyType_, class ContainerType_>
109 mpp_TplParams()
110 prefix_ ConnectorType_ &
111 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,KeyType_,ContainerType_>::
112 newConnector(mpp_FnParams())
113 {
114     std::auto_ptr<ConnectorType_> conn (new ConnectorType_);
115     KeyType_ key (static_cast<Self_*>(this)->connectorSetup(*conn mpp_CallParamsKomma()));
116     return * connectors_.insert(key, conn).first->second;
117 }
118
119 ////////////////////////////////////////
120 // Vector container
121
122 template <class Self_, class ConnectorType_, class ContainerType_>
123 mpp_TplParams()
124 prefix_ ConnectorType_ &
125 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,ContainerType_>::
126 newConnector(mpp_FnParams())
127 {
128     connectors_.push_back(new ConnectorType_);
129     ConnectorType_ & conn (connectors_.back());
130     try { static_cast<Self_*>(this)->connectorSetup(conn mpp_CallParamsKomma()); }
131     catch (...) { connectors_.pop_back(); throw; }
132     return conn;
133 }
134
135 ////////////////////////////////////////
136 // User managed container
137
138 template <class Self_, class ConnectorType_>
139 mpp_TplParams()
140 prefix_ ConnectorType_ &
141 senf::ppi::module::MultiConnectorMixin<Self_,ConnectorType_,void,void>::
142 newConnector(mpp_FnParams())
143 {
144     std::auto_ptr<ConnectorType_> cp (new ConnectorType_);
145     ConnectorType_ & cref (*cp);
146     static_cast<Self_*>(this)->connectorSetup(cp mpp_CallParamsKomma());
147     return cref;
148 }
149
150 ////////////////////////////////////////
151 // senf::ppi::connect
152
153 template <class Source, class Target mpp_TplParamsKomma()>
154 typename boost::enable_if<
155     boost::is_base_of<senf::ppi::connector::OutputConnector, typename Source::ConnectorType>,
156     typename Source::ConnectorType & >::type
157 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
158 {
159     connect(source.newConnector(mpp_CallParams()), target);
160 }
161
162 template <class Source, class Target mpp_TplParamsKomma()>
163 typename boost::enable_if<
164     boost::is_base_of<senf::ppi::connector::InputConnector, typename Target::ConnectorType>,
165     typename Target::ConnectorType & >::type
166 senf::ppi::connect(Source & source, Target & target mpp_FnParamsKomma())
167 {
168     connect(source, target.newConnector(mpp_CallParams()));
169 }
170
171 // ////////////////////////////////////////////////////////////////////////
172 #endif // /////////////////////////////////////////////////////////////////
173 // ////////////////////////////////////////////////////////////////////////
174 // Undefine local Macros
175
176 #undef mpp_CallParamsKomma
177 #undef mpp_CallParams
178 #undef mpp_FnParamsKomma
179 #undef mpp_FnParams
180 #undef mpp_TplParamsKomma
181 #undef mpp_TplParams_
182 #undef mpp_TplParams
183             
184 // ////////////////////////////////////////////////////////////////////////
185 /*
186  (save-excursion (re-search-backward "^// Undefine local Macros")
187  (forward-line 1) (delete-region (point) (progn (search-forward
188  "// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
189  (e (progn (insert (save-excursion (re-search-backward 
190  "^// Local Macros") (search-forward "#define") (beginning-of-line)
191  (buffer-substring (point) (progn (search-forward "// ////")
192  (search-backward "#define") (forward-line 1) (point))))) (point))))
193  (reverse-region b e) (shell-command-on-region b e "grep -F '#define'" nil
194  t) (goto-char b) (while (looking-at "#define") (delete-char 7) (insert
195  "#undef") (skip-chars-forward " ") (re-search-forward "[^a-zA-Z_]")
196  (delete-region (1- (point)) (progn (end-of-line) (point))) (forward-line
197  1))))
198 */
199 // ////////////////////////////////////////////////////////////////////////
200 #endif // /////////////////////////////////////////////////////////////////
201 // ///////////////////////////mpp.e////////////////////////////////////////
202
203 \f
204 // Local Variables:
205 // mode: c++
206 // fill-column: 100
207 // comment-column: 40
208 // c-file-style: "senf"
209 // indent-tabs-mode: nil
210 // ispell-local-dictionary: "american"
211 // compile-command: "scons -u test"
212 // End: