libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_CONTAINER_MEMORY_MAPPED_DATASET_VECTOR_HPP__ 00029 #define MOOST_CONTAINER_MEMORY_MAPPED_DATASET_VECTOR_HPP__ 00030 00031 #include <string> 00032 #include <stdexcept> 00033 #include <iterator> 00034 00035 #include <boost/type_traits/is_pod.hpp> 00036 #include <boost/noncopyable.hpp> 00037 00038 #include "section_writer_base.hpp" 00039 00040 namespace moost { namespace container { 00041 00052 template <typename T> 00053 class mmd_vector : public boost::noncopyable 00054 { 00055 BOOST_STATIC_ASSERT_MSG(boost::is_pod<T>::value, "mmd_vector<> template can only handle POD types"); 00056 00057 public: 00058 static const size_t MMD_VECTOR_ALIGNMENT = 16; 00059 00060 typedef const T& const_reference; 00061 typedef const T *const_iterator; 00062 typedef size_t size_type; 00063 typedef T value_type; 00064 typedef const T* const_pointer; 00065 typedef std::random_access_iterator_tag iterator_category; 00066 00067 class writer : public mmd_section_writer_base 00068 { 00069 public: 00070 // required to make push_back work with std::back_inserter() 00071 typedef const T& const_reference; 00072 typedef size_t size_type; 00073 typedef T value_type; 00074 00075 writer(memory_mapped_dataset::writer& wr, const std::string& name, size_t alignment = MMD_VECTOR_ALIGNMENT) 00076 : mmd_section_writer_base(wr, name, "mmd_vector", alignment) 00077 , m_size(0) 00078 { 00079 setattr("elem_size", sizeof(value_type)); 00080 } 00081 00082 writer& operator<< (const_reference e) 00083 { 00084 push_back(e); 00085 return *this; 00086 } 00087 00088 void push_back(const_reference e) 00089 { 00090 write(e); 00091 ++m_size; 00092 } 00093 00094 size_type size() const 00095 { 00096 return m_size; 00097 } 00098 00099 protected: 00100 void pre_commit() 00101 { 00102 setattr("size", m_size); 00103 } 00104 00105 private: 00106 size_type m_size; 00107 }; 00108 00109 mmd_vector() 00110 : m_begin(0) 00111 , m_end(0) 00112 { 00113 } 00114 00115 mmd_vector(const memory_mapped_dataset& mmd, const std::string& name) 00116 { 00117 set(mmd, name); 00118 } 00119 00120 void set(const memory_mapped_dataset& mmd, const std::string& name) 00121 { 00122 const memory_mapped_dataset::section_info& info = mmd.find(name, "mmd_vector"); 00123 00124 if (info.getattr<size_t>("elem_size") != sizeof(T)) 00125 { 00126 throw std::runtime_error("wrong element size for vector " + name + " in dataset " + mmd.description()); 00127 } 00128 00129 size_type size = info.getattr<size_type>("size"); 00130 m_begin = mmd.data<T>(info.offset(), size); 00131 m_end = m_begin + size; 00132 } 00133 00134 void warm_cache() const 00135 { 00136 memory_mapped_dataset::warm_cache(m_begin, m_end); 00137 } 00138 00139 const_iterator begin() const 00140 { 00141 return m_begin; 00142 } 00143 00144 const_iterator end() const 00145 { 00146 return m_end; 00147 } 00148 00149 size_type size() const 00150 { 00151 return m_end - m_begin; 00152 } 00153 00154 bool empty() const 00155 { 00156 return size() == 0; 00157 } 00158 00159 const_reference operator[] (size_type ix) const 00160 { 00161 return m_begin[ix]; 00162 } 00163 00164 private: 00165 const_iterator m_begin; 00166 const_iterator m_end; 00167 }; 00168 00169 }} 00170 00171 #endif