986a2a4f8fb5f4be96366c7c85c3debf14532b19
[senf.git] / senf / PPI / Connectors.cci
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 inline non-template implementation */
25
26 // Custom includes
27 #include <senf/Utils/TypeInfo.hh>
28 #include <senf/Utils/senfassert.hh>
29 #include "Module.hh"
30
31 #define prefix_ inline
32 ///////////////////////////////cci.p///////////////////////////////////////
33
34 ///////////////////////////////////////////////////////////////////////////
35 // senf::ppi::connector::Connector
36
37 prefix_ senf::ppi::connector::Connector & senf::ppi::connector::Connector::peer()
38     const
39 {
40     // The connector is not connected
41     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
42     return *peer_;
43 }
44
45 prefix_ senf::ppi::module::Module & senf::ppi::connector::Connector::module()
46     const
47 {
48     // The connector is not registered in the module -> probably a route() or noroute() statement is
49     // missing.
50     SENF_ASSERT(module_, "Connector not registered: Missing route() or noroute()");
51     return *module_;
52 }
53
54 prefix_ void senf::ppi::connector::Connector::tracing(TraceState state)
55 {
56     traceState_ = state;
57 }
58
59 prefix_ senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::tracing()
60 {
61     return traceState_;
62 }
63
64 ////////////////////////////////////////
65 // protected members
66
67 prefix_ senf::ppi::connector::Connector::Connector()
68     : peer_(), module_()
69 {}
70
71 prefix_ senf::ppi::connector::Connector::~Connector()
72 {
73     if (connected()) {
74         Connector & peer (*peer_);
75         peer_->peer_ = 0;
76         if (! peer.initializationScheduled())
77             peer.enqueueInitializable();
78         peer.v_disconnected();
79     }
80 }
81
82 prefix_ bool senf::ppi::connector::Connector::connected()
83     const
84 {
85     return peer_;
86 }
87
88 prefix_ void senf::ppi::connector::Connector::unregisterConnector()
89 {
90     if (module_)
91         module_->unregisterConnector(*this);
92 }
93
94 ////////////////////////////////////////
95 // private members
96
97 prefix_ void senf::ppi::connector::Connector::setModule(module::Module & module)
98 {
99     module_ = &module;
100 }
101
102 ///////////////////////////////////////////////////////////////////////////
103 // senf::ppi::connector::PassiveConnector
104
105 prefix_ senf::ppi::connector::ActiveConnector & senf::ppi::connector::PassiveConnector::peer()
106     const
107 {
108     return dynamic_cast<ActiveConnector&>(Connector::peer());
109 }
110
111 prefix_ bool senf::ppi::connector::PassiveConnector::throttled()
112     const
113 {
114     return nativeThrottled_ || remoteThrottled_;
115 }
116
117 ////////////////////////////////////////
118 // private members
119
120 prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle()
121 {
122     throttleTrace("OUT", "throttle");
123     if (connected())
124         peer().notifyThrottle();
125 }
126
127 prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle()
128 {
129     throttleTrace("OUT", "unthrottle");
130     if (connected()) {
131         peer().notifyUnthrottle();
132         v_unthrottleEvent();
133     }
134 }
135
136 prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle()
137 {
138     if (!throttled()) {
139         remoteThrottled_ = true;
140         emitThrottle();
141     }
142     else
143         remoteThrottled_ = true;
144 }
145
146 prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRoute & route)
147 {
148     routes_.push_back(&route);
149 }
150
151 prefix_ void senf::ppi::connector::PassiveConnector::unregisterRoute(ForwardingRoute & route)
152 {
153     Routes::iterator i (std::find(routes_.begin(), routes_.end(), &route));
154     if (i != routes_.end())
155         routes_.erase(i);
156 }
157
158 // public members
159
160 prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
161     const
162 {
163     return nativeThrottled_;
164 }
165
166 prefix_ void senf::ppi::connector::PassiveConnector::throttle()
167 {
168     if (!throttled()) {
169         nativeThrottled_ = true;
170         emitThrottle();
171     } else
172         nativeThrottled_ = true;
173 }
174
175 prefix_ void senf::ppi::connector::PassiveConnector::unthrottle()
176 {
177     if (throttled() && ! remoteThrottled_) {
178         nativeThrottled_ = false;
179         emitUnthrottle();
180     } else
181         nativeThrottled_ = false;
182
183 }
184
185 ////////////////////////////////////////
186 // protected members
187
188 prefix_ senf::ppi::connector::PassiveConnector::PassiveConnector()
189     : callback_(), remoteThrottled_(), nativeThrottled_()
190 {}
191
192 prefix_ void senf::ppi::connector::PassiveConnector::emit()
193 {
194     // No event callback has been registered (onRequest() call missing)
195     SENF_ASSERT(callback_, "senf::ppi::connector::PassiveConnector: missing onRequest()");
196     if (!throttled())
197         callback_();
198     else
199         throttleTrace("IN ", "queueing packet");
200 }
201
202 ///////////////////////////////////////////////////////////////////////////
203 // senf::ppi::connector::ActiveConnector
204
205 prefix_ senf::ppi::connector::PassiveConnector & senf::ppi::connector::ActiveConnector::peer()
206     const
207 {
208     return dynamic_cast<PassiveConnector&>(Connector::peer());
209 }
210
211 prefix_ void senf::ppi::connector::ActiveConnector::onThrottle()
212 {
213     throttleCallback_ = Callback();
214 }
215
216 prefix_ void senf::ppi::connector::ActiveConnector::onUnthrottle()
217 {
218     unthrottleCallback_ = Callback();
219 }
220
221 prefix_ bool senf::ppi::connector::ActiveConnector::throttled()
222     const
223 {
224     return ! connected() || peer().throttled();
225 }
226
227 ////////////////////////////////////////
228 // protected members
229
230 prefix_ senf::ppi::connector::ActiveConnector::ActiveConnector()
231     : throttleCallback_(), unthrottleCallback_(), notifyRoutes_(), throttled_(false)
232 {}
233
234 ///////////////////////////////////////////////////////////////////////////
235 // senf::ppi::connector::InputConnector
236
237 prefix_ senf::Packet senf::ppi::connector::InputConnector::read()
238 {
239     return operator()();
240 }
241
242 prefix_ senf::ppi::connector::OutputConnector & senf::ppi::connector::InputConnector::peer()
243     const
244 {
245     return dynamic_cast<OutputConnector &>(Connector::peer());
246 }
247
248 prefix_ senf::ppi::connector::InputConnector::queue_iterator
249 senf::ppi::connector::InputConnector::begin()
250     const
251 {
252     return queue_.begin();
253 }
254
255 prefix_ senf::ppi::connector::InputConnector::queue_iterator
256 senf::ppi::connector::InputConnector::end()
257     const
258 {
259     return queue_.end();
260 }
261
262 prefix_ senf::Packet senf::ppi::connector::InputConnector::peek()
263     const
264 {
265     // Cannot peek() head of empty queue
266     SENF_ASSERT( ! queue_.empty(),
267                  "senf::ppi::connector::InputConnector: cannot call peek() on empty queue" );
268     return queue_.back();
269 }
270
271 prefix_ senf::ppi::connector::InputConnector::size_type
272 senf::ppi::connector::InputConnector::queueSize()
273     const
274 {
275     return queue_.size();
276 }
277
278 prefix_ bool senf::ppi::connector::InputConnector::empty()
279     const
280 {
281     return queue_.empty();
282 }
283
284 ////////////////////////////////////////
285 // protected members
286
287 prefix_ senf::ppi::connector::InputConnector::InputConnector()
288 {}
289
290 ////////////////////////////////////////
291 // private members
292
293 prefix_ void senf::ppi::connector::InputConnector::enqueue(Packet const & p)
294 {
295     queue_.push_front(p);
296     v_enqueueEvent();
297 }
298
299 ///////////////////////////////////////////////////////////////////////////
300 // senf::ppi::connector::OutputConnector
301
302 prefix_ senf::ppi::connector::InputConnector & senf::ppi::connector::OutputConnector::peer()
303     const
304 {
305     return dynamic_cast<InputConnector&>(Connector::peer());
306 }
307
308 prefix_ void senf::ppi::connector::OutputConnector::operator()(Packet const & p)
309 {
310     trace(p, "OUT");
311     if (connected())
312         peer().enqueue(p);
313 }
314
315 prefix_ void senf::ppi::connector::OutputConnector::write(Packet const & p)
316 {
317     operator()(p);
318 }
319
320 ////////////////////////////////////////
321 // protected members
322
323 prefix_ senf::ppi::connector::OutputConnector::OutputConnector()
324 {}
325
326 ///////////////////////////////////////////////////////////////////////////
327 // senf::ppi::connector::GenericPassiveInput
328
329 prefix_ senf::ppi::connector::GenericPassiveInput::GenericPassiveInput()
330     : qdisc_(new ThresholdQueueing(1,0))
331 {}
332
333 prefix_ senf::ppi::connector::GenericActiveOutput & senf::ppi::connector::GenericPassiveInput::peer()
334     const
335 {
336     return dynamic_cast<GenericActiveOutput&>(Connector::peer());
337 }
338
339 prefix_ bool senf::ppi::connector::GenericPassiveInput::boolean_test()
340     const
341 {
342     return ! empty();
343 }
344
345 ///////////////////////////////////////////////////////////////////////////
346 // senf::ppi::connector::GenericPassiveOutput
347
348 prefix_ senf::ppi::connector::GenericActiveInput & senf::ppi::connector::GenericPassiveOutput::peer()
349     const
350 {
351     return dynamic_cast<GenericActiveInput&>(Connector::peer());
352 }
353
354 prefix_ bool senf::ppi::connector::GenericPassiveOutput::boolean_test()
355     const
356 {
357     return  true;
358 }
359
360 prefix_ void senf::ppi::connector::GenericPassiveOutput::connect(GenericActiveInput & target)
361 {
362     Connector::connect(target);
363 }
364
365 prefix_ senf::ppi::connector::GenericPassiveOutput::GenericPassiveOutput()
366 {}
367
368 ///////////////////////////////////////////////////////////////////////////
369 // senf::ppi::connector::GenericActiveInput
370
371 prefix_ senf::ppi::connector::GenericPassiveOutput & senf::ppi::connector::GenericActiveInput::peer()
372     const
373 {
374     return dynamic_cast<GenericPassiveOutput&>(Connector::peer());
375 }
376
377 prefix_ bool senf::ppi::connector::GenericActiveInput::boolean_test()
378     const
379 {
380     return ! empty() || (connected() && ! peer().throttled());
381 }
382
383 prefix_ void senf::ppi::connector::GenericActiveInput::request()
384 {
385     if (connected())
386         peer().emit();
387 }
388
389 prefix_ senf::ppi::connector::GenericActiveInput::GenericActiveInput()
390 {}
391
392 ///////////////////////////////////////////////////////////////////////////
393 // senf::ppi::connector::GenericActiveOutput
394
395 prefix_ senf::ppi::connector::GenericPassiveInput & senf::ppi::connector::GenericActiveOutput::peer()
396     const
397 {
398     return dynamic_cast<GenericPassiveInput&>(Connector::peer());
399 }
400
401 prefix_ bool senf::ppi::connector::GenericActiveOutput::boolean_test()
402     const
403 {
404     return connected() && ! peer().throttled();
405 }
406
407 prefix_ void senf::ppi::connector::GenericActiveOutput::connect(GenericPassiveInput & target)
408 {
409     Connector::connect(target);
410 }
411
412 prefix_ senf::ppi::connector::GenericActiveOutput::GenericActiveOutput()
413 {}
414
415 ///////////////////////////////cci.e///////////////////////////////////////
416 #undef prefix_
417
418 \f
419 // Local Variables:
420 // mode: c++
421 // fill-column: 100
422 // comment-column: 40
423 // c-file-style: "senf"
424 // indent-tabs-mode: nil
425 // ispell-local-dictionary: "american"
426 // compile-command: "scons -u test"
427 // End: