Adjustment and fixes for boost-1.36 support
[senf.git] / Packets / PacketImpl.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief PacketImpl public header */
25
26 #ifndef HH_SENF_Packets_PacketImpl_
27 #define HH_SENF_Packets_PacketImpl_ 1
28
29 // Custom includes
30 #include <memory>
31 #include <vector>
32 #include <boost/utility.hpp>
33 #include <boost/type_traits/is_base_of.hpp>
34 #include <boost/type_traits/has_trivial_constructor.hpp>
35 #include <boost/type_traits/has_trivial_destructor.hpp>
36 #include <boost/static_assert.hpp>
37 #include "../Utils/pool_alloc_mixin.hh"
38 #include "PacketTypes.hh"
39 #include "../Utils/singleton.hh"
40
41 //#include "PacketImpl.mpp"
42 ///////////////////////////////hh.p////////////////////////////////////////
43
44 namespace senf {
45
46     /** \brief Marker base-class for complex annotations
47
48         This class is used as a base class to mark an annotation type as complex. A complex
49         annotation will have it's constructor/destructor called. Non-complex annotations will not
50         have their constructor called, they will be zero initialized. The destructor of non-complex
51         annotations is never called.
52
53         An annotation must be marked as complex if it is not <a
54         href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">POD</a>. Simplified, an
55         annotation must be marked as ComplexAnnotation, if
56
57         \li it has a (user defined) constructor or destructor
58         \li it has any data members which have (user defined) constructors or destructors
59
60         \see \ref packet_usage_annotation
61      */
62     struct ComplexAnnotation {};
63
64 namespace detail {
65
66     struct AnnotationP
67     {
68         virtual ~AnnotationP();
69     };
70
71     template <class Annotation>
72     struct TAnnotationP
73         : public AnnotationP
74     {
75         Annotation annotation;
76     };
77
78     union AnnotationEntry {
79         AnnotationP * p;
80         unsigned long long i;
81     };
82
83     struct AnnotationIndexerBase
84     {
85         static unsigned maxAnnotations;
86         static std::vector<bool> & small();
87     };
88
89     template <class Annotation>
90     struct AnnotationIndexer 
91         : public senf::singleton< AnnotationIndexer<Annotation> >, 
92           public AnnotationIndexerBase
93     {
94         AnnotationIndexer();
95         unsigned index_;
96         static unsigned index();
97         static bool const Complex = boost::is_base_of<ComplexAnnotation, Annotation>::value;
98         static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) && ! Complex);
99
100 #       if 0 // The test is difficult since it does not work with user-defined trivial constructors
101 #       ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
102
103         BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value 
104                                && boost::has_trivial_destructor<Annotation>::value)
105                               || Complex ));
106
107 #       endif
108 #       endif
109     };
110
111     template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
112     struct GetAnnotation
113     {
114         static Annotation & get(AnnotationEntry & e);
115     };
116
117     template <class Annotation>
118     struct GetAnnotation<Annotation, true>
119     {
120         static Annotation & get(AnnotationEntry & e);
121     };
122
123     /** \brief Internal: Packet data storage
124
125         \internal
126
127         This is the class holding the packet data and the interpreter chain. All manipulations of
128         the packet data are performed via the interface exported here. This is very important, since
129         PacketImpl will update the interpreters (that is the vector indices stored therein) whenever
130         the data is changed.
131      */
132     class PacketImpl
133         : boost::noncopyable,
134           public pool_alloc_mixin<PacketImpl>
135     {
136     public:
137         typedef senf::detail::packet::byte byte;
138         typedef senf::detail::packet::raw_container raw_container;
139         typedef senf::detail::packet::size_type size_type;
140         typedef senf::detail::packet::difference_type difference_type;
141         typedef senf::detail::packet::interpreter_list interpreter_list;
142         typedef senf::detail::packet::iterator iterator;
143         typedef senf::detail::packet::const_iterator const_iterator;
144         typedef senf::detail::packet::refcount_t refcount_t;
145
146         // structors
147
148         PacketImpl();
149         PacketImpl(size_type size, byte initValue);
150         template <class InputIterator>
151         PacketImpl(InputIterator b, InputIterator e);
152         ~PacketImpl();
153
154         // rerference/memory management
155
156         void add_ref(refcount_t n=1);
157         void release(refcount_t n=1);
158         refcount_t refcount() const;
159
160         // Interpreter chain
161
162         PacketInterpreterBase * first();
163         PacketInterpreterBase * last();
164
165         PacketInterpreterBase * next(PacketInterpreterBase * p);
166         PacketInterpreterBase * prev(PacketInterpreterBase * p);
167
168         void appendInterpreter    (PacketInterpreterBase * p);
169         void prependInterpreter   (PacketInterpreterBase * p);
170         void truncateInterpreters (PacketInterpreterBase * p);
171         void truncateInterpretersBackwards (PacketInterpreterBase * p);
172
173         // Data container
174
175         iterator begin();
176         iterator end();
177         size_type size();
178
179         void insert(PacketData * self, iterator pos, byte v);
180         void insert(PacketData * self, iterator pos, size_type n, byte v);
181         template <class ForwardIterator>
182         void insert(PacketData * self, iterator pos, ForwardIterator f, ForwardIterator l);
183
184         void erase(PacketData * self, iterator pos);
185         void erase(PacketData * self, iterator first, iterator last);
186         void clear(PacketData * self);
187
188         void reserve(size_type n);
189         size_type capacity() const;
190
191         // Annotations
192         template <class Annotation>
193         Annotation & annotation();
194
195         /** \brief Internal: Keep PacketImpl instance alive
196
197             \internal
198
199             The Guard will keep the PacketImpl instance alive during a members execution time
200             It the refcount should drop to 0, PacketImpl will be deleted after the member
201             has completed executing.
202          */
203         struct Guard {
204             Guard(PacketImpl * impl);
205             ~Guard();
206             PacketImpl * p;
207         };
208
209     private:
210         refcount_t refcount_;
211         raw_container data_;
212         interpreter_list interpreters_;
213         
214         typedef std::vector<AnnotationEntry> Annotations;
215         Annotations annotations_;
216
217         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
218         void updateIterators(PacketData * self, difference_type pos, difference_type n);
219     };
220
221 }}
222
223 ///////////////////////////////hh.e////////////////////////////////////////
224 #endif
225 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
226 #define HH_SENF_Packets_PacketImpl_i_
227 #include "PacketImpl.cci"
228 //#include "PacketImpl.ct"
229 #include "PacketImpl.cti"
230 #endif
231
232 \f
233 // Local Variables:
234 // mode: c++
235 // fill-column: 100
236 // c-file-style: "senf"
237 // indent-tabs-mode: nil
238 // ispell-local-dictionary: "american"
239 // compile-command: "scons -u test"
240 // comment-column: 40
241 // End:
242