PPI: Implement DynamicConnectorMixin
[senf.git] / PPI / DynamicConnectorMixin.hh
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 DynamicConnectorMixin public header */
25
26 #ifndef HH_SENF_PPI_DynamicConnectorMixin_
27 #define HH_SENF_PPI_DynamicConnectorMixin_ 1
28
29 // Custom includes
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"
35 #include "Setup.hh"
36
37 #include "DynamicConnectorMixin.mpp"
38 ///////////////////////////////hh.p////////////////////////////////////////
39
40 #ifndef SENF_DYNAMIC_CONNECTOR_MAX_ARGS
41 #define SENF_DYNAMIC_CONNECTOR_MAX_ARGS 3
42 #endif
43
44 namespace senf {
45 namespace ppi {
46
47 #   define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
48             0, \
49             SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \
50             SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \
51             2 ))
52 #   include BOOST_PP_ITERATE()
53
54 namespace module {
55
56 namespace detail {
57     template <class KeyType, class ConnectorType>
58     struct DefaultDynamicContainer 
59     { typedef boost::ptr_map<KeyType, ConnectorType> type; };
60
61     template <class ConnectorType>
62     struct DefaultDynamicContainer<void,ConnectorType> 
63     { typedef boost::ptr_vector<ConnectorType> type; };
64
65     template <class ConnectorType>
66     struct DynamicDisableType
67         : public boost::mpl::if_< 
68               boost::is_base_of<connector::InputConnector, ConnectorType>,
69               ppi::detail::DisableStandardInput, ppi::detail::DisableStandardOutput >
70     {};
71 }
72
73     /** \brief Dynamic connector management
74
75         Provide modules with support for dynamic connectors.
76
77         \li A module might have dynamic input or output connectors
78         \li Creating a new connection might take an argument
79         \li Connectors are stored either in a vector or a map
80         
81         Workflow:
82         \li Connectors are created by the helper.
83         \li Connector is passed to Self::connectorSetup. This returns either void or the map
84             key. connectorSetup must setup internal routing and callbacks.
85         \li Connector inserted into container.
86
87         connectorSetup may take additional arguments besides reference to connector. These arguments
88         are taken from the trailing ppi::connect call arguments.
89
90         The list manager will insert the new connector at the end of the list BEFORE calling
91         connetorSetup. This allows the setup routine to manipulate the position.
92      */
93     template <class Self, 
94               class ConnectorType, 
95               class KeyType=void, 
96               class ContainerType=typename detail::DefaultDynamicContainer<
97                                                KeyType,ConnectorType>::type>
98     class DynamicConnectorMixin 
99         : private detail::DynamicDisableType<ConnectorType>::type
100     {
101     public:
102         typedef ConnectorType DynamicConnector;
103
104     protected:
105         typedef ContainerType DynamicConnectorContainer;
106         ContainerType & connectors();
107
108     private:
109 #       define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
110             0, \
111             SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \
112             SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \
113             1 ))
114 #       include BOOST_PP_ITERATE()
115         
116         ContainerType connectors_;
117     };
118
119     template <class Self,
120               class ConnectorType,
121               class ContainerType>
122     class DynamicConnectorMixin<Self, ConnectorType, void, ContainerType>
123         : private detail::DynamicDisableType<ConnectorType>::type
124     {
125     public:
126         typedef ConnectorType DynamicConnector;
127         
128     protected:
129         typedef ContainerType ConnectorContainer;
130         ContainerType & connectors();
131
132     private:
133 #       define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
134             0, \
135             SENF_DYNAMIC_CONNECTOR_MAX_ARGS, \
136             SENF_ABSOLUTE_INCLUDE_PATH(PPI/DynamicConnectorMixin.mpp), \
137             1 ))
138 #       include BOOST_PP_ITERATE()
139         
140         ContainerType connectors_;
141     };
142         
143 }}}
144
145 ///////////////////////////////hh.e////////////////////////////////////////
146 //#include "DynamicConnectorMixin.cci"
147 //#include "DynamicConnectorMixin.ct"
148 #include "DynamicConnectorMixin.cti"
149 #endif
150
151 \f
152 // Local Variables:
153 // mode: c++
154 // fill-column: 100
155 // comment-column: 40
156 // c-file-style: "senf"
157 // indent-tabs-mode: nil
158 // ispell-local-dictionary: "american"
159 // compile-command: "scons -u test"
160 // End: