switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Packets / PacketImpl.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief PacketImpl public header */
30
31 #ifndef HH_SENF_Packets_PacketImpl_
32 #define HH_SENF_Packets_PacketImpl_ 1
33
34 // Custom includes
35 #include <memory>
36 #include <vector>
37 #include <boost/utility.hpp>
38 #include <boost/static_assert.hpp>
39 #include <boost/ptr_container/ptr_vector.hpp>
40 #include <senf/Utils/pool_alloc_mixin.hh>
41 #include <senf/Utils/singleton.hh>
42
43 //#include "PacketImpl.mpp"
44 #include "PacketImpl.ih"
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46
47 namespace senf {
48
49     /** \brief Marker base-class for complex annotations
50
51         This class is used as a base class to mark an annotation type as complex. A complex
52         annotation will have it's constructor/destructor called. Non-complex annotations will not
53         have their constructor called, they will be zero initialized. The destructor of non-complex
54         annotations is never called.
55
56         An annotation must be marked as complex if it is not <a
57         href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">POD</a>. Simplified, an
58         annotation must be marked as ComplexAnnotation, if
59
60         \li it has a (user defined) constructor or destructor
61         \li it has any data members which have (user defined) constructors or destructors
62
63         \see \ref packet_usage_annotation
64      */
65     struct ComplexAnnotation {};
66
67     /** \brief Dump annotation registry debug information
68
69         This function will dump debug information about all registered annotations to \a os. This
70         information may then be used to tune the following annotation parameters for optimal
71         performance:
72         \li \c SENF_PACKET_ANNOTATION_SLOTS (define, default 8) is the number of slots available for
73             fast annotations
74         \li \c SENF_PACKET_ANNOTATION_SLOTSIZE (define, default 16) is the maximum size of a fast
75             annotation in bytes
76
77         The output includes the current parameter and has the following columns:
78         \li \c NAME: Annotation type name
79         \li \c FAST: This is 'yes', if the annotation was allocated to a fast slot. Otherwise the
80             annotation is managed as a slow/complex annotation
81         \li \c COMPLEX: This is 'yes', if the annotation inherits from ComplexAnnotation
82         \li \c SIZE: Size of the annotation in bytes
83
84         Fast annotations are considerable faster than complex and slow annotations. However, only
85         annotations which do not need constructor or destructor calls and which may be
86         zero-initialized (on the memory level) are legible as fast annotations.
87
88         It is thus desirable to eliminate any complex and slow annotations, if possible. To optimize
89         the annotation system, you may take the following steps:
90         \li If there are reasonably sized non-complex annotations which are larger than the current
91             \c SENF_PACKET_ANNOTATION_SLOTSIZE value, increase this value accordingly
92         \li If there are more non-complex annotations with a size less than
93             \c SENF_PACKET_ANNOTATION_SLOTSIZE than there are available slots, increase \c
94             SENF_PACKET_ANNOTATION_SLOTS accordingly
95         \li If all fast annotations are smaller than \c SENF_PACKET_ANNOTATION_SLOTSIZE, you may
96             decrease that value accordingly
97         \li If there are fewer than \c SENF_PACKET_ANNOTATION_SLOTS fast annotations, you may
98             decrease that value accordingly
99
100         \see \ref packet_usage_annotation
101      */
102     void dumpPacketAnnotationRegistry(std::ostream & os);
103
104 namespace detail {
105
106     /** \brief Internal: Packet data storage
107
108         \internal
109
110         This is the class holding the packet data and the interpreter chain. All manipulations of
111         the packet data are performed via the interface exported here. This is very important, since
112         PacketImpl will update the interpreters (that is the vector indices stored therein) whenever
113         the data is changed.
114      */
115     class PacketImpl
116         : boost::noncopyable,
117           public pool_alloc_mixin<PacketImpl>
118     {
119     public:
120         typedef senf::detail::packet::byte byte;
121         typedef senf::detail::packet::raw_container raw_container;
122         typedef senf::detail::packet::size_type size_type;
123         typedef senf::detail::packet::difference_type difference_type;
124         typedef senf::detail::packet::interpreter_list interpreter_list;
125         typedef senf::detail::packet::iterator iterator;
126         typedef senf::detail::packet::const_iterator const_iterator;
127         typedef senf::detail::packet::refcount_t refcount_t;
128
129         // structors
130
131         PacketImpl();
132         PacketImpl(size_type size, byte initValue);
133         template <class InputIterator>
134         PacketImpl(InputIterator b, InputIterator e);
135         ~PacketImpl();
136
137         // rerference/memory management
138
139         void add_ref();
140         void release();
141         refcount_t refcount() const;
142
143         // Interpreter chain
144
145         PacketInterpreterBase * first();
146         PacketInterpreterBase * last();
147
148         PacketInterpreterBase * next(PacketInterpreterBase * p);
149         PacketInterpreterBase * prev(PacketInterpreterBase * p);
150
151         void appendInterpreter    (PacketInterpreterBase * p);
152         void prependInterpreter   (PacketInterpreterBase * p);
153         void prependInterpreter   (PacketInterpreterBase * p, PacketInterpreterBase * before);
154         void truncateInterpreters (PacketInterpreterBase * p);
155         void truncateInterpretersBackwards (PacketInterpreterBase * p);
156
157         // Data container
158
159         iterator begin();
160         iterator end();
161         size_type size();
162
163         void insert(PacketData * self, iterator pos, byte v);
164         void insert(PacketData * self, iterator pos, size_type n, byte v);
165         template <class ForwardIterator>
166         void insert(PacketData * self, iterator pos, ForwardIterator f, ForwardIterator l);
167
168         void erase(PacketData * self, iterator pos);
169         void erase(PacketData * self, iterator first, iterator last);
170         void clear(PacketData * self);
171
172         void reserve(size_type n);
173         size_type capacity() const;
174
175         // Annotations
176         template <class Annotation>
177         Annotation & annotation();
178
179         void clearAnnotations();
180         void assignAnnotations(PacketImpl const & other);
181         void dumpAnnotations(std::ostream & os);
182
183         /** \brief Internal: Keep PacketImpl instance alive
184
185             \internal
186
187             The Guard will keep the PacketImpl instance alive during a members execution time
188             It the refcount should drop to 0, PacketImpl will be deleted after the member
189             has completed executing.
190          */
191         struct Guard {
192             Guard(PacketImpl * impl);
193             ~Guard();
194             PacketImpl * p;
195         };
196
197     private:
198         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
199         void updateIterators(PacketData * self, difference_type pos, difference_type n);
200
201         void * annotation(AnnotationRegistry::key_type key); // may return 0 !
202         void * complexAnnotation(AnnotationRegistry::key_type key); // may return 0 !
203         template <class Annotation>
204         void * complexAnnotation();
205
206         refcount_t refcount_;
207         raw_container data_;
208         interpreter_list interpreters_;
209
210         union SimpleAnnotationSlot
211         {
212             unsigned char _ [SENF_PACKET_ANNOTATION_SLOTSIZE];
213         };
214
215         typedef boost::ptr_vector< boost::nullable<AnnotationRegistry::EntryBase> >
216             ComplexAnnotations;
217         ComplexAnnotations complexAnnotations_;
218
219         SimpleAnnotationSlot simpleAnnotations_[SENF_PACKET_ANNOTATION_SLOTS];
220     };
221
222 }}
223
224 //-/////////////////////////////////////////////////////////////////////////////////////////////////
225 #endif
226 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
227 #define HH_SENF_Packets_PacketImpl_i_
228 #include "PacketImpl.cci"
229 #include "PacketImpl.ct"
230 #include "PacketImpl.cti"
231 #endif
232
233 \f
234 // Local Variables:
235 // mode: c++
236 // fill-column: 100
237 // c-file-style: "senf"
238 // indent-tabs-mode: nil
239 // ispell-local-dictionary: "american"
240 // compile-command: "scons -u test"
241 // comment-column: 40
242 // End: