Utils/Termlib: Extend the completion API
[senf.git] / PPI / Connectors.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
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 Connectors non-inline non-template implementation */
25
26 #include "Connectors.hh"
27 #include "Connectors.ih"
28
29 // Custom includes
30 #include "Route.hh"
31 #include "Module.hh"
32 #include "ModuleManager.hh"
33
34 //#include "Connectors.mpp"
35 #define prefix_
36 ///////////////////////////////cc.p////////////////////////////////////////
37
38 ///////////////////////////////////////////////////////////////////////////
39 // senf::ppi::connector::Connector
40
41 prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
42 {
43     // The connector is not registered -> route() or noroute() statement missing
44     SENF_ASSERT( module_ && 
45                  "senf::ppi::connector::Connector::connect(): (source) "
46                  "Missing route() or noroute()" );
47     // The connector is already connected
48     SENF_ASSERT( ! peer_ &&
49                  "senf::ppi::connector::Connector::connect(): (source) "
50                  "duplicate connection" );
51     // The target connector is not registered -> route() or noroute() statement missing
52     SENF_ASSERT( target.module_ &&
53                  "senf::ppi::connector::Connector::connect(): (target) "
54                  "Missing route() or noroute()" );
55     // The target connector is already connected
56     SENF_ASSERT( ! target.peer_ &&
57                  "senf::ppi::connector::Connector::connect(): (target) "
58                  "duplicate connection" );
59     if (! (packetTypeID() == typeid(void) ||
60            target.packetTypeID() == typeid(void) || 
61            packetTypeID() == target.packetTypeID()) )
62         throw IncompatibleConnectorsException() 
63             << ": " << prettyName(packetTypeID()) 
64             << " [in module " << prettyName(typeid(*module_))  << "] "
65             << ", " << prettyName(target.packetTypeID())
66             << " [in module " << prettyName(typeid(*target.module_)) << "]";
67             
68     peer_ = & target;
69     target.peer_ = this;
70
71     if (! initializationScheduled())
72         enqueueInitializable();
73     if (! peer().initializationScheduled())
74         peer().enqueueInitializable();
75 }
76
77 prefix_ void senf::ppi::connector::Connector::disconnect()
78 {
79     // Cannot disconnected a non-connected connector
80     SENF_ASSERT( peer_ &&
81                  "senf::ppi::connector::Connector::disconnect(): Not connected" );
82     Connector & peer (*peer_);
83     peer_ = 0;
84     peer.peer_ = 0;
85
86     if (! initializationScheduled())
87         enqueueInitializable();
88     if (! peer.initializationScheduled())
89         peer.enqueueInitializable();
90 }
91
92 prefix_ std::type_info const & senf::ppi::connector::Connector::packetTypeID()
93 {
94     return typeid(void);
95 }
96
97 ///////////////////////////////////////////////////////////////////////////
98 // senf::ppi::connector::PassiveConnector
99
100 ////////////////////////////////////////
101 // private members
102
103 prefix_ void senf::ppi::connector::PassiveConnector::v_init()
104 {
105     Routes::const_iterator i (routes_.begin());
106     Routes::const_iterator const i_end (routes_.end());
107     for (; i != i_end; ++i)
108         if ((*i)->throttled())
109             break;
110     if (i == i_end)
111         remoteThrottled_ = false;
112     if (throttled())
113         emitThrottle();
114     else
115         emitUnthrottle();
116 }
117
118 prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent()
119 {}
120
121 prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
122 {
123     if (throttled() && !nativeThrottled_) {
124         Routes::const_iterator i (routes_.begin());
125         Routes::const_iterator const i_end (routes_.end());
126         for (; i != i_end; ++i)
127             if ((*i)->throttled())
128                 break;
129         if (i == i_end) {
130             remoteThrottled_ = false;
131             emitUnthrottle();
132         }
133     } 
134     else
135         remoteThrottled_ = false;
136 }
137
138 ///////////////////////////////////////////////////////////////////////////
139 // senf::ppi::connector::ActiveConnector
140
141 ////////////////////////////////////////
142 // private members
143
144 prefix_ void senf::ppi::connector::ActiveConnector::v_init()
145 {
146     if (! connected())
147         notifyThrottle();
148 }
149
150 prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle()
151 {
152     if (! throttled_) {
153         throttled_ = true;
154         if (throttleCallback_)
155             throttleCallback_();
156         NotifyRoutes::const_iterator i (notifyRoutes_.begin());
157         NotifyRoutes::const_iterator const i_end (notifyRoutes_.end());
158         for (; i != i_end; ++i)
159             (*i)->notifyThrottle();
160     }
161 }
162
163 prefix_ void senf::ppi::connector::ActiveConnector::notifyUnthrottle()
164 {
165     if (throttled_) {
166         throttled_ = false;
167         if (unthrottleCallback_)
168             unthrottleCallback_();
169         NotifyRoutes::const_iterator i (notifyRoutes_.begin());
170         NotifyRoutes::const_iterator const i_end (notifyRoutes_.end());
171         for (; i != i_end; ++i)
172             (*i)->notifyUnthrottle();
173     }
174 }
175
176 prefix_ void senf::ppi::connector::ActiveConnector::registerRoute(ForwardingRoute & route)
177 {
178     notifyRoutes_.push_back(&route);
179 }
180
181 ///////////////////////////////////////////////////////////////////////////
182 // senf::ppi::connector::InputConnector
183
184 prefix_ senf::Packet senf::ppi::connector::InputConnector::operator()()
185 {
186     if (empty())
187         v_requestEvent();
188     Packet p;
189     if (! empty()) {
190         p = peek();
191         queue_.pop_back();
192         v_dequeueEvent();
193     }
194     return p;
195 }
196
197 ////////////////////////////////////////
198 // private members
199
200 prefix_ void senf::ppi::connector::InputConnector::v_requestEvent()
201 {}
202
203 prefix_ void senf::ppi::connector::InputConnector::v_enqueueEvent()
204 {}
205
206 prefix_ void senf::ppi::connector::InputConnector::v_dequeueEvent()
207 {}
208
209 ///////////////////////////////////////////////////////////////////////////
210 // senf::ppi::connector::GenericActiveInput
211
212 ////////////////////////////////////////
213 // private members
214
215 prefix_ void senf::ppi::connector::GenericActiveInput::v_requestEvent()
216 {
217     request();
218 }
219
220 ///////////////////////////////////////////////////////////////////////////
221 // senf::ppi::connector::GenericPassiveInput
222
223 ////////////////////////////////////////
224 // private members 
225
226 prefix_ void senf::ppi::connector::GenericPassiveInput::v_enqueueEvent()
227 {
228     emit();
229     qdisc_->update(*this, QueueingDiscipline::ENQUEUE);
230 }
231
232 prefix_ void senf::ppi::connector::GenericPassiveInput::v_dequeueEvent()
233 {
234     qdisc_->update(*this, QueueingDiscipline::DEQUEUE);
235 }
236
237 prefix_ void senf::ppi::connector::GenericPassiveInput::v_unthrottleEvent()
238 {
239     size_type n (queueSize());
240     while (n) {
241         emit();
242         size_type nn (queueSize());
243         if (n == nn)
244             break;
245         n = nn;
246     }
247 }
248
249 ///////////////////////////////cc.e////////////////////////////////////////
250 #undef prefix_
251 //#include "Connectors.mpp"
252
253 \f
254 // Local Variables:
255 // mode: c++
256 // fill-column: 100
257 // comment-column: 40
258 // c-file-style: "senf"
259 // indent-tabs-mode: nil
260 // ispell-local-dictionary: "american"
261 // compile-command: "scons -u test"
262 // End: