667eebb151ec9e237711d89891ac433b4b6109a9
[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_PacketImpl_
27 #define HH_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 #       ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
101
102         BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value 
103                                && boost::has_trivial_destructor<Annotation>::value)
104                               || Complex ));
105
106 #       endif
107     };
108
109     template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
110     struct GetAnnotation
111     {
112         static Annotation & get(AnnotationEntry & e);
113     };
114
115     template <class Annotation>
116     struct GetAnnotation<Annotation, true>
117     {
118         static Annotation & get(AnnotationEntry & e);
119     };
120
121     /** \brief Internal: Packet data storage
122
123         \internal
124
125         This is the class holding the packet data and the interpreter chain. All manipulations of
126         the packet data are performed via the interface exported here. This is very important, since
127         PacketImpl will update the interpreters (that is the vector indices stored therein) whenever
128         the data is changed.
129      */
130     class PacketImpl
131         : boost::noncopyable,
132           public pool_alloc_mixin<PacketImpl>
133     {
134     public:
135         typedef senf::detail::packet::byte byte;
136         typedef senf::detail::packet::raw_container raw_container;
137         typedef senf::detail::packet::size_type size_type;
138         typedef senf::detail::packet::difference_type difference_type;
139         typedef senf::detail::packet::interpreter_list interpreter_list;
140         typedef senf::detail::packet::iterator iterator;
141         typedef senf::detail::packet::const_iterator const_iterator;
142         typedef senf::detail::packet::refcount_t refcount_t;
143
144         // structors
145
146         PacketImpl();
147         PacketImpl(size_type size, byte initValue);
148         template <class InputIterator>
149         PacketImpl(InputIterator b, InputIterator e);
150         ~PacketImpl();
151
152         // rerference/memory management
153
154         void add_ref(refcount_t n=1);
155         void release(refcount_t n=1);
156         refcount_t refcount() const;
157
158         // Interpreter chain
159
160         PacketInterpreterBase * first();
161         PacketInterpreterBase * last();
162
163         PacketInterpreterBase * next(PacketInterpreterBase * p);
164         PacketInterpreterBase * prev(PacketInterpreterBase * p);
165
166         void appendInterpreter    (PacketInterpreterBase * p);
167         void prependInterpreter   (PacketInterpreterBase * p);
168         void truncateInterpreters (PacketInterpreterBase * p);
169         void truncateInterpretersBackwards (PacketInterpreterBase * p);
170
171         // Data container
172
173         iterator begin();
174         iterator end();
175         size_type size();
176
177         void insert(PacketData * self, iterator pos, byte v);
178         void insert(PacketData * self, iterator pos, size_type n, byte v);
179         template <class ForwardIterator>
180         void insert(PacketData * self, iterator pos, ForwardIterator f, ForwardIterator l);
181
182         void erase(PacketData * self, iterator pos);
183         void erase(PacketData * self, iterator first, iterator last);
184         void clear(PacketData * self);
185
186         // Annotations
187         template <class Annotation>
188         Annotation & annotation();
189
190         /** \brief Internal: Keep PacketImpl instance alive
191
192             \internal
193
194             The Guard will keep the PacketImpl instance alive during a members execution time
195             It the refcount should drop to 0, PacketImpl will be deleted after the member
196             has completed executing.
197          */
198         struct Guard {
199             Guard(PacketImpl * impl);
200             ~Guard();
201             PacketImpl * p;
202         };
203
204     private:
205         refcount_t refcount_;
206         raw_container data_;
207         interpreter_list interpreters_;
208         
209         typedef std::vector<AnnotationEntry> Annotations;
210         Annotations annotations_;
211
212         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
213         void updateIterators(PacketData * self, difference_type pos, difference_type n);
214     };
215
216 }}
217
218 ///////////////////////////////hh.e////////////////////////////////////////
219 #endif
220 #if !defined(HH_Packets__decls_) && !defined(HH_PacketImpl_i_)
221 #define HH_PacketImpl_i_
222 #include "PacketImpl.cci"
223 //#include "PacketImpl.ct"
224 #include "PacketImpl.cti"
225 #endif
226
227 \f
228 // Local Variables:
229 // mode: c++
230 // fill-column: 100
231 // c-file-style: "senf"
232 // indent-tabs-mode: nil
233 // ispell-local-dictionary: "american"
234 // compile-command: "scons -u test"
235 // comment-column: 40
236 // End:
237