/home/bes3soft/bes3soft/Boss/7.0.2/dist/7.0.2/Event/eformat/eformat-00-00-04/eformat/PagedMemory.h

Go to the documentation of this file.
00001 //Dear emacs, this is -*- c++ -*-
00002 
00013 #ifndef EFORMAT_PAGEDMEMORY_H
00014 #define EFORMAT_PAGEDMEMORY_H
00015 
00016 #include <stdint.h>
00017 #include <sys/uio.h>
00018 #include "eformat/util.h"
00019 #include "eformat/TooBigCountIssue.h"
00020 #include "eformat/NotAlignedIssue.h"
00021 #include "eformat/OutOfBoundsIssue.h"
00022 
00026 #define CAST32(x) reinterpret_cast<const uint32_t*>(x)
00027 
00028 namespace eformat {
00029 
00039   template <unsigned int TMAXPAGES=128> class PagedMemory {
00040 
00041   public: //export template symbol
00042 
00043     static const unsigned int MAXPAGES;
00044 
00045   public: //interface
00046 
00061     PagedMemory (const struct iovec* pages, size_t count);
00062 
00066     inline const struct iovec* pages (void) const { return m_iovec; }
00067 
00071     inline size_t count (void) const { return m_count; }
00072 
00076     inline size_t size (void) const { return m_size; }
00077 
00078   public: //indexing
00079 
00086     typedef struct node_t {
00087       const struct iovec* page; //a pointer to the page
00088       size_t start; //the cumulative, logical start of this page in words
00089       size_t end; //the cumulative, logical end of this page in words
00090       node_t* previous; //the previos page
00091       node_t* next; //the next page
00092     } node_t;
00093 
00094   public: //iteration
00095 
00101     class const_iterator {
00102 
00103     private: //only parent class can use this
00104       
00105       friend class PagedMemory;
00106 
00115       const_iterator (const node_t* node, size_t offset)
00116         : m_node(node), m_off(offset) {}
00117       
00118 
00119     public: //access methods
00120 
00125       const_iterator () : m_node(), m_off() {}
00126 
00132       const_iterator (const const_iterator& other)
00133         : m_node(other.m_node), m_off(other.m_off) {}
00134 
00138       ~const_iterator () {}
00139 
00145       const_iterator& operator= (const const_iterator& other);
00146 
00152       bool operator!= (const const_iterator& other) const;
00153 
00159       inline bool operator== (const const_iterator& other) const
00160       { return !(*this != other); }
00161 
00167       uint32_t operator[] (size_t pos) const;
00168 
00175       uint32_t at (size_t pos) const;
00176 
00182       inline uint32_t operator* (void) const 
00183       { return CAST32(m_node->page->iov_base)[m_off-m_node->start]; }
00184 
00189       const_iterator& operator++ (void);
00190 
00195       const_iterator& operator-- ();
00196 
00202       const_iterator& operator+= (size_t offset);
00203 
00209       const_iterator& operator-= (size_t offset);
00210 
00216       inline bool operator< (const const_iterator& other) const
00217       { return m_off < other.m_off; }
00218 
00224       inline bool operator> (const const_iterator& other) const
00225       { return m_off > other.m_off; }
00226 
00232       inline int32_t operator- (const const_iterator& other) const
00233       { return (int32_t)m_off - (int32_t)other.m_off; }
00234 
00235     private: //representation
00236 
00237       const node_t* m_node; 
00238       size_t m_off; 
00239 
00240     };
00241 
00242   public: //more interface declarations
00243 
00249     inline const_iterator begin (void) const 
00250     { return const_iterator(m_node, 0); }
00251 
00257     inline const_iterator end (void) const
00258     { return const_iterator(&m_node[m_count], m_size); }
00259 
00260   private: //representation
00261 
00262     const struct iovec* m_iovec; 
00263     size_t m_count; 
00264     node_t m_node[TMAXPAGES]; 
00265     size_t m_size; 
00266 
00267   };
00268 
00269 }
00270 
00271 template <unsigned int TMAXPAGES> const unsigned int 
00272 eformat::PagedMemory<TMAXPAGES>::MAXPAGES = TMAXPAGES;
00273 
00274 template <unsigned int TMAXPAGES> eformat::PagedMemory<TMAXPAGES>::PagedMemory 
00275 (const struct iovec* pages, size_t count)
00276   : m_iovec(pages),
00277     m_count(count),
00278     m_size(0)
00279 {
00280   if (m_count > MAXPAGES) {
00281     //Problem, I cannot index this amount of data
00282     throw EFORMAT_TOO_BIG_COUNT(count, MAXPAGES);
00283   }
00284   for (size_t i=0; i<count; ++i) {
00285     m_node[i].page = &pages[i];
00286     if (pages[i].iov_len % 4 != 0) {
00287       //Problem, one of the data blocks is *not* 32-bit aligned
00288       throw EFORMAT_NOT_ALIGNED(pages[i].iov_base, pages[i].iov_len);
00289     }
00290     m_node[i].start = m_size;
00291     m_size += pages[i].iov_len >> 2;
00292     m_node[i].end = m_size;
00293     if (i > 0) m_node[i].previous = &m_node[i-1];
00294     else m_node[i].previous = 0;
00295     if (i < (count-1) ) m_node[i].next = &m_node[i+1];
00296     else m_node[i].next = 0;
00297   }
00298 }
00299 
00300 template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
00301 eformat::PagedMemory<TMAXPAGES>::const_iterator::operator=
00302   (const typename eformat::PagedMemory<TMAXPAGES>::const_iterator& other)
00303 {
00304   m_node = other.m_node;
00305   m_off = other.m_off;
00306   return *this;
00307 }
00308 
00309 template <unsigned int TMAXPAGES>
00310 bool eformat::PagedMemory<TMAXPAGES>::const_iterator::operator!= 
00311 (const typename eformat::PagedMemory<TMAXPAGES>::const_iterator& other) const
00312 {
00313   return (m_node == other.m_node && m_off == other.m_off)?false:true;
00314 }
00315 
00316 template <unsigned int TMAXPAGES> 
00317 uint32_t eformat::PagedMemory<TMAXPAGES>::const_iterator::operator[] 
00318 (size_t pos) const
00319 {
00320   if (m_off + pos < m_node->end) { //trying to reach data on the current page
00321     return CAST32(m_node->page->iov_base)[(m_off+pos)-m_node->start];
00322   }
00323   //otherwise it is not on this page, I have to find the page
00324   const_iterator it = *this;
00325   it += pos;
00326   return *it;
00327 }
00328 
00329 template <unsigned int TMAXPAGES>
00330 uint32_t eformat::PagedMemory<TMAXPAGES>::const_iterator::at (size_t pos) const
00331 {
00332   //immediate return (most of the cases)
00333   if (m_off + pos < m_node->end) { //trying to reach data on the current page
00334     return CAST32(m_node->page->iov_base)[(m_off+pos)-m_node->start];
00335   }
00336 
00337   //immediate points of failure
00338   if (!m_node || (m_node->next == 0 && (m_off+pos) >= m_node->end))
00339     throw EFORMAT_OUT_OF_BOUNDS(0, pos << 2);
00340 
00341   //if I get here, the data is on another page and the request might still be
00342   //out of bounds, so watch.
00343   const_iterator it = *this;
00344   it += pos;
00345   return it.at(0);
00346 }
00347 
00348 template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
00349 eformat::PagedMemory<TMAXPAGES>::const_iterator::operator++ (void)
00350 { 
00351   ++m_off;
00352   if ( m_off >= (m_node->end) ) {
00353     if (!m_node->next) { //it was the last
00354       m_off = m_node->end;
00355       return *this;
00356     }
00357     m_node = m_node->next;
00358     m_off = m_node->start;
00359   }
00360   return *this; 
00361 }
00362 
00363 template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
00364 eformat::PagedMemory<TMAXPAGES>::const_iterator::operator-- (void)
00365 { 
00366   --m_off;
00367   if ( m_off < (m_node->start) ) {
00368     if (!m_node->previous) { //it was the last
00369       m_off = m_node->start;
00370       return *this;
00371     }
00372     m_node = m_node->previous;
00373     m_off = m_node->end - 1;
00374   }
00375   return *this; 
00376 }
00377 
00378 template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
00379 eformat::PagedMemory<TMAXPAGES>::const_iterator::operator+= (size_t offset) 
00380 {
00381   size_t aim = offset + m_off;
00382   while (aim >= (m_node->end)) {
00383     if (m_node->next) m_node = m_node->next;
00384     else { //it was the last
00385       m_off = m_node->end;
00386       return *this;
00387     }
00388   }
00389   m_off = aim;
00390   return *this;
00391 }
00392 
00393 template <unsigned int TMAXPAGES> typename eformat::PagedMemory<TMAXPAGES>::const_iterator&
00394 eformat::PagedMemory<TMAXPAGES>::const_iterator::operator-= (size_t offset) 
00395 {
00396   size_t aim = m_off - offset;
00397   while (aim < (m_node->start)) {
00398     if (m_node->previous) m_node = m_node->previous;
00399     else { //it was the first
00400       m_off = m_node->start;
00401       return *this;
00402     }
00403   }
00404   m_off = aim;
00405   return *this;
00406 }
00407 
00408 #endif /* EFORMAT_PAGEDMEMORY_H */

Generated on Tue Nov 29 22:58:25 2016 for BOSS_7.0.2 by  doxygen 1.4.7