Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: courgette/memory_allocator.h

Issue 6597038: Implementation of an STL compatible allocator for Courgette on Windows.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « courgette/ensemble_apply.cc ('k') | courgette/memory_allocator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef COURGETTE_MEMORY_ALLOCATOR_H_
6 #define COURGETTE_MEMORY_ALLOCATOR_H_
7
8 #include <memory>
9
10 #include "base/basictypes.h"
11 #include "base/logging.h"
12 #include "base/platform_file.h"
13
14 namespace courgette {
15
16 #ifdef OS_WIN
17
18 // Manages a temporary file. The file is created in the %TEMP% folder and
19 // is deleted when the file handle is closed.
20 // NOTE: Since the file will be used as backing for a memory allocation,
21 // it will never be so big that size_t cannot represent its size.
22 class TempFile {
23 public:
24 TempFile();
25 ~TempFile();
26
27 bool Create();
28 void Close();
29 bool SetSize(size_t size);
30
31 // Returns true iff the temp file is currently open.
32 bool valid() const;
33
34 // Returns the handle of the temporary file or INVALID_HANDLE_VALUE if
35 // a temp file has not been created.
36 base::PlatformFile handle() const;
37
38 // Returns the size of the temp file. If the temp file doesn't exist,
39 // the return value is 0.
40 size_t size() const;
41
42 protected:
43 base::PlatformFile file_;
44 size_t size_;
45 };
46
47 // Manages a read/write virtual mapping of a physical file.
48 class FileMapping {
49 public:
50 FileMapping();
51 ~FileMapping();
52
53 // Map a file from beginning to |size|.
54 bool Create(HANDLE file, size_t size);
55 void Close();
56
57 // Returns true iff a mapping has been created.
58 bool valid() const;
59
60 // Returns a writable pointer to the beginning of the memory mapped file.
61 // If Create has not been called successfully, return value is NULL.
62 void* view() const;
63
64 protected:
65 HANDLE mapping_;
66 void* view_;
67 };
68
69 // Manages a temporary file and a memory mapping of the temporary file.
70 // The memory that this class manages holds a pointer back to the TempMapping
71 // object itself, so that given a memory pointer allocated by this class,
72 // you can get a pointer to the TempMapping instance that owns that memory.
73 class TempMapping {
74 public:
75 TempMapping();
76 ~TempMapping();
77
78 // Creates a temporary file of size |size| and maps it into the current
79 // process' address space.
80 bool Initialize(size_t size);
81
82 // Returns a writable pointer to the reserved memory.
83 void* memory() const;
84
85 // Returns a pointer to the TempMapping instance that allocated the |mem|
86 // block of memory. It's the callers responsibility to make sure that
87 // the memory block was allocated by the TempMapping class.
88 static TempMapping* GetMappingFromPtr(void* mem);
89
90 protected:
91 TempFile file_;
92 FileMapping mapping_;
93 };
94
95 // An STL compatible memory allocator class that allocates memory either
96 // from the heap or via a temporary file. A file allocation will be made
97 // if either the requested memory size exceeds |kMaxHeapAllocationSize|
98 // or if a heap allocation fails.
99 // Allocating the memory as a mapping of a temporary file solves the problem
100 // that there might not be enough physical memory and pagefile to support the
101 // allocation. This can happen because these resources are too small, or
102 // already committed to other processes. Provided there is enough disk, the
103 // temporary file acts like a pagefile that other processes can't access.
104 template<class T>
105 class MemoryAllocator {
106 public:
107 typedef T value_type;
108 typedef value_type* pointer;
109 typedef value_type& reference;
110 typedef const value_type* const_pointer;
111 typedef const value_type& const_reference;
112 typedef size_t size_type;
113 typedef ptrdiff_t difference_type;
114
115 // Each allocation is tagged with a single byte so that we know how to
116 // deallocate it.
117 enum AllocationType {
118 HEAP_ALLOCATION,
119 FILE_ALLOCATION,
120 };
121
122 // 5MB is the maximum heap allocation size that we'll attempt.
123 // When applying a patch for Chrome 10.X we found that at this
124 // threshold there were 17 allocations higher than this threshold
125 // (largest at 136MB) 10 allocations just below the threshold and 6362
126 // smaller allocations.
127 static const size_t kMaxHeapAllocationSize = 1024 * 1024 * 5;
128
129 template<class OtherT>
130 struct rebind {
131 // convert an MemoryAllocator<T> to a MemoryAllocator<OtherT>
132 typedef MemoryAllocator<OtherT> other;
133 };
134
135 MemoryAllocator() _THROW0() {
136 }
137
138 explicit MemoryAllocator(const MemoryAllocator<T>& other) _THROW0() {
139 }
140
141 template<class OtherT>
142 explicit MemoryAllocator(const MemoryAllocator<OtherT>& other) _THROW0() {
143 }
144
145 ~MemoryAllocator() {
146 }
147
148 void deallocate(pointer ptr, size_type size) {
149 uint8* mem = reinterpret_cast<uint8*>(ptr);
150 mem -= sizeof(T);
151 if (mem[0] == HEAP_ALLOCATION) {
152 delete [] mem;
153 } else {
154 DCHECK_EQ(static_cast<uint8>(FILE_ALLOCATION), mem[0]);
155 TempMapping* mapping = TempMapping::GetMappingFromPtr(mem);
156 delete mapping;
157 }
158 }
159
160 pointer allocate(size_type count) {
161 // We use the first byte of each allocation to mark the allocation type.
162 // However, so that the allocation is properly aligned, we allocate an
163 // extra element and then use the first byte of the first element
164 // to mark the allocation type.
165 count++;
166
167 if (count > max_size())
168 throw std::length_error("overflow");
169
170 size_type bytes = count * sizeof(T);
171 uint8* mem = NULL;
172
173 // First see if we can do this allocation on the heap.
174 if (count < kMaxHeapAllocationSize)
175 mem = new(std::nothrow) uint8[bytes];
176 if (mem != NULL) {
177 mem[0] = static_cast<uint8>(HEAP_ALLOCATION);
178 } else {
179 // If either the heap allocation failed or the request exceeds the
180 // max heap allocation threshold, we back the allocation with a temp file.
181 TempMapping* mapping = new TempMapping();
182 if (!mapping->Initialize(bytes)) {
183 delete mapping;
184 throw std::bad_alloc("TempMapping::Initialize");
185 }
186 mem = reinterpret_cast<uint8*>(mapping->memory());
187 mem[0] = static_cast<uint8>(FILE_ALLOCATION);
188 }
189 return reinterpret_cast<pointer>(mem + sizeof(T));
190 }
191
192 pointer allocate(size_type count, const void* hint) {
193 return allocate(count);
194 }
195
196 void construct(pointer ptr, const T& value) {
197 ::new(ptr) T(value);
198 }
199
200 void destroy(pointer ptr) {
201 ptr->~T();
202 }
203
204 size_t max_size() const _THROW0() {
205 size_type count = static_cast<size_type>(-1) / sizeof(T);
206 return (0 < count ? count : 1);
207 }
208 };
209
210 #else // OS_WIN
211
212 // On Mac, Linux, we just use the default STL allocator.
213 template<class T>
214 class MemoryAllocator : public std::allocator<T> {
215 public:
216 };
217
218 #endif // OS_WIN
219
220 } // namespace courgette
221
222 #endif // COURGETTE_MEMORY_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « courgette/ensemble_apply.cc ('k') | courgette/memory_allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698