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