d3244925f8f6eea91c86ef15549c77fe0513f4c2
[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_ bool senf::ppi::connector::Connector::connected()
80     const
81 {
82     return peer_;
83 }
84
85 ///////////////////////////////////////////////////////////////////////////
86 // senf::ppi::connector::PassiveConnector
87
88 prefix_ senf::ppi::connector::ActiveConnector & senf::ppi::connector::PassiveConnector::peer()
89     const
90 {
91     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
92     return *peer_;
93 }
94
95 prefix_ bool senf::ppi::connector::PassiveConnector::throttled()
96     const
97 {
98     return nativeThrottled_ || remoteThrottled_;
99 }
100
101 ////////////////////////////////////////
102 // private members
103
104 prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle()
105 {
106     SENF_PPI_THROTTLE_TRACE("OUT", "throttle");
107     if (connected())
108         peer().notifyThrottle();
109 }
110
111 prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle()
112 {
113     SENF_PPI_THROTTLE_TRACE("OUT", "unthrottle");
114     if (connected()) {
115         peer().notifyUnthrottle();
116         v_unthrottleEvent();
117     }
118 }
119
120 prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle()
121 {
122     if (!throttled()) {
123         remoteThrottled_ = true;
124         emitThrottle();
125     }
126     else
127         remoteThrottled_ = true;
128 }
129
130 // public members
131
132 prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
133     const
134 {
135     return nativeThrottled_;
136 }
137
138 prefix_ void senf::ppi::connector::PassiveConnector::throttle()
139 {
140     if (!throttled()) {
141         nativeThrottled_ = true;
142         emitThrottle();
143     } else
144         nativeThrottled_ = true;
145 }
146
147 prefix_ void senf::ppi::connector::PassiveConnector::unthrottle()
148 {
149     if (throttled() && ! remoteThrottled_) {
150         nativeThrottled_ = false;
151         emitUnthrottle();
152     } else
153         nativeThrottled_ = false;
154
155 }
156
157 ////////////////////////////////////////
158 // protected members
159
160 prefix_ senf::ppi::connector::PassiveConnector::PassiveConnector()
161     : callback_(), remoteThrottled_(), nativeThrottled_()
162 {}
163
164 prefix_ void senf::ppi::connector::PassiveConnector::emit()
165 {
166     // No event callback has been registered (onRequest() call missing)
167     SENF_ASSERT(callback_, "senf::ppi::connector::PassiveConnector: missing onRequest()");
168     if (!throttled()) {
169         callback_();
170     } else {
171         SENF_PPI_THROTTLE_TRACE("IN ", "queueing packet");
172     }
173 }
174
175 ///////////////////////////////////////////////////////////////////////////
176 // senf::ppi::connector::ActiveConnector
177
178 prefix_ senf::ppi::connector::PassiveConnector & senf::ppi::connector::ActiveConnector::peer()
179     const
180 {
181     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
182     return *peer_;
183 }
184
185 prefix_ void senf::ppi::connector::ActiveConnector::onThrottle()
186 {
187     throttleCallback_ = Callback();
188 }
189
190 prefix_ void senf::ppi::connector::ActiveConnector::onUnthrottle()
191 {
192     unthrottleCallback_ = Callback();
193 }
194
195 prefix_ bool senf::ppi::connector::ActiveConnector::throttled()
196     const
197 {
198     return ! connected() || peer().throttled();
199 }
200
201 ////////////////////////////////////////
202 // protected members
203
204 prefix_ senf::ppi::connector::ActiveConnector::ActiveConnector()
205     : throttleCallback_(), unthrottleCallback_(), notifyRoutes_(), throttled_(false)
206 {}
207
208 ///////////////////////////////////////////////////////////////////////////
209 // senf::ppi::connector::InputConnector
210
211 prefix_ senf::Packet senf::ppi::connector::InputConnector::read()
212 {
213     return operator()();
214 }
215
216 prefix_ senf::ppi::connector::OutputConnector & senf::ppi::connector::InputConnector::peer()
217     const
218 {
219     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
220     return *peer_;
221 }
222
223 prefix_ senf::ppi::connector::InputConnector::queue_iterator
224 senf::ppi::connector::InputConnector::begin()
225     const
226 {
227     return queue_.begin();
228 }
229
230 prefix_ senf::ppi::connector::InputConnector::queue_iterator
231 senf::ppi::connector::InputConnector::end()
232     const
233 {
234     return queue_.end();
235 }
236
237 prefix_ senf::Packet senf::ppi::connector::InputConnector::peek()
238     const
239 {
240     // Cannot peek() head of empty queue
241     SENF_ASSERT( ! queue_.empty(),
242                  "senf::ppi::connector::InputConnector: cannot call peek() on empty queue" );
243     return queue_.back();
244 }
245
246 prefix_ senf::ppi::connector::InputConnector::size_type
247 senf::ppi::connector::InputConnector::queueSize()
248     const
249 {
250     return queue_.size();
251 }
252
253 prefix_ bool senf::ppi::connector::InputConnector::empty()
254     const
255 {
256     return queue_.empty();
257 }
258
259 ////////////////////////////////////////
260 // protected members
261
262 prefix_ senf::ppi::connector::InputConnector::InputConnector()
263 {}
264
265 ////////////////////////////////////////
266 // private members
267
268 prefix_ void senf::ppi::connector::InputConnector::enqueue(Packet const & p)
269 {
270     queue_.push_front(p);
271     v_enqueueEvent();
272 }
273
274 ///////////////////////////////////////////////////////////////////////////
275 // senf::ppi::connector::OutputConnector
276
277 prefix_ senf::ppi::connector::InputConnector & senf::ppi::connector::OutputConnector::peer()
278     const
279 {
280     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
281     return *peer_;
282 }
283
284 prefix_ void senf::ppi::connector::OutputConnector::operator()(Packet const & p)
285 {
286     SENF_PPI_TRACE(p, "OUT");
287     if (connected())
288         peer().enqueue(p);
289 }
290
291 prefix_ void senf::ppi::connector::OutputConnector::write(Packet const & p)
292 {
293     operator()(p);
294 }
295
296 ////////////////////////////////////////
297 // protected members
298
299 prefix_ senf::ppi::connector::OutputConnector::OutputConnector()
300 {}
301
302 ///////////////////////////////////////////////////////////////////////////
303 // senf::ppi::connector::GenericPassiveInput
304
305 prefix_ senf::ppi::connector::GenericPassiveInput::GenericPassiveInput()
306     : qdisc_(new ThresholdQueueing(1,0))
307 {}
308
309 prefix_ senf::ppi::connector::GenericActiveOutput & senf::ppi::connector::GenericPassiveInput::peer()
310     const
311 {
312     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
313     return *peer_;
314 }
315
316 prefix_ bool senf::ppi::connector::GenericPassiveInput::boolean_test()
317     const
318 {
319     return ! empty();
320 }
321
322 ///////////////////////////////////////////////////////////////////////////
323 // senf::ppi::connector::GenericPassiveOutput
324
325 prefix_ senf::ppi::connector::GenericActiveInput & senf::ppi::connector::GenericPassiveOutput::peer()
326     const
327 {
328     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
329     return *peer_;
330 }
331
332 prefix_ bool senf::ppi::connector::GenericPassiveOutput::boolean_test()
333     const
334 {
335     return  true;
336 }
337
338 prefix_ void senf::ppi::connector::GenericPassiveOutput::connect(GenericActiveInput & target)
339 {
340     Connector::connect(target);
341 }
342
343 prefix_ senf::ppi::connector::GenericPassiveOutput::GenericPassiveOutput()
344 {}
345
346 ///////////////////////////////////////////////////////////////////////////
347 // senf::ppi::connector::GenericActiveInput
348
349 prefix_ senf::ppi::connector::GenericPassiveOutput & senf::ppi::connector::GenericActiveInput::peer()
350     const
351 {
352     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
353     return *peer_;
354 }
355
356 prefix_ bool senf::ppi::connector::GenericActiveInput::boolean_test()
357     const
358 {
359     return ! empty() || (connected() && ! peer().throttled());
360 }
361
362 prefix_ void senf::ppi::connector::GenericActiveInput::request()
363 {
364     if (connected())
365         peer().emit();
366 }
367
368 prefix_ senf::ppi::connector::GenericActiveInput::GenericActiveInput()
369 {}
370
371 ///////////////////////////////////////////////////////////////////////////
372 // senf::ppi::connector::GenericActiveOutput
373
374 prefix_ senf::ppi::connector::GenericPassiveInput & senf::ppi::connector::GenericActiveOutput::peer()
375     const
376 {
377     SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
378     return *peer_;
379 }
380
381 prefix_ bool senf::ppi::connector::GenericActiveOutput::boolean_test()
382     const
383 {
384     return connected() && ! peer().throttled();
385 }
386
387 prefix_ void senf::ppi::connector::GenericActiveOutput::connect(GenericPassiveInput & target)
388 {
389     Connector::connect(target);
390 }
391
392 prefix_ senf::ppi::connector::GenericActiveOutput::GenericActiveOutput()
393 {}
394
395 ///////////////////////////////cci.e///////////////////////////////////////
396 #undef prefix_
397
398 \f
399 // Local Variables:
400 // mode: c++
401 // fill-column: 100
402 // comment-column: 40
403 // c-file-style: "senf"
404 // indent-tabs-mode: nil
405 // ispell-local-dictionary: "american"
406 // compile-command: "scons -u test"
407 // End: