1 /* 2 * This code is (c) 2012 Johannes Thoma 3 * 4 * This file is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This file is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this file. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * You can download original source from https://github.com/johannesthoma/mmap_allocator.git 18 */ 19 20 #ifndef _MMAPPABLE_VECTOR_H 21 #define _MMAPPABLE_VECTOR_H 22 23 #include <memory> 24 #include <string> 25 #include <stdio.h> 26 #include <vector> 27 #include "mmap_allocator.h" 28 29 namespace mmap_allocator_namespace { 30 // template <typename T, typename A = mmap_allocator<T> > 31 template <typename T, typename A> // A defaults to mmap_allocator<T> : see mmap_allocator.h 32 class mmappable_vector: public std::vector<T, A> { 33 public: 34 typedef std::vector<T, A> Base; 35 36 typedef typename Base::const_iterator const_iterator; 37 typedef typename Base::iterator iterator; 38 typedef T value_type; 39 typedef A allocator_type; 40 mmappable_vector()41 mmappable_vector(): 42 Base() 43 { 44 } 45 mmappable_vector(const mmappable_vector<T,A> & other)46 mmappable_vector(const mmappable_vector<T, A> &other): 47 Base(other) 48 { 49 } 50 mmappable_vector(size_t n)51 explicit mmappable_vector(size_t n): 52 Base() 53 { 54 mmap_file(n); 55 } 56 mmappable_vector(A alloc)57 explicit mmappable_vector(A alloc): 58 Base(alloc) 59 { 60 } 61 mmappable_vector(iterator from,iterator to)62 mmappable_vector(iterator from, iterator to): 63 Base(from, to) 64 { 65 } 66 67 template <typename Iter> 68 mmappable_vector(Iter first, Iter last, A a = A()): Base(first,last,a)69 Base(first, last, a) 70 { 71 } 72 mmappable_vector(int n,T val,A alloc)73 mmappable_vector(int n, T val, A alloc): 74 Base(n, val, alloc) 75 { 76 } 77 mmappable_vector(int n,T val)78 mmappable_vector(int n, T val): 79 Base(n, val) 80 { 81 } 82 mmappable_vector(std::vector<T,std::allocator<T>> v)83 mmappable_vector(std::vector<T,std::allocator<T> > v): 84 std::vector<T,std::allocator<T> >(v) 85 { 86 } 87 88 /* Use this only when the allocator is already initialized. */ mmap_file(size_t n)89 void mmap_file(size_t n) 90 { 91 Base::reserve(n); 92 _M_set_finish(n); 93 } 94 95 void mmap_file(std::string filename, enum access_mode access_mode, const off_t offset, const size_t n, int flags = 0) 96 { 97 if (Base::size() > 0) { 98 throw mmap_allocator_exception("Remapping currently not implemented."); 99 } 100 #ifdef __GNUC__ 101 #if __GNUC__ == 3 102 A *the_allocator = static_cast<A*>(&(this->Base::_M_impl)); 103 #else 104 A *the_allocator = &Base::_M_get_Tp_allocator(); 105 #endif 106 #else 107 #error "Not GNU C++, please either implement me or use GCC" 108 #endif 109 the_allocator->filename = filename; 110 the_allocator->offset = offset; 111 the_allocator->access_mode = access_mode; 112 the_allocator->map_whole_file = (flags & MAP_WHOLE_FILE) != 0; 113 the_allocator->allow_remap = (flags & ALLOW_REMAP) != 0; 114 the_allocator->bypass_file_pool = (flags & BYPASS_FILE_POOL) != 0; 115 the_allocator->keep_forever = (flags & KEEP_FOREVER) != 0; 116 117 mmap_file(n); 118 } 119 munmap_file(void)120 void munmap_file(void) 121 { 122 size_t n = Base::size(); 123 #ifdef __GNUC__ 124 Base::_M_deallocate(Base::_M_impl._M_start, n); 125 Base::_M_impl._M_start = 0; 126 Base::_M_impl._M_finish = 0; 127 Base::_M_impl._M_end_of_storage = 0; 128 #else 129 #error "Not GNU C++, please either implement me or use GCC" 130 #endif 131 } 132 remmap_file_for_read()133 void remmap_file_for_read() 134 { 135 #ifdef __GNUC__ 136 #if __GNUC__ == 3 137 A *the_allocator = static_cast<A*>(&(this->Base::_M_impl)); 138 #else 139 A *the_allocator = &Base::_M_get_Tp_allocator(); 140 #endif 141 #else 142 #error "Not GNU C++, please either implement me or use GCC" 143 #endif 144 the_allocator->private_file.remmap_file_for_read(); 145 } 146 147 private: _M_set_finish(size_t n)148 void _M_set_finish(size_t n) 149 { 150 #ifdef __GNUC__ 151 Base::_M_impl._M_finish = Base::_M_impl._M_start + n; 152 #else 153 #error "Not GNU C++, please either implement me or use GCC" 154 #endif 155 } 156 }; 157 158 template <typename T> to_std_vector(const mmappable_vector<T> & v)159 std::vector<T> to_std_vector(const mmappable_vector<T> &v) 160 { 161 return std::vector<T>(v.begin(), v.end()); 162 } 163 164 template <typename T> to_mmappable_vector(const std::vector<T> & v)165 mmappable_vector<T> to_mmappable_vector(const std::vector<T> &v) 166 { 167 return mmappable_vector<T>(v.begin(), v.end()); 168 } 169 } 170 171 #endif /* MMAPPABLE_VECTOR_H */ 172