Adjustment and fixes for boost-1.36 support
[senf.git] / Packets / PacketImpl.hh
index ad254d6..32ae5a1 100644 (file)
@@ -1,6 +1,8 @@
-// Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// $Id$
+//
+// 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
@@ -45,7 +129,7 @@ namespace detail {
         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>
     {
@@ -68,7 +152,7 @@ namespace detail {
         ~PacketImpl();
 
         // rerference/memory management
+
         void add_ref(refcount_t n=1);
         void release(refcount_t n=1);
         refcount_t refcount() const;
@@ -101,6 +185,13 @@ namespace detail {
         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
@@ -119,6 +210,9 @@ namespace detail {
         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);
@@ -128,8 +222,8 @@ namespace detail {
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #endif
-#if !defined(SENF_PACKETS_DECL_ONLY) && !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"