CGEM BOSS 6.6.5.h
BESIII Offline Software System
Loading...
Searching...
No Matches
PagedMemory.h
Go to the documentation of this file.
1//Dear emacs, this is -*- c++ -*-
2
3/**
4 * @file eformat/PagedMemory.h
5 * @author <a href="mailto:[email protected]">Andre DOS ANJOS</a>
6 * $Author: maqm $
7 * $Revision: 1.2 $
8 * $Date: 2011/03/09 23:25:55 $
9 *
10 * @brief Represents and facilitates access to a linked list of eformat::node's
11 */
12
13#ifndef EFORMAT_PAGEDMEMORY_H
14#define EFORMAT_PAGEDMEMORY_H
15
16#include <stdint.h>
17#include <sys/uio.h>
18#include "eformat/util.h"
22
23/**
24 * Defines how to cast to 32-bit unsigned integers
25 */
26#define CAST32(x) reinterpret_cast<const uint32_t*>(x)
27
28namespace eformat {
29
30 /**
31 * A list of nodes. To gain speed, the PagedMemory uses an internal page
32 * index. The default maximum size of this index is 128. The user can
33 * instanciate bigger PagedMemory objects by increasing the default template
34 * parameter size to a more suitable value.
35 *
36 * @warn <b>Attention:</b> PagedMemory's with different index sizes cannot
37 * interact directly.
38 */
39 template <unsigned int TMAXPAGES=128> class PagedMemory {
40
41 public: //export template symbol
42
43 static const unsigned int MAXPAGES;
44
45 public: //interface
46
47 /**
48 * Simpler constructor: starts from an existing set of base addresses and
49 * sizes. Please note that for reasons of simplicity, the data in all
50 * memory blocks have to be 32-bit aligned. Otherwise, the implementation
51 * should be DC::Buffer, where this has all been thought about.
52 *
53 * Also note that this class is intended for reading data and optimized for
54 * such. If you just want to manipulate fragments you are better doing it
55 * your self or using the writing part of the library.
56 *
57 * @param pages The memory area I would like to read data from
58 * @param count The number of pages pointed by the variable pages. This
59 * has to be smaller than TMAXPAGES.
60 */
61 PagedMemory (const struct iovec* pages, size_t count);
62
63 /**
64 * Returns the base address of the input IO vector
65 */
66 inline const struct iovec* pages (void) const { return m_iovec; }
67
68 /**
69 * Returns the number of blocks in this IO vector
70 */
71 inline size_t count (void) const { return m_count; }
72
73 /**
74 * Returns the size in bytes words for this PagedMemory.
75 */
76 inline size_t size (void) const { return m_size; }
77
78 public: //indexing
79
80 /**
81 * Define a private type that is used to index the access to this type of
82 * eformat::Memory. The performance of this iterator is dependent on the
83 * distance from the current offset and on the page sizes. Try to use the
84 * iterator for small scale reach and readjust if necessary.
85 */
86 typedef struct node_t {
87 const struct iovec* page; //a pointer to the page
88 size_t start; //the cumulative, logical start of this page in words
89 size_t end; //the cumulative, logical end of this page in words
90 node_t* previous; //the previos page
91 node_t* next; //the next page
93
94 public: //iteration
95
96 /**
97 * Defines an iterator-like type for this type of memory. There are no
98 * guarantees on the iteration. The user should test and only iterate from
99 * begin() till end()
100 */
102
103 private: //only parent class can use this
104
105 friend class PagedMemory;
106
107 /**
108 * Builds a new iterator giving an index and an offset inside that
109 * index.
110 *
111 * @param base The base address of the memory block being pointed now
112 * @param size The total size of this block, in 32-bit words
113 * @param offset The offset to where I should point to, in 32-bit words
114 */
115 const_iterator (const node_t* node, size_t offset)
116 : m_node(node), m_off(offset) {}
117
118
119 public: //access methods
120
121 /**
122 * Returns an iterator that points nowhere, to fake similar behaviour as
123 * the normal pointers.
124 */
125 const_iterator () : m_node(), m_off() {}
126
127 /**
128 * Copies the value of an iterator
129 *
130 * @param other The iterator to copy the data from
131 */
133 : m_node(other.m_node), m_off(other.m_off) {}
134
135 /**
136 * Destroys an iterator
137 */
139
140 /**
141 * Copies the value of an iterator
142 *
143 * @param other The iterator to copy the data from
144 */
146
147 /**
148 * Compares two pointers
149 *
150 * @param other The other iterator to compare this one with.
151 */
152 bool operator!= (const const_iterator& other) const;
153
154 /**
155 * Compares two pointers
156 *
157 * @param other The other iterator to compare this one with.
158 */
159 inline bool operator== (const const_iterator& other) const
160 { return !(*this != other); }
161
162 /**
163 * Gets a value away N positions from this iterator, unchecked
164 *
165 * @param pos The number "N" of positions away from this iterator
166 */
167 uint32_t operator[] (size_t pos) const;
168
169 /**
170 * Gets a value away N positions from this iterator, checked and may
171 * throw an exception
172 *
173 * @param pos The number "N" of positions away from this iterator
174 */
175 uint32_t at (size_t pos) const;
176
177 /**
178 * Gets the current value for the pointed position, as a 32-bit
179 * integer. This is unchecked so you have to make sure you are before
180 * end().
181 */
182 inline uint32_t operator* (void) const
183 { return CAST32(m_node->page->iov_base)[m_off-m_node->start]; }
184
185 /**
186 * Advances forward on the pointing place, 4 bytes or 1 word. This is the
187 * @b prefix operator.
188 */
190
191 /**
192 * Step back on the pointing place, 4 bytes or 1 word. This is the
193 * @b prefix operator.
194 */
196
197 /**
198 * Advances forward on the pointing place, by a number of (32-bit) words
199 *
200 * @param offset The amount of words to advance
201 */
202 const_iterator& operator+= (size_t offset);
203
204 /**
205 * Retrocesses on the pointing place, by a number of (32-bit) words
206 *
207 * @param offset The amount of words to advance
208 */
209 const_iterator& operator-= (size_t offset);
210
211 /**
212 * Compares two operators (offset comparison)
213 *
214 * @param other The other iterator to compare to
215 */
216 inline bool operator< (const const_iterator& other) const
217 { return m_off < other.m_off; }
218
219 /**
220 * Compares two operators (offset comparison)
221 *
222 * @param other The other iterator to compare to
223 */
224 inline bool operator> (const const_iterator& other) const
225 { return m_off > other.m_off; }
226
227 /**
228 * Returns the difference in position between two iterators
229 *
230 * @param other The other iterator to compare to
231 */
232 inline int32_t operator- (const const_iterator& other) const
233 { return (int32_t)m_off - (int32_t)other.m_off; }
234
235 private: //representation
236
237 const node_t* m_node; ///< base address of the index table
238 size_t m_off; ///< the current offset, in 32-bit words
239
240 };
241
242 public: //more interface declarations
243
244 /**
245 * Returns a const iterator to the begin of this list
246 *
247 * @param it An <em>updateable</em> iterator you should provide.
248 */
249 inline const_iterator begin (void) const
250 { return const_iterator(m_node, 0); }
251
252 /**
253 * Returns a const iterator to the end of this list
254 *
255 * @param it An <em>updateable</em> iterator you should provide.
256 */
257 inline const_iterator end (void) const
258 { return const_iterator(&m_node[m_count], m_size); }
259
260 private: //representation
261
262 const struct iovec* m_iovec; ///< my iovec set of pages
263 size_t m_count; ///< how many pages do I have in the list above
264 node_t m_node[TMAXPAGES]; ///< index
265 size_t m_size; ///< the number of words I have in this Memory
266
267 };
268
269}
270
271template <unsigned int TMAXPAGES> const unsigned int
273
274template <unsigned int TMAXPAGES> eformat::PagedMemory<TMAXPAGES>::PagedMemory
275(const struct iovec* pages, size_t count)
276 : m_iovec(pages),
277 m_count(count),
278 m_size(0)
279{
280 if (m_count > MAXPAGES) {
281 //Problem, I cannot index this amount of data
283 }
284 for (size_t i=0; i<count; ++i) {
285 m_node[i].page = &pages[i];
286 if (pages[i].iov_len % 4 != 0) {
287 //Problem, one of the data blocks is *not* 32-bit aligned
288 throw EFORMAT_NOT_ALIGNED(pages[i].iov_base, pages[i].iov_len);
289 }
290 m_node[i].start = m_size;
291 m_size += pages[i].iov_len >> 2;
292 m_node[i].end = m_size;
293 if (i > 0) m_node[i].previous = &m_node[i-1];
294 else m_node[i].previous = 0;
295 if (i < (count-1) ) m_node[i].next = &m_node[i+1];
296 else m_node[i].next = 0;
297 }
298}
299
300template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
303{
304 m_node = other.m_node;
305 m_off = other.m_off;
306 return *this;
307}
308
309template <unsigned int TMAXPAGES>
311(const typename eformat::PagedMemory<TMAXPAGES>::const_iterator& other) const
312{
313 return (m_node == other.m_node && m_off == other.m_off)?false:true;
314}
315
316template <unsigned int TMAXPAGES>
318(size_t pos) const
319{
320 if (m_off + pos < m_node->end) { //trying to reach data on the current page
321 return CAST32(m_node->page->iov_base)[(m_off+pos)-m_node->start];
322 }
323 //otherwise it is not on this page, I have to find the page
324 const_iterator it = *this;
325 it += pos;
326 return *it;
327}
328
329template <unsigned int TMAXPAGES>
331{
332 //immediate return (most of the cases)
333 if (m_off + pos < m_node->end) { //trying to reach data on the current page
334 return CAST32(m_node->page->iov_base)[(m_off+pos)-m_node->start];
335 }
336
337 //immediate points of failure
338 if (!m_node || (m_node->next == 0 && (m_off+pos) >= m_node->end))
339 throw EFORMAT_OUT_OF_BOUNDS(0, pos << 2);
340
341 //if I get here, the data is on another page and the request might still be
342 //out of bounds, so watch.
343 const_iterator it = *this;
344 it += pos;
345 return it.at(0);
346}
347
348template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
350{
351 ++m_off;
352 if ( m_off >= (m_node->end) ) {
353 if (!m_node->next) { //it was the last
354 m_off = m_node->end;
355 return *this;
356 }
357 m_node = m_node->next;
358 m_off = m_node->start;
359 }
360 return *this;
361}
362
363template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
365{
366 --m_off;
367 if ( m_off < (m_node->start) ) {
368 if (!m_node->previous) { //it was the last
369 m_off = m_node->start;
370 return *this;
371 }
372 m_node = m_node->previous;
373 m_off = m_node->end - 1;
374 }
375 return *this;
376}
377
378template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
380{
381 size_t aim = offset + m_off;
382 while (aim >= (m_node->end)) {
383 if (m_node->next) m_node = m_node->next;
384 else { //it was the last
385 m_off = m_node->end;
386 return *this;
387 }
388 }
389 m_off = aim;
390 return *this;
391}
392
393template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
395{
396 size_t aim = m_off - offset;
397 while (aim < (m_node->start)) {
398 if (m_node->previous) m_node = m_node->previous;
399 else { //it was the first
400 m_off = m_node->start;
401 return *this;
402 }
403 }
404 m_off = aim;
405 return *this;
406}
407
408#endif /* EFORMAT_PAGEDMEMORY_H */
Describes the exception where some chunk of memory is not 32-bit aligned.
#define EFORMAT_NOT_ALIGNED(base, size)
Out of bounds exception when trying to read beyond existing buffers.
#define EFORMAT_OUT_OF_BOUNDS(size, pos)
#define CAST32(x)
Definition PagedMemory.h:26
Describes an exception that happens when the total number of blocks I'm managing is bigger than the o...
#define EFORMAT_TOO_BIG_COUNT(count, maxcount)
uint32_t operator[](size_t pos) const
bool operator!=(const const_iterator &other) const
const_iterator & operator=(const const_iterator &other)
const_iterator(const const_iterator &other)
const_iterator & operator+=(size_t offset)
const_iterator & operator++(void)
uint32_t at(size_t pos) const
bool operator==(const const_iterator &other) const
const_iterator & operator-=(size_t offset)
bool operator>(const const_iterator &other) const
bool operator<(const const_iterator &other) const
int32_t operator-(const const_iterator &other) const
size_t size(void) const
Definition PagedMemory.h:76
PagedMemory(const struct iovec *pages, size_t count)
size_t count(void) const
Definition PagedMemory.h:71
const struct iovec * pages(void) const
Definition PagedMemory.h:66
static const unsigned int MAXPAGES
Definition PagedMemory.h:43
struct eformat::PagedMemory::node_t node_t
const_iterator begin(void) const
const_iterator end(void) const
const struct iovec * page
Definition PagedMemory.h:87
Defines a set of utilities common to many event operations.