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