libmoost
/home/mhx/git/github/libmoost/include/moost/container/memory_mapped_dataset/vector.hpp
Go to the documentation of this file.
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