PPI: optimized internal connector packet handling (queuing only if necessary, pass...
[senf.git] / senf / PPI / Connectors.cci
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Connectors inline non-template implementation */
30
31 // Custom includes
32 #include <senf/Utils/TypeInfo.hh>
33 #include <senf/Utils/senfassert.hh>
34 #include "Module.hh"
35
36 #define prefix_ inline
37 //-/////////////////////////////////////////////////////////////////////////////////////////////////
38
39 #ifdef SENF_PPI_NOTRACE
40 #   define SENF_PPI_THROTTLE_TRACE(label, type)
41 #   define SENF_PPI_TRACE(packet, label)
42 #else
43 #   define SENF_PPI_THROTTLE_TRACE(label, type) throttleTrace(label, type)
44 #   define SENF_PPI_TRACE(packet, label) trace(packet, label)
45 #endif
46
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48 // senf::ppi::connector::Connector
49
50 prefix_ senf::ppi::connector::Connector & senf::ppi::connector::Connector::peer()
51     const
52 {
53     // The connector is not connected
54     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
55     return *peer_;
56 }
57
58 prefix_ senf::ppi::module::Module & senf::ppi::connector::Connector::module()
59     const
60 {
61     // The connector is not registered in the module -> probably a route() or noroute() statement is
62     // missing.
63     SENF_ASSERT(module_, "Connector not registered: Missing route() or noroute()");
64     return *module_;
65 }
66
67 prefix_ void senf::ppi::connector::Connector::tracing(TraceState state)
68 {
69     traceState_ = state;
70 }
71
72 prefix_ senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::tracing()
73 {
74     return traceState_;
75 }
76
77 //-/////////////////////////////////////////////////////////////////////////////////////////////////
78 // protected members
79
80 prefix_ senf::ppi::connector::Connector::Connector()
81     : peer_(), module_()
82 {}
83
84 prefix_ bool senf::ppi::connector::Connector::connected()
85     const
86 {
87     return peer_;
88 }
89
90 //-/////////////////////////////////////////////////////////////////////////////////////////////////
91 // senf::ppi::connector::PassiveConnector
92
93 prefix_ senf::ppi::connector::ActiveConnector & senf::ppi::connector::PassiveConnector::peer()
94     const
95 {
96     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
97     return *peer_;
98 }
99
100 prefix_ bool senf::ppi::connector::PassiveConnector::throttled()
101     const
102 {
103     return nativeThrottled_ || remoteThrottled_;
104 }
105
106 //-/////////////////////////////////////////////////////////////////////////////////////////////////
107 // private members
108
109 prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle()
110 {
111     SENF_PPI_THROTTLE_TRACE("OUT", "throttle");
112     if (connected())
113         peer().notifyThrottle();
114 }
115
116 prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle()
117 {
118     SENF_PPI_THROTTLE_TRACE("OUT", "unthrottle");
119     if (connected()) {
120         peer().notifyUnthrottle();
121         v_unthrottleEvent();
122     }
123 }
124
125 prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle()
126 {
127     if (!throttled()) {
128         remoteThrottled_ = true;
129         emitThrottle();
130     }
131     else
132         remoteThrottled_ = true;
133 }
134
135 // public members
136
137 prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
138     const
139 {
140     return nativeThrottled_;
141 }
142
143 prefix_ void senf::ppi::connector::PassiveConnector::throttle()
144 {
145     if (!throttled()) {
146         nativeThrottled_ = true;
147         emitThrottle();
148     } else
149         nativeThrottled_ = true;
150 }
151
152 prefix_ void senf::ppi::connector::PassiveConnector::unthrottle()
153 {
154     if (throttled() && ! remoteThrottled_) {
155         nativeThrottled_ = false;
156         emitUnthrottle();
157     } else
158         nativeThrottled_ = false;
159
160 }
161
162 //-/////////////////////////////////////////////////////////////////////////////////////////////////
163 // protected members
164
165 prefix_ senf::ppi::connector::PassiveConnector::PassiveConnector()
166     : callback_(), remoteThrottled_(), nativeThrottled_()
167 {}
168
169 prefix_ void senf::ppi::connector::PassiveConnector::emit()
170 {
171     // No event callback has been registered (onRequest() call missing)
172     SENF_ASSERT(callback_, "senf::ppi::connector::PassiveConnector: missing onRequest()");
173     if (!throttled()) {
174         callback_();
175     } else {
176         SENF_PPI_THROTTLE_TRACE("IN ", "queueing packet");
177     }
178 }
179
180 //-/////////////////////////////////////////////////////////////////////////////////////////////////
181 // senf::ppi::connector::ActiveConnector
182
183 prefix_ senf::ppi::connector::PassiveConnector & senf::ppi::connector::ActiveConnector::peer()
184     const
185 {
186     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
187     return *peer_;
188 }
189
190 prefix_ void senf::ppi::connector::ActiveConnector::onThrottle()
191 {
192     throttleCallback_ = Callback();
193 }
194
195 prefix_ void senf::ppi::connector::ActiveConnector::onUnthrottle()
196 {
197     unthrottleCallback_ = Callback();
198 }
199
200 prefix_ bool senf::ppi::connector::ActiveConnector::throttled()
201     const
202 {
203     return ! connected() || peer().throttled();
204 }
205
206 //-/////////////////////////////////////////////////////////////////////////////////////////////////
207 // protected members
208
209 prefix_ senf::ppi::connector::ActiveConnector::ActiveConnector()
210     : throttleCallback_(), unthrottleCallback_(), notifyRoutes_(), throttled_(false)
211 {}
212
213 //-/////////////////////////////////////////////////////////////////////////////////////////////////
214 // senf::ppi::connector::InputConnector
215
216 prefix_ senf::Packet const & senf::ppi::connector::InputConnector::read()
217 {
218     return operator()();
219 }
220
221 prefix_ senf::ppi::connector::OutputConnector & senf::ppi::connector::InputConnector::peer()
222     const
223 {
224     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
225     return *peer_;
226 }
227
228 prefix_ senf::ppi::connector::InputConnector::size_type
229 senf::ppi::connector::InputConnector::queueSize()
230     const
231 {
232     return queue_.size() + (fastPacket_ ? 1 : 0);
233 }
234
235 prefix_ bool senf::ppi::connector::InputConnector::empty()
236     const
237 {
238     return fastPacket_ == NULL && queue_.empty();
239 }
240
241 //-/////////////////////////////////////////////////////////////////////////////////////////////////
242 // protected members
243
244 prefix_ senf::ppi::connector::InputConnector::InputConnector()
245     : fastPacket_(NULL)
246 {}
247
248 //-/////////////////////////////////////////////////////////////////////////////////////////////////
249 // private members
250
251 prefix_ void senf::ppi::connector::InputConnector::enqueue(Packet const & p)
252 {
253     if (queue_.empty()) {
254         fastPacket_ = &p;
255         try {
256             v_enqueueEvent();
257         } catch (Exception & e) {
258             queue_.push_front(p);
259             throw e;
260         }
261         if (fastPacket_) {
262             queue_.push_front(p);
263             fastPacket_ = NULL;
264         }
265     } else {
266         queue_.push_front(p);
267         v_enqueueEvent();
268     }
269 }
270
271 //-/////////////////////////////////////////////////////////////////////////////////////////////////
272 // senf::ppi::connector::OutputConnector
273
274 prefix_ senf::ppi::connector::InputConnector & senf::ppi::connector::OutputConnector::peer()
275     const
276 {
277     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
278     return *peer_;
279 }
280
281 prefix_ void senf::ppi::connector::OutputConnector::operator()(Packet const & p)
282 {
283     SENF_PPI_TRACE(p, "OUT");
284     if (connected())
285         peer().enqueue(p);
286 }
287
288 prefix_ void senf::ppi::connector::OutputConnector::write(Packet const & p)
289 {
290     operator()(p);
291 }
292
293 //-/////////////////////////////////////////////////////////////////////////////////////////////////
294 // protected members
295
296 prefix_ senf::ppi::connector::OutputConnector::OutputConnector()
297 {}
298
299 //-/////////////////////////////////////////////////////////////////////////////////////////////////
300 // senf::ppi::connector::GenericPassiveInput
301
302 prefix_ senf::ppi::connector::GenericPassiveInput::GenericPassiveInput()
303     : qdisc_(new ThresholdQueueing(1,0))
304 {}
305
306 prefix_ senf::ppi::connector::GenericActiveOutput & senf::ppi::connector::GenericPassiveInput::peer()
307     const
308 {
309     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
310     return *peer_;
311 }
312
313 prefix_ bool senf::ppi::connector::GenericPassiveInput::boolean_test()
314     const
315 {
316     return ! empty();
317 }
318
319 //-/////////////////////////////////////////////////////////////////////////////////////////////////
320 // senf::ppi::connector::GenericPassiveOutput
321
322 prefix_ senf::ppi::connector::GenericActiveInput & senf::ppi::connector::GenericPassiveOutput::peer()
323     const
324 {
325     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
326     return *peer_;
327 }
328
329 prefix_ bool senf::ppi::connector::GenericPassiveOutput::boolean_test()
330     const
331 {
332     return  true;
333 }
334
335 prefix_ void senf::ppi::connector::GenericPassiveOutput::connect(GenericActiveInput & target)
336 {
337     Connector::connect(target);
338 }
339
340 prefix_ senf::ppi::connector::GenericPassiveOutput::GenericPassiveOutput()
341 {}
342
343 //-/////////////////////////////////////////////////////////////////////////////////////////////////
344 // senf::ppi::connector::GenericActiveInput
345
346 prefix_ senf::ppi::connector::GenericPassiveOutput & senf::ppi::connector::GenericActiveInput::peer()
347     const
348 {
349     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
350     return *peer_;
351 }
352
353 prefix_ bool senf::ppi::connector::GenericActiveInput::boolean_test()
354     const
355 {
356     return ! empty() || (connected() && ! peer().throttled());
357 }
358
359 prefix_ void senf::ppi::connector::GenericActiveInput::request()
360 {
361     if (connected())
362         peer().emit();
363 }
364
365 prefix_ senf::ppi::connector::GenericActiveInput::GenericActiveInput()
366 {}
367
368 //-/////////////////////////////////////////////////////////////////////////////////////////////////
369 // senf::ppi::connector::GenericActiveOutput
370
371 prefix_ senf::ppi::connector::GenericPassiveInput & senf::ppi::connector::GenericActiveOutput::peer()
372     const
373 {
374     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
375     return *peer_;
376 }
377
378 prefix_ bool senf::ppi::connector::GenericActiveOutput::boolean_test()
379     const
380 {
381     return connected() && ! peer().throttled();
382 }
383
384 prefix_ void senf::ppi::connector::GenericActiveOutput::connect(GenericPassiveInput & target)
385 {
386     Connector::connect(target);
387 }
388
389 prefix_ senf::ppi::connector::GenericActiveOutput::GenericActiveOutput()
390 {}
391
392 //-/////////////////////////////////////////////////////////////////////////////////////////////////
393 #undef prefix_
394
395 \f
396 // Local Variables:
397 // mode: c++
398 // fill-column: 100
399 // comment-column: 40
400 // c-file-style: "senf"
401 // indent-tabs-mode: nil
402 // ispell-local-dictionary: "american"
403 // compile-command: "scons -u test"
404 // End: