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