PacketImpl.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 PacketImpl inline non-template implementation */
16 
17 // Custom includes
18 
19 #define prefix_ inline
20 //-/////////////////////////////////////////////////////////////////////////////////////////////////
21 
22 //-/////////////////////////////////////////////////////////////////////////////////////////////////
23 // senf::detail::AnnotationRegistry
24 
25 prefix_ std::string senf::detail::AnnotationRegistry::name(key_type key)
26  const
27 {
28  Registry::const_iterator i (registry_.find(key));
29  return i == registry_.end() ? "" : i->second->v_name();
30 }
31 
32 prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_type key)
33  const
34 {
35  Registry::const_iterator i (registry_.find(key));
36  return i != registry_.end() && i->second->v_isComplex();
37 }
38 
39 prefix_ unsigned senf::detail::AnnotationRegistry::size(key_type key)
40  const
41 {
42  Registry::const_iterator i (registry_.find(key));
43  return i == registry_.end() ? 0 : i->second->v_size();
44 }
45 
46 prefix_ senf::detail::AnnotationRegistry::iterator senf::detail::AnnotationRegistry::begin()
47  const
48 {
49  return boost::make_transform_iterator(index_.begin(),
50  __gnu_cxx::select2nd<Index::value_type>());
51 }
52 
53 prefix_ senf::detail::AnnotationRegistry::iterator senf::detail::AnnotationRegistry::end()
54  const
55 {
56  return boost::make_transform_iterator(index_.end(),
57  __gnu_cxx::select2nd<Index::value_type>());
58 }
59 
60 prefix_ senf::detail::AnnotationRegistry::AnnotationRegistry()
61  : simpleAnnotationCount_ (0)
62 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
63  , complexAnnotationCount_ (0)
64 #endif
65 {}
66 
67 //-/////////////////////////////////////////////////////////////////////////////////////////////////
68 
69 // Memory management:
70 //
71 // * The PacketImpl destructor will *explicitly* clean-up the interpreters_ list by removing
72 // each element from the list and deleting it if it's (intrusive) refcount is 0
73 // * The PacketInterpreters use safe hooks -> they know whether they are part of a list or not
74 // * PacketHandle has an intrusive_ptr to PacketInterpreterBase. The intrusive_ptr_add_ref
75 // will refcount both the PacketImpl as well as the PacketInterpreterBase
76 // * intrusive_ptr_remove will only delete the object if it's not in a container
77 // * removing an object from the list will decrement the PacketImpl refcount accordingly
78 // * inserting an object into the list will increment the PacketImpl refcount accordingly
79 // * each PacketInterpreterBase instance holds a *raw* pointer to the PacketImpl
80 //
81 // The following operations change refcounts:
82 //
83 // * intrusive_ptr_add_ref(PacketInterpreterBase *);
84 // * intrusive_ptr_remove(PacketInterpreterBase *);
85 // * PacketImpl::appendInterpreter();
86 // * PacketImpl::prependInterpreter();
87 // * PacketImpl::truncateInterpreters();
88 //
89 // The last three also modify the impl_ member accordingly by calling
90 // PacketInterpreterBase::assign/release
91 
92 //-/////////////////////////////////////////////////////////////////////////////////////////////////
93 // senf::detail::PacketImpl
94 
95 prefix_ senf::detail::PacketImpl::PacketImpl()
96  : refcount_(0)
97 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
98  , preallocHigh_(0), preallocFree_(0)
99 #else
100  , preallocFree_(prealloc_)
101 #endif
102 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
103  , preallocHeapcount_(0)
104 #endif
105 {
106  ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
107 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
108  ::memset(prealloc_, 0, sizeof(prealloc_));
109 #endif
110 }
111 
112 prefix_ senf::detail::PacketImpl::PacketImpl(size_type size, byte initValue)
113  : refcount_(0), data_(size,initValue)
114 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
115  , preallocHigh_(0), preallocFree_(0)
116 #else
117  , preallocFree_(prealloc_)
118 #endif
119 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
120  , preallocHeapcount_(0)
121 #endif
122 {
123  ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
124 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
125  ::memset(prealloc_, 0, sizeof(prealloc_));
126 #endif
127 }
128 
129 prefix_ senf::detail::PacketImpl::PacketImpl(byte * data, size_type size, size_type chunkSize,
130  size_type offset)
131  : refcount_(0)
132 #ifndef SENF_PACKET_STD_CONTAINER
133  , data_(data, size, chunkSize, offset)
134 #else
135  , data_(data + offset, data + offset + size)
136 #endif
137 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
138  , preallocHigh_(0), preallocFree_(0)
139 #else
140  , preallocFree_(prealloc_)
141 #endif
142 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
143  , preallocHeapcount_(0)
144 #endif
145 {
146  ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
147 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
148  ::memset(prealloc_, 0, sizeof(prealloc_));
149 #endif
150 }
151 
152 prefix_ senf::detail::PacketImpl::~PacketImpl()
153 {
154 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
155  if (preallocHeapcount_)
156  destroySelf();
157 #endif
158 }
159 
160 // reference/memory management
161 
162 prefix_ void senf::detail::PacketImpl::add_ref()
163 {
164  ++ refcount_;
165 }
166 
167 prefix_ senf::detail::PacketImpl::refcount_t senf::detail::PacketImpl::refcount()
168  const
169 {
170  return refcount_;
171 }
172 
173 prefix_ void senf::detail::intrusive_ptr_add_ref(PacketImpl * impl)
174 {
175  impl->add_ref();
176 }
177 
178 prefix_ void senf::detail::intrusive_ptr_release(PacketImpl * impl)
179 {
180  impl->release();
181 }
182 
183 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
184 
185 prefix_ void * senf::detail::PacketImpl::allocateInterpreter()
186 {
187 # ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
188  if (preallocFree_ != prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS) {
189 # endif
190  void * rv (preallocFree_);
191  SENF_ASSERT(rv >= prealloc_ && rv < prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS,
192  "Prealloc array exceeded");
193 #ifdef SENF_DEBUG
194  if (size_type(static_cast<PreallocSlot *>(rv) - prealloc_) > maxPreallocHigh_)
195  maxPreallocHigh_ = static_cast<PreallocSlot *>(rv) - prealloc_;
196 #endif
197  preallocFree_ += preallocFree_->nextOffset_ + 1;
198  return rv;
199 # ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
200  }
201  else {
202  ++ preallocHeapcount_;
203 # ifdef SENF_DEBUG
204  if (maxPreallocHeapcount_ < preallocHeapcount_)
205  maxPreallocHeapcount_ = preallocHeapcount_;
206 # endif
207  return new PreallocSlot;
208  }
209 # endif
210 }
211 
212 #else /* SENF_PACKET_ALTERNATIVE_PREALLOC */
213 
214 prefix_ void * senf::detail::PacketImpl::allocateInterpreter()
215 
216 {
217  if (preallocFree_) {
218  void * rv (preallocFree_);
219  SENF_ASSERT(rv >= prealloc_ && rv < prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS,
220  "Internal failure: preallocFree_ points outside of prealloc_ array");
221  preallocFree_ = preallocFree_ -> nextFree_;
222  return rv;
223  }
224  else
225 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
226  if (preallocHigh_ < SENF_PACKET_PREALLOC_INTERPRETERS)
227 #endif
228  {
229  SENF_ASSERT( preallocHigh_ < SENF_PACKET_PREALLOC_INTERPRETERS,
230  "Number of interpreters > SENF_PREALLOC_INTERPRETERS" );
231  ++ preallocHigh_;
232 #ifdef SENF_DEBUG
233  if (maxPreallocHigh_ < preallocHigh_)
234  maxPreallocHigh_ = preallocHigh_;
235 #endif
236  return & prealloc_[preallocHigh_ - 1];
237  }
238 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
239  else {
240  ++ preallocHeapcount_;
241 #ifdef SENF_DEBUG
242  if (maxPreallocHeapcount_ < preallocHeapcount_)
243  maxPreallocHeapcount_ = preallocHeapcount_;
244 #endif
245  return new PreallocSlot;
246  }
247 #endif
248 }
249 
250 #endif /* SENF_PACKET_ALTERNATIVE_PREALLOC */
251 
252 prefix_ void senf::detail::PacketImpl::deallocateInterpreter(void * address)
253 {
254 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
255  if (preallocHeapcount_ > 0 &&
256  (address < prealloc_ || address > prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS)) {
257  -- preallocHeapcount_;
258  delete static_cast<PreallocSlot *>(address);
259  }
260  else {
261 #endif
262  SENF_ASSERT(address >= prealloc_ && address < prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS,
263  "Internal failure: PacketInterpreter outside prealloc array but heapcount == 0");
264 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
265  static_cast<PreallocSlot *>(address)->nextFree_ = preallocFree_;
266 #else
267  static_cast<PreallocSlot *>(address)->nextOffset_ = (preallocFree_ - static_cast<PreallocSlot *>(address)) - 1;
268 #endif
269  preallocFree_ = static_cast<PreallocSlot *>(address);
270 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
271  }
272 #endif
273 }
274 
275 #ifndef SENF_PACKET_STD_CONTAINER
276 
277 prefix_ bool senf::detail::PacketImpl::usingExternalMemory()
278  const
279 {
280  return data_.external();
281 }
282 
283 prefix_ void senf::detail::PacketImpl::releaseExternalMemory()
284 {
285  data_.releaseExternal();
286 }
287 
288 #else
289 
290 prefix_ bool senf::detail::PacketImpl::usingExternalMemory()
291  const
292 {
293  return false;
294 }
295 
296 prefix_ void senf::detail::PacketImpl::releaseExternalMemory()
297 {}
298 
299 #endif
300 
301 // Interpreter chain
302 
303 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::first()
304 {
305  return interpreters_.empty() ? nullptr : & interpreters_.front();
306 }
307 
308 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::last()
309 {
310  return interpreters_.empty() ? nullptr : & interpreters_.back();
311 }
312 
313 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::next(PacketInterpreterBase * p)
314 {
315  interpreter_list::iterator i (interpreter_list::s_iterator_to(*p));
316  return (++i == interpreters_.end()) ? nullptr : &*i;
317 }
318 
319 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::prev(PacketInterpreterBase * p)
320 {
321  interpreter_list::iterator i (interpreter_list::s_iterator_to(*p));
322  return (i == interpreters_.begin()) ? nullptr : &*(--i);
323 }
324 
325 prefix_ void senf::detail::PacketImpl::truncateInterpreters(PacketInterpreterBase * p)
326 {
327  Guard guard (this);
328  eraseInterpreters(interpreter_list::s_iterator_to(*p),interpreters_.end());
329 }
330 
331 prefix_ void senf::detail::PacketImpl::truncateInterpretersBackwards(PacketInterpreterBase * p)
332 {
333  Guard guard (this);
334  eraseInterpreters(interpreters_.begin(),boost::next(interpreter_list::s_iterator_to(*p)));
335 }
336 
337 prefix_ void senf::detail::PacketImpl::clearInterpreters()
338 {
339  interpreters_.clear();
340 }
341 
342 // Data container
343 
344 prefix_ senf::detail::PacketImpl::iterator senf::detail::PacketImpl::begin()
345 {
346  return data_.begin();
347 }
348 
349 prefix_ senf::detail::PacketImpl::iterator senf::detail::PacketImpl::end()
350 {
351  return data_.end();
352 }
353 
354 prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::size()
355 {
356  return data_.size();
357 }
358 
359 prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, byte v)
360 {
361  difference_type ix (std::distance(begin(),pos));
362  data_.insert(pos,v);
363  updateIterators(self,ix,1);
364 }
365 
366 prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, size_type n,
367  byte v)
368 {
369  difference_type ix (std::distance(begin(),pos));
370  data_.insert(pos,n,v);
371  updateIterators(self,ix,n);
372 }
373 
374 prefix_ void senf::detail::PacketImpl::erase(PacketData * self, iterator pos)
375 {
376  difference_type ix (std::distance(begin(),pos));
377  data_.erase(pos);
378  updateIterators(self,ix,-1);
379 }
380 
381 prefix_ void senf::detail::PacketImpl::erase(PacketData * self, iterator first, iterator last)
382 {
383  difference_type ix (std::distance(begin(),first));
384  difference_type delta (std::distance(first,last));
385  data_.erase(first,last);
386  updateIterators(self,ix,-delta);
387 }
388 
389 #ifdef SENF_PACKET_STD_CONTAINER
390 
391 prefix_ void senf::detail::PacketImpl::truncateDataBackwards(PacketData * self, iterator pos)
392 {
393  erase(self, begin(), pos);
394 }
395 
396 prefix_ senf::detail::PacketImpl::iterator
397 senf::detail::PacketImpl::truncateRawDataBackwards(iterator pos)
398 {
399  SENF_ASSERT( interpreters_.empty(),
400  "truncateRawDataBackwards called with non-empty interpreter chain" );
401  data_.erase(data_.begin(), pos);
402  return data_.begin();
403 }
404 
405 prefix_ void senf::detail::PacketImpl::truncateRawDataForward(iterator pos)
406 {
407  data_.erase(pos, data_.end());
408 }
409 
410 #else
411 
412 prefix_ void senf::detail::PacketImpl::truncateDataBackwards(PacketData * self, iterator pos)
413 {
414  difference_type delta (std::distance(begin(),pos));
415  data_.truncateFront(pos);
416  updateIterators(self,0,-delta);
417 }
418 
419 prefix_ senf::detail::PacketImpl::iterator
420 senf::detail::PacketImpl::truncateRawDataBackwards(iterator pos)
421 {
422  SENF_ASSERT( interpreters_.empty(),
423  "truncateRawDataBackwards called with non-empty interpreter chain" );
424  data_.truncateFront(pos);
425  return pos;
426 }
427 
428 prefix_ void senf::detail::PacketImpl::truncateRawDataForward(iterator pos)
429 {
430  data_.truncateBack(pos);
431 }
432 
433 #endif
434 
435 // Annotations
436 
437 prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_type key)
438 {
439 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
440  return key >= 0 ? & simpleAnnotations_[key] : complexAnnotation(key);
441 #else
442  return & simpleAnnotations_[key];
443 #endif
444 }
445 
446 prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::maxPreallocHigh()
447 {
448 #if defined(SENF_DEBUG)
449  return maxPreallocHigh_;
450 #else
451  return -1;
452 #endif
453 }
454 
455 prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::maxPreallocHeapcount()
456 {
457 #if defined(SENF_DEBUG) && ! defined(SENF_PACKET_NO_HEAP_INTERPRETERS)
458  return maxPreallocHeapcount_;
459 #else
460  return -1;
461 #endif
462 }
463 
464 //-/////////////////////////////////////////////////////////////////////////////////////////////////
465 // senf::detail::PacketImpl::Guard
466 
467 prefix_ senf::detail::PacketImpl::Guard::Guard(PacketImpl * impl)
468  : p (impl)
469 {
470  p->add_ref();
471 }
472 
473 prefix_ senf::detail::PacketImpl::Guard::~Guard()
474 {
475  p->release();
476 }
477 
478 //-/////////////////////////////////////////////////////////////////////////////////////////////////
479 #undef prefix_
480 
481 
482 // Local Variables:
483 // mode: c++
484 // fill-column: 100
485 // c-file-style: "senf"
486 // indent-tabs-mode: nil
487 // ispell-local-dictionary: "american"
488 // compile-command: "scons -u test"
489 // comment-column: 40
490 // End: