// $Id$
//
-// Copyright (C) 2007
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
/** \file
\brief PacketImpl public header */
-#ifndef HH_PacketImpl_
-#define HH_PacketImpl_ 1
+#ifndef HH_SENF_Packets_PacketImpl_
+#define HH_SENF_Packets_PacketImpl_ 1
// Custom includes
#include <memory>
+#include <vector>
#include <boost/utility.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/static_assert.hpp>
#include "../Utils/pool_alloc_mixin.hh"
#include "PacketTypes.hh"
+#include "../Utils/singleton.hh"
//#include "PacketImpl.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
+
+ /** \brief Marker base-class for complex annotations
+
+ This class is used as a base class to mark an annotation type as complex. A complex
+ annotation will have it's constructor/destructor called. Non-complex annotations will not
+ have their constructor called, they will be zero initialized. The destructor of non-complex
+ annotations is never called.
+
+ An annotation must be marked as complex if it is not <a
+ href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">POD</a>. Simplified, an
+ annotation must be marked as ComplexAnnotation, if
+
+ \li it has a (user defined) constructor or destructor
+ \li it has any data members which have (user defined) constructors or destructors
+
+ \see \ref packet_usage_annotation
+ */
+ struct ComplexAnnotation {};
+
namespace detail {
-
+
+ struct AnnotationP
+ {
+ virtual ~AnnotationP();
+ };
+
+ template <class Annotation>
+ struct TAnnotationP
+ : public AnnotationP
+ {
+ Annotation annotation;
+ };
+
+ union AnnotationEntry {
+ AnnotationP * p;
+ unsigned long long i;
+ };
+
+ struct AnnotationIndexerBase
+ {
+ static unsigned maxAnnotations;
+ static std::vector<bool> & small();
+ };
+
+ template <class Annotation>
+ struct AnnotationIndexer
+ : public senf::singleton< AnnotationIndexer<Annotation> >,
+ public AnnotationIndexerBase
+ {
+ AnnotationIndexer();
+ unsigned index_;
+ static unsigned index();
+ static bool const Complex = boost::is_base_of<ComplexAnnotation, Annotation>::value;
+ static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) && ! Complex);
+
+# if 0 // The test is difficult since it does not work with user-defined trivial constructors
+# ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
+
+ BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value
+ && boost::has_trivial_destructor<Annotation>::value)
+ || Complex ));
+
+# endif
+# endif
+ };
+
+ template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
+ struct GetAnnotation
+ {
+ static Annotation & get(AnnotationEntry & e);
+ };
+
+ template <class Annotation>
+ struct GetAnnotation<Annotation, true>
+ {
+ static Annotation & get(AnnotationEntry & e);
+ };
+
/** \brief Internal: Packet data storage
-
+
\internal
This is the class holding the packet data and the interpreter chain. All manipulations of
PacketImpl will update the interpreters (that is the vector indices stored therein) whenever
the data is changed.
*/
- class PacketImpl
+ class PacketImpl
: boost::noncopyable,
public pool_alloc_mixin<PacketImpl>
{
~PacketImpl();
// rerference/memory management
-
+
void add_ref(refcount_t n=1);
void release(refcount_t n=1);
refcount_t refcount() const;
void erase(PacketData * self, iterator first, iterator last);
void clear(PacketData * self);
+ void reserve(size_type n);
+ size_type capacity() const;
+
+ // Annotations
+ template <class Annotation>
+ Annotation & annotation();
+
/** \brief Internal: Keep PacketImpl instance alive
\internal
refcount_t refcount_;
raw_container data_;
interpreter_list interpreters_;
+
+ typedef std::vector<AnnotationEntry> Annotations;
+ Annotations annotations_;
void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
void updateIterators(PacketData * self, difference_type pos, difference_type n);
///////////////////////////////hh.e////////////////////////////////////////
#endif
-#if !defined(HH_Packets__decls_) && !defined(HH_PacketImpl_i_)
-#define HH_PacketImpl_i_
+#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
+#define HH_SENF_Packets_PacketImpl_i_
#include "PacketImpl.cci"
//#include "PacketImpl.ct"
#include "PacketImpl.cti"