Line data Source code
1 : /*
2 : * (C) Copyright 2010 Xilexio
3 : *
4 : * This file is part of CoherentDB.
5 : *
6 : * CoherentDB is free software: you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation, either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * CoherentDB is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public
17 : * License along with CoherentDB. If not, see
18 : * http://www.gnu.org/licenses/.
19 : */
20 :
21 : #ifndef MEMORY_ALLOCATOR_H
22 : #define MEMORY_ALLOCATOR_H
23 :
24 : #include <cstddef>
25 : #include <bits/allocator.h>
26 : #include <sys/mman.h>
27 : #include <memory_manager/session.h>
28 : #include <memory_manager/sub_session.h>
29 : #include <debug/asserts.h>
30 :
31 : namespace coherent
32 : {
33 : namespace memory_manager
34 : {
35 :
36 : typedef boost::shared_lock<boost::shared_mutex> scoped_read_lock;
37 : typedef boost::unique_lock<boost::shared_mutex> scoped_write_lock;
38 : typedef boost::unique_lock<boost::mutex> scoped_lock;
39 :
40 : class out_of_session_memory : public std::exception
41 0 : {
42 0 : virtual const char* what() const throw ()
43 : {
44 0 : return "Insufficent session memory left for memory allocation.";
45 : }
46 : };
47 :
48 : template <class T>
49 : class allocator;
50 :
51 : // specialize for void
52 :
53 : template <>
54 : class allocator<void> : public std::allocator<void>
55 : {
56 : };
57 :
58 : template <class T>
59 : class allocator : public std::allocator<T>
60 : {
61 : public:
62 : typedef size_t size_type;
63 : typedef ptrdiff_t difference_type;
64 : typedef T* pointer;
65 : typedef const T* const_pointer;
66 : typedef T& reference;
67 : typedef const T& const_reference;
68 : typedef T value_type;
69 :
70 : template<typename W>
71 : struct rebind
72 : {
73 : typedef allocator<W> other;
74 : };
75 :
76 8329989 : allocator() throw () : std::allocator<T>()
77 : {
78 8340059 : }
79 :
80 : allocator(const allocator& orig) throw () : std::allocator<T>(orig)
81 : {
82 : }
83 :
84 : template <class U>
85 : allocator(const allocator<U>& orig) throw () : std::allocator<T>(orig)
86 : {
87 : }
88 :
89 8318683 : ~allocator() throw ()
90 : {
91 8318683 : }
92 :
93 4183106 : pointer allocate(size_type n, allocator<void>::const_pointer hint = 0)
94 : {
95 4183106 : if (n == 0)
96 0 : return 0;
97 :
98 4183106 : size_t needed_bytes = sizeof (T) * n;
99 :
100 4183106 : memory_sub_session* mss = memory_sub_session::current();
101 : r_assert(mss);
102 :
103 8350638 : scoped_write_lock als(mss->alloc_lock);
104 :
105 4184902 : memory_session* ms = mss->get_parent();
106 :
107 8359027 : scoped_read_lock ll(ms->limit_lock);
108 8355462 : scoped_write_lock al(ms->alloc_lock);
109 :
110 : // fprintf(stderr, "allocate %d", n * sizeof(T));
111 :
112 4188469 : if (n > max_size_no_lock(ms))
113 0 : throw out_of_session_memory();
114 :
115 4183083 : pointer res = reinterpret_cast<pointer> (mss->allocate(needed_bytes));
116 :
117 : // fprintf(stderr, ";\tcurrent %u\n", ms->allocated_bytes);
118 :
119 4167713 : return res;
120 : }
121 :
122 4179936 : void deallocate(pointer ptr, size_type n)
123 : {
124 4179936 : if (n == 0)
125 0 : return;
126 :
127 4179936 : memory_sub_session* mss = memory_sub_session::current();
128 : r_assert(mss);
129 :
130 8348992 : scoped_write_lock als(mss->alloc_lock);
131 :
132 4185478 : memory_session* ms = mss->get_parent();
133 :
134 8358707 : scoped_read_lock ll(ms->limit_lock);
135 8353099 : scoped_write_lock al(ms->alloc_lock);
136 :
137 4188692 : byte* p = reinterpret_cast<byte*> (ptr);
138 4188692 : size_t bytes = sizeof (T) * n;
139 :
140 : // fprintf(stderr, "deallocate %d", n * sizeof(T));
141 :
142 4188692 : mss->deallocate(p, bytes);
143 :
144 : // fprintf(stderr, ";\tcurrent %u small_allocs %u free_small_chunks %u allocs %u\n free_small_chunks: ", ms->allocated_bytes, ms->small_allocs.size(), ms->free_small_chunks.size(), ms->allocs.size());
145 : // for (std::map<byte*, size_t>::iterator i = ms->free_small_chunks.begin(); i != ms->free_small_chunks.end(); ++i) {
146 : // fprintf(stderr, "%u-%u(%u) ", (unsigned int) i->first, (unsigned int) i->first + i->second - 1, i->second);
147 : // }
148 : // fprintf(stderr, "\n");
149 : }
150 :
151 0 : size_type max_size() const throw ()
152 : {
153 167 : memory_session* ms = memory_session::current();
154 : r_assert(ms);
155 :
156 335 : scoped_read_lock ll(ms->limit_lock);
157 335 : scoped_read_lock al(ms->alloc_lock);
158 :
159 168 : return max_size_no_lock(ms);
160 : }
161 :
162 : private:
163 0 : size_type max_size_no_lock(memory_session* ms) const throw ()
164 : {
165 : d_assert(ms->limit_bytes <= std::allocator<T>::max_size());
166 :
167 4184174 : if (ms->limit_bytes >= ms->allocated_bytes)
168 4184174 : return ms->limit_bytes - ms->allocated_bytes;
169 : else
170 4184174 : return 0;
171 : }
172 : };
173 :
174 : template <class T1, class T2>
175 : bool operator ==(const allocator<T1>&, const allocator<T2>&) throw ()
176 : {
177 : return true;
178 : }
179 :
180 : template <class T1, class T2>
181 : bool operator !=(const allocator<T1>&, const allocator<T2>&) throw ()
182 : {
183 : return false;
184 : }
185 :
186 : template <typename T>
187 : allocator<T>& allocator_instance()
188 : {
189 : static allocator<T> instance;
190 : return instance;
191 : }
192 :
193 : template <typename T>
194 4185140 : T* allocate(size_t size)
195 : {
196 4185140 : return allocator<T > ().allocate(size);
197 : }
198 :
199 : template <typename T>
200 4185566 : void deallocate(T* p, size_t size)
201 : {
202 4185566 : return allocator<T > ().deallocate(p, size);
203 : }
204 :
205 : }
206 : }
207 :
208 : #endif
|