Connectors.cci
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief Connectors inline non-template implementation */
16 
17 // Custom includes
18 #include <senf/Utils/TypeInfo.hh>
19 #include <senf/Utils/senfassert.hh>
20 #include <senf/Utils/senflikely.hh>
21 
22 #define prefix_ inline
23 //-/////////////////////////////////////////////////////////////////////////////////////////////////
24 
25 #ifdef SENF_PPI_NOTRACE
26 # define SENF_PPI_THROTTLE_TRACE(label, type)
27 # define SENF_PPI_TRACE(packet, label)
28 #else
29 # define SENF_PPI_THROTTLE_TRACE(label, type) throttleTrace(label, type)
30 # define SENF_PPI_TRACE(packet, label) trace(packet, label)
31 #endif
32 
33 //-/////////////////////////////////////////////////////////////////////////////////////////////////
34 // senf::ppi::connector::Connector
35 
36 prefix_ senf::ppi::connector::Connector & senf::ppi::connector::Connector::peer()
37  const
38 {
39  // The connector is not connected
40  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
41  return *peer_;
42 }
43 
44 #ifndef SENF_PPI_NOTRACE
45 prefix_ void senf::ppi::connector::Connector::staticTracingState(TraceState state)
46 {
47  staticTraceState_ = state;
48 }
49 
50 prefix_ senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::tracingState()
51  const
52 {
53  return std::max(staticTraceState_, traceState_);
54 }
55 
56 prefix_ void senf::ppi::connector::Connector::tracingState(TraceState state)
57 {
58  traceState_ = state;
59 }
60 
61 prefix_ void senf::ppi::connector::Connector::tracingFilter(std::string const & traceFilter)
62 {
63  traceFilter_ = traceFilter;
64 }
65 #endif
66 
67 //-/////////////////////////////////////////////////////////////////////////////////////////////////
68 // protected members
69 
70 prefix_ bool senf::ppi::connector::Connector::connected()
71  const
72 {
73  return peer_;
74 }
75 
76 prefix_ senf::console::DirectoryNode & senf::ppi::connector::Connector::consoleDir()
77  const
78 {
79  return consoleDir_.node();
80 }
81 
82 //-/////////////////////////////////////////////////////////////////////////////////////////////////
83 // senf::ppi::connector::PassiveConnector
84 
85 prefix_ senf::ppi::connector::ActiveConnector & senf::ppi::connector::PassiveConnector::peer()
86  const
87 {
88  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
89  return *peer_;
90 }
91 
92 prefix_ bool senf::ppi::connector::PassiveConnector::throttled()
93  const
94 {
95  return nativeThrottled_ || remoteThrottled_;
96 }
97 
98 //-/////////////////////////////////////////////////////////////////////////////////////////////////
99 // private members
100 
101 prefix_ void senf::ppi::connector::PassiveConnector::emitThrottle()
102 {
103  SENF_PPI_THROTTLE_TRACE("OUT", "throttle");
104  if (SENF_LIKELY(connected()))
105  peer().notifyThrottle();
106 }
107 
108 prefix_ void senf::ppi::connector::PassiveConnector::emitUnthrottle()
109 {
110  SENF_PPI_THROTTLE_TRACE("OUT", "unthrottle");
111  if (SENF_LIKELY(connected())) {
112  peer().notifyUnthrottle();
113  v_unthrottleEvent();
114  }
115 }
116 
117 prefix_ void senf::ppi::connector::PassiveConnector::notifyThrottle()
118 {
119  if (SENF_LIKELY(!throttled())) {
120  remoteThrottled_ = true;
121  emitThrottle();
122  }
123  else
124  remoteThrottled_ = true;
125 }
126 
127 // public members
128 
129 prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
130  const
131 {
132  return nativeThrottled_;
133 }
134 
135 prefix_ void senf::ppi::connector::PassiveConnector::throttle()
136 {
137  if (SENF_LIKELY(!throttled())) {
138  nativeThrottled_ = true;
139  emitThrottle();
140  } else
141  nativeThrottled_ = true;
142 }
143 
144 prefix_ void senf::ppi::connector::PassiveConnector::unthrottle()
145 {
146  if (throttled() && ! remoteThrottled_) {
147  nativeThrottled_ = false;
148  emitUnthrottle();
149  } else
150  nativeThrottled_ = false;
151 
152 }
153 
154 //-/////////////////////////////////////////////////////////////////////////////////////////////////
155 // protected members
156 
157 prefix_ void senf::ppi::connector::PassiveConnector::emit()
158 {
159  // No event callback has been registered (onRequest() call missing)
160  SENF_ASSERT(callback_, "senf::ppi::connector::PassiveConnector: missing onRequest()");
161  if (SENF_LIKELY(!throttled())) {
162  callback_();
163  } else {
164  SENF_PPI_THROTTLE_TRACE("IN ", "queueing packet");
165  }
166 }
167 
168 //-/////////////////////////////////////////////////////////////////////////////////////////////////
169 // senf::ppi::connector::ActiveConnector
170 
171 prefix_ senf::ppi::connector::PassiveConnector & senf::ppi::connector::ActiveConnector::peer()
172  const
173 {
174  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
175  return *peer_;
176 }
177 
178 prefix_ void senf::ppi::connector::ActiveConnector::onThrottle()
179 {
180  throttleCallback_ = Callback();
181 }
182 
183 prefix_ void senf::ppi::connector::ActiveConnector::onUnthrottle()
184 {
185  unthrottleCallback_ = Callback();
186 }
187 
188 prefix_ bool senf::ppi::connector::ActiveConnector::throttled()
189  const
190 {
191  return ! connected() || peer().throttled();
192 }
193 
194 //-/////////////////////////////////////////////////////////////////////////////////////////////////
195 // protected members
196 
197 prefix_ senf::ppi::connector::ActiveConnector::ActiveConnector()
198  : peer_(nullptr), throttled_(false)
199 {}
200 
201 //-/////////////////////////////////////////////////////////////////////////////////////////////////
202 // senf::ppi::connector::InputConnector
203 
204 prefix_ senf::Packet const & senf::ppi::connector::InputConnector::read()
205 {
206  return operator()();
207 }
208 
209 prefix_ senf::ppi::connector::OutputConnector & senf::ppi::connector::InputConnector::peer()
210  const
211 {
212  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
213  return *peer_;
214 }
215 
216 prefix_ senf::ppi::connector::InputConnector::size_type
217 senf::ppi::connector::InputConnector::queueSize()
218  const
219 {
220 // return queue_.size() + (fastPacket_ ? 1 : 0);
221  return queue_.size() + bool(fastPacket_);
222 }
223 
224 prefix_ bool senf::ppi::connector::InputConnector::empty()
225  const
226 {
227  return fastPacket_ == nullptr && queue_.empty();
228 }
229 
230 //-/////////////////////////////////////////////////////////////////////////////////////////////////
231 // protected members
232 
233 prefix_ senf::ppi::connector::InputConnector::InputConnector()
234  : peer_(nullptr), fastPacket_(nullptr)
235 {}
236 
237 //-/////////////////////////////////////////////////////////////////////////////////////////////////
238 // private members
239 
240 prefix_ void senf::ppi::connector::InputConnector::enqueue(Packet const & p)
241 {
242  if (SENF_LIKELY(queue_.empty())) {
243  fastPacket_ = &p;
244  try {
245  v_enqueueEvent();
246  } catch (Exception & e) {
247  if (fastPacket_) {
248  queue_.push_front(p);
249  fastPacket_ = nullptr;
250  }
251  throw e;
252  }
253  if (SENF_UNLIKELY(fastPacket_)) {
254  queue_.push_front(p);
255  fastPacket_ = nullptr;
256  }
257  } else {
258  queue_.push_front(p);
259  v_enqueueEvent();
260  }
261 }
262 
263 
264 //-/////////////////////////////////////////////////////////////////////////////////////////////////
265 // senf::ppi::connector::OutputConnector
266 
267 prefix_ senf::ppi::connector::InputConnector & senf::ppi::connector::OutputConnector::peer()
268  const
269 {
270  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
271  return *peer_;
272 }
273 
274 prefix_ void senf::ppi::connector::OutputConnector::operator()(Packet const & p)
275 {
276  SENF_PPI_TRACE(p, "OUT");
277  if (SENF_LIKELY(connected()))
278  peer().enqueue(p);
279 }
280 
281 prefix_ void senf::ppi::connector::OutputConnector::write(Packet const & p)
282 {
283  operator()(p);
284 }
285 
286 //-/////////////////////////////////////////////////////////////////////////////////////////////////
287 // protected members
288 
289 prefix_ senf::ppi::connector::OutputConnector::OutputConnector()
290  : peer_(nullptr)
291 {}
292 
293 //-/////////////////////////////////////////////////////////////////////////////////////////////////
294 // senf::ppi::connector::GenericPassiveInput
295 
296 prefix_ senf::ppi::connector::GenericPassiveInput::GenericPassiveInput()
297  : peer_(nullptr), throttlingDisc_(new ThresholdThrottling(1,0))
298 {}
299 
300 prefix_ senf::ppi::connector::GenericActiveOutput & senf::ppi::connector::GenericPassiveInput::peer()
301  const
302 {
303  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
304  return *peer_;
305 }
306 
307 prefix_ bool senf::ppi::connector::GenericPassiveInput::boolean_test()
308  const
309 {
310  return ! empty();
311 }
312 
313 //-/////////////////////////////////////////////////////////////////////////////////////////////////
314 // senf::ppi::connector::GenericPassiveOutput
315 
316 prefix_ senf::ppi::connector::GenericActiveInput & senf::ppi::connector::GenericPassiveOutput::peer()
317  const
318 {
319  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
320  return *peer_;
321 }
322 
323 prefix_ bool senf::ppi::connector::GenericPassiveOutput::boolean_test()
324  const
325 {
326  return true;
327 }
328 
329 prefix_ void senf::ppi::connector::GenericPassiveOutput::connect(GenericActiveInput & target)
330 {
331  OutputConnector::connect(target);
332 }
333 
334 prefix_ senf::ppi::connector::GenericPassiveOutput::GenericPassiveOutput()
335  : peer_(nullptr)
336 {}
337 
338 //-/////////////////////////////////////////////////////////////////////////////////////////////////
339 // senf::ppi::connector::GenericActiveInput
340 
341 prefix_ senf::ppi::connector::GenericPassiveOutput & senf::ppi::connector::GenericActiveInput::peer()
342  const
343 {
344  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
345  return *peer_;
346 }
347 
348 prefix_ bool senf::ppi::connector::GenericActiveInput::boolean_test()
349  const
350 {
351  return ! empty() || (connected() && ! peer().throttled());
352 }
353 
354 prefix_ void senf::ppi::connector::GenericActiveInput::request()
355 {
356  if (SENF_LIKELY(connected()))
357  peer().emit();
358 }
359 
360 prefix_ senf::ppi::connector::GenericActiveInput::GenericActiveInput()
361  : peer_(nullptr)
362 {}
363 
364 //-/////////////////////////////////////////////////////////////////////////////////////////////////
365 // senf::ppi::connector::GenericActiveOutput
366 
367 prefix_ senf::ppi::connector::GenericPassiveInput & senf::ppi::connector::GenericActiveOutput::peer()
368  const
369 {
370  SENF_ASSERT(peer_, "senf::ppi::connect() call missing");
371  return *peer_;
372 }
373 
374 prefix_ bool senf::ppi::connector::GenericActiveOutput::boolean_test()
375  const
376 {
377  return connected() && ! peer().throttled();
378 }
379 
380 prefix_ void senf::ppi::connector::GenericActiveOutput::connect(GenericPassiveInput & target)
381 {
382  OutputConnector::connect(target);
383 }
384 
385 prefix_ senf::ppi::connector::GenericActiveOutput::GenericActiveOutput()
386  : peer_(nullptr)
387 {}
388 
389 //-/////////////////////////////////////////////////////////////////////////////////////////////////
390 #undef prefix_
391 
392 
393 // Local Variables:
394 // mode: c++
395 // fill-column: 100
396 // comment-column: 40
397 // c-file-style: "senf"
398 // indent-tabs-mode: nil
399 // ispell-local-dictionary: "american"
400 // compile-command: "scons -u test"
401 // End: