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
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
15 \brief PacketImpl inline non-template implementation */
19 #define prefix_ inline
20 //-/////////////////////////////////////////////////////////////////////////////////////////////////
22 //-/////////////////////////////////////////////////////////////////////////////////////////////////
23 // senf::detail::AnnotationRegistry
25 prefix_ std::string senf::detail::AnnotationRegistry::name(key_type key)
28 Registry::const_iterator i (registry_.find(key));
29 return i == registry_.end() ? "" : i->second->v_name();
32 prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_type key)
35 Registry::const_iterator i (registry_.find(key));
36 return i != registry_.end() && i->second->v_isComplex();
39 prefix_ unsigned senf::detail::AnnotationRegistry::size(key_type key)
42 Registry::const_iterator i (registry_.find(key));
43 return i == registry_.end() ? 0 : i->second->v_size();
46 prefix_ senf::detail::AnnotationRegistry::iterator senf::detail::AnnotationRegistry::begin()
49 return boost::make_transform_iterator(index_.begin(),
50 __gnu_cxx::select2nd<Index::value_type>());
53 prefix_ senf::detail::AnnotationRegistry::iterator senf::detail::AnnotationRegistry::end()
56 return boost::make_transform_iterator(index_.end(),
57 __gnu_cxx::select2nd<Index::value_type>());
60 prefix_ senf::detail::AnnotationRegistry::AnnotationRegistry()
61 : simpleAnnotationCount_ (0)
62 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
63 , complexAnnotationCount_ (0)
67 //-/////////////////////////////////////////////////////////////////////////////////////////////////
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
81 // The following operations change refcounts:
83 // * intrusive_ptr_add_ref(PacketInterpreterBase *);
84 // * intrusive_ptr_remove(PacketInterpreterBase *);
85 // * PacketImpl::appendInterpreter();
86 // * PacketImpl::prependInterpreter();
87 // * PacketImpl::truncateInterpreters();
89 // The last three also modify the impl_ member accordingly by calling
90 // PacketInterpreterBase::assign/release
92 //-/////////////////////////////////////////////////////////////////////////////////////////////////
93 // senf::detail::PacketImpl
95 prefix_ senf::detail::PacketImpl::PacketImpl()
97 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
98 , preallocHigh_(0), preallocFree_(0)
100 , preallocFree_(prealloc_)
102 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
103 , preallocHeapcount_(0)
106 ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
107 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
108 ::memset(prealloc_, 0, sizeof(prealloc_));
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)
117 , preallocFree_(prealloc_)
119 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
120 , preallocHeapcount_(0)
123 ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
124 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
125 ::memset(prealloc_, 0, sizeof(prealloc_));
129 prefix_ senf::detail::PacketImpl::PacketImpl(byte * data, size_type size, size_type chunkSize,
132 #ifndef SENF_PACKET_STD_CONTAINER
133 , data_(data, size, chunkSize, offset)
135 , data_(data + offset, data + offset + size)
137 #ifdef SENF_PACKET_ALTERNATIVE_PREALLOC
138 , preallocHigh_(0), preallocFree_(0)
140 , preallocFree_(prealloc_)
142 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
143 , preallocHeapcount_(0)
146 ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
147 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
148 ::memset(prealloc_, 0, sizeof(prealloc_));
152 prefix_ senf::detail::PacketImpl::~PacketImpl()
154 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
155 if (preallocHeapcount_)
160 // reference/memory management
162 prefix_ void senf::detail::PacketImpl::add_ref()
167 prefix_ senf::detail::PacketImpl::refcount_t senf::detail::PacketImpl::refcount()
173 prefix_ void senf::detail::intrusive_ptr_add_ref(PacketImpl * impl)
178 prefix_ void senf::detail::intrusive_ptr_release(PacketImpl * impl)
183 #ifndef SENF_PACKET_ALTERNATIVE_PREALLOC
185 prefix_ void * senf::detail::PacketImpl::allocateInterpreter()
187 # ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
188 if (preallocFree_ != prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS) {
190 void * rv (preallocFree_);
191 SENF_ASSERT(rv >= prealloc_ && rv < prealloc_ + SENF_PACKET_PREALLOC_INTERPRETERS,
192 "Prealloc array exceeded");
194 if (size_type(static_cast<PreallocSlot *>(rv) - prealloc_) > maxPreallocHigh_)
195 maxPreallocHigh_ = static_cast<PreallocSlot *>(rv) - prealloc_;
197 preallocFree_ += preallocFree_->nextOffset_ + 1;
199 # ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
202 ++ preallocHeapcount_;
204 if (maxPreallocHeapcount_ < preallocHeapcount_)
205 maxPreallocHeapcount_ = preallocHeapcount_;
207 return new PreallocSlot;
212 #else /* SENF_PACKET_ALTERNATIVE_PREALLOC */
214 prefix_ void * senf::detail::PacketImpl::allocateInterpreter()
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_;
225 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
226 if (preallocHigh_ < SENF_PACKET_PREALLOC_INTERPRETERS)
229 SENF_ASSERT( preallocHigh_ < SENF_PACKET_PREALLOC_INTERPRETERS,
230 "Number of interpreters > SENF_PREALLOC_INTERPRETERS" );
233 if (maxPreallocHigh_ < preallocHigh_)
234 maxPreallocHigh_ = preallocHigh_;
236 return & prealloc_[preallocHigh_ - 1];
238 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
240 ++ preallocHeapcount_;
242 if (maxPreallocHeapcount_ < preallocHeapcount_)
243 maxPreallocHeapcount_ = preallocHeapcount_;
245 return new PreallocSlot;
250 #endif /* SENF_PACKET_ALTERNATIVE_PREALLOC */
252 prefix_ void senf::detail::PacketImpl::deallocateInterpreter(void * address)
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);
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_;
267 static_cast<PreallocSlot *>(address)->nextOffset_ = (preallocFree_ - static_cast<PreallocSlot *>(address)) - 1;
269 preallocFree_ = static_cast<PreallocSlot *>(address);
270 #ifndef SENF_PACKET_NO_HEAP_INTERPRETERS
275 #ifndef SENF_PACKET_STD_CONTAINER
277 prefix_ bool senf::detail::PacketImpl::usingExternalMemory()
280 return data_.external();
283 prefix_ void senf::detail::PacketImpl::releaseExternalMemory()
285 data_.releaseExternal();
290 prefix_ bool senf::detail::PacketImpl::usingExternalMemory()
296 prefix_ void senf::detail::PacketImpl::releaseExternalMemory()
303 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::first()
305 return interpreters_.empty() ? nullptr : & interpreters_.front();
308 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::last()
310 return interpreters_.empty() ? nullptr : & interpreters_.back();
313 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::next(PacketInterpreterBase * p)
315 interpreter_list::iterator i (interpreter_list::s_iterator_to(*p));
316 return (++i == interpreters_.end()) ? nullptr : &*i;
319 prefix_ senf::PacketInterpreterBase * senf::detail::PacketImpl::prev(PacketInterpreterBase * p)
321 interpreter_list::iterator i (interpreter_list::s_iterator_to(*p));
322 return (i == interpreters_.begin()) ? nullptr : &*(--i);
325 prefix_ void senf::detail::PacketImpl::truncateInterpreters(PacketInterpreterBase * p)
328 eraseInterpreters(interpreter_list::s_iterator_to(*p),interpreters_.end());
331 prefix_ void senf::detail::PacketImpl::truncateInterpretersBackwards(PacketInterpreterBase * p)
334 eraseInterpreters(interpreters_.begin(),boost::next(interpreter_list::s_iterator_to(*p)));
337 prefix_ void senf::detail::PacketImpl::clearInterpreters()
339 interpreters_.clear();
344 prefix_ senf::detail::PacketImpl::iterator senf::detail::PacketImpl::begin()
346 return data_.begin();
349 prefix_ senf::detail::PacketImpl::iterator senf::detail::PacketImpl::end()
354 prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::size()
359 prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, byte v)
361 difference_type ix (std::distance(begin(),pos));
363 updateIterators(self,ix,1);
366 prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, size_type n,
369 difference_type ix (std::distance(begin(),pos));
370 data_.insert(pos,n,v);
371 updateIterators(self,ix,n);
374 prefix_ void senf::detail::PacketImpl::erase(PacketData * self, iterator pos)
376 difference_type ix (std::distance(begin(),pos));
378 updateIterators(self,ix,-1);
381 prefix_ void senf::detail::PacketImpl::erase(PacketData * self, iterator first, iterator last)
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);
389 #ifdef SENF_PACKET_STD_CONTAINER
391 prefix_ void senf::detail::PacketImpl::truncateDataBackwards(PacketData * self, iterator pos)
393 erase(self, begin(), pos);
396 prefix_ senf::detail::PacketImpl::iterator
397 senf::detail::PacketImpl::truncateRawDataBackwards(iterator pos)
399 SENF_ASSERT( interpreters_.empty(),
400 "truncateRawDataBackwards called with non-empty interpreter chain" );
401 data_.erase(data_.begin(), pos);
402 return data_.begin();
405 prefix_ void senf::detail::PacketImpl::truncateRawDataForward(iterator pos)
407 data_.erase(pos, data_.end());
412 prefix_ void senf::detail::PacketImpl::truncateDataBackwards(PacketData * self, iterator pos)
414 difference_type delta (std::distance(begin(),pos));
415 data_.truncateFront(pos);
416 updateIterators(self,0,-delta);
419 prefix_ senf::detail::PacketImpl::iterator
420 senf::detail::PacketImpl::truncateRawDataBackwards(iterator pos)
422 SENF_ASSERT( interpreters_.empty(),
423 "truncateRawDataBackwards called with non-empty interpreter chain" );
424 data_.truncateFront(pos);
428 prefix_ void senf::detail::PacketImpl::truncateRawDataForward(iterator pos)
430 data_.truncateBack(pos);
437 prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_type key)
439 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
440 return key >= 0 ? & simpleAnnotations_[key] : complexAnnotation(key);
442 return & simpleAnnotations_[key];
446 prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::maxPreallocHigh()
448 #if defined(SENF_DEBUG)
449 return maxPreallocHigh_;
455 prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::maxPreallocHeapcount()
457 #if defined(SENF_DEBUG) && ! defined(SENF_PACKET_NO_HEAP_INTERPRETERS)
458 return maxPreallocHeapcount_;
464 //-/////////////////////////////////////////////////////////////////////////////////////////////////
465 // senf::detail::PacketImpl::Guard
467 prefix_ senf::detail::PacketImpl::Guard::Guard(PacketImpl * impl)
473 prefix_ senf::detail::PacketImpl::Guard::~Guard()
478 //-/////////////////////////////////////////////////////////////////////////////////////////////////
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