LSan: invoke leak detection in RendererMain() on renderer exit.
[chromium-blink-merge.git] / courgette / memory_allocator.cc
blob5b92c8003060d03483b8178bdc68dcda1442f31b
1 // Copyright (c) 2012 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.
5 #include "courgette/memory_allocator.h"
7 #include <map>
9 #include "base/files/file_util.h"
10 #include "base/strings/stringprintf.h"
12 #if defined(OS_WIN)
14 namespace {
16 // The file is created in the %TEMP% folder.
17 // NOTE: Since the file will be used as backing for a memory allocation,
18 // it will never be so big that size_t cannot represent its size.
19 base::File CreateTempFile() {
20 base::FilePath path;
21 if (!base::CreateTemporaryFile(&path))
22 return base::File();
24 int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
25 base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
26 base::File::FLAG_TEMPORARY;
27 return base::File(path, flags);
30 } // namespace
32 namespace courgette {
34 // FileMapping
36 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) {
39 FileMapping::~FileMapping() {
40 Close();
43 bool FileMapping::InitializeView(size_t size) {
44 DCHECK(view_ == NULL);
45 DCHECK(mapping_ != NULL);
46 view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size);
47 if (!view_) {
48 Close();
49 return false;
51 return true;
54 bool FileMapping::Create(HANDLE file, size_t size) {
55 DCHECK(file != INVALID_HANDLE_VALUE);
56 DCHECK(!valid());
57 mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL);
58 if (!mapping_)
59 return false;
61 return InitializeView(size);
64 void FileMapping::Close() {
65 if (view_)
66 ::UnmapViewOfFile(view_);
67 if (mapping_)
68 ::CloseHandle(mapping_);
69 mapping_ = NULL;
70 view_ = NULL;
73 bool FileMapping::valid() const {
74 return view_ != NULL;
77 void* FileMapping::view() const {
78 return view_;
81 // TempMapping
83 TempMapping::TempMapping() {
86 TempMapping::~TempMapping() {
89 bool TempMapping::Initialize(size_t size) {
90 file_ = CreateTempFile();
91 if (!file_.IsValid())
92 return false;
94 // TODO(tommi): The assumption here is that the alignment of pointers (this)
95 // is as strict or stricter than the alignment of the element type. This is
96 // not always true, e.g. __m128 has 16-byte alignment.
97 size += sizeof(this);
98 if (!file_.SetLength(size) ||
99 !mapping_.Create(file_.GetPlatformFile(), size)) {
100 file_.Close();
101 return false;
104 TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view());
105 write[0] = this;
107 return true;
110 void* TempMapping::memory() const {
111 uint8* mem = reinterpret_cast<uint8*>(mapping_.view());
112 // The 'this' pointer is written at the start of mapping_.view(), so
113 // go past it. (See Initialize()).
114 if (mem)
115 mem += sizeof(this);
116 DCHECK(mem);
117 return mem;
120 bool TempMapping::valid() const {
121 return mapping_.valid();
124 // static
125 TempMapping* TempMapping::GetMappingFromPtr(void* mem) {
126 TempMapping* ret = NULL;
127 if (mem) {
128 ret = reinterpret_cast<TempMapping**>(mem)[-1];
130 DCHECK(ret);
131 return ret;
134 } // namespace courgette
136 #endif // OS_WIN