memory_allocator.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.
4
5#include "courgette/memory_allocator.h"
6
7#include <map>
8
9#include "base/file_util.h"
10#include "base/stringprintf.h"
11
12#if defined(OS_WIN)
13
14namespace courgette {
15
16// TempFile
17
18TempFile::TempFile() : file_(base::kInvalidPlatformFileValue) {
19}
20
21TempFile::~TempFile() {
22  Close();
23}
24
25void TempFile::Close() {
26  if (valid()) {
27    base::ClosePlatformFile(file_);
28    file_ = base::kInvalidPlatformFileValue;
29  }
30}
31
32bool TempFile::Create() {
33  DCHECK(file_ == base::kInvalidPlatformFileValue);
34  base::FilePath path;
35  if (!file_util::CreateTemporaryFile(&path))
36    return false;
37
38  bool created = false;
39  base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
40  int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ |
41              base::PLATFORM_FILE_WRITE |
42              base::PLATFORM_FILE_DELETE_ON_CLOSE |
43              base::PLATFORM_FILE_TEMPORARY;
44  file_ = base::CreatePlatformFile(path, flags, &created, &error_code);
45  if (file_ == base::kInvalidPlatformFileValue)
46    return false;
47
48  return true;
49}
50
51bool TempFile::valid() const {
52  return file_ != base::kInvalidPlatformFileValue;
53}
54
55base::PlatformFile TempFile::handle() const {
56  return file_;
57}
58
59bool TempFile::SetSize(size_t size) {
60  return base::TruncatePlatformFile(file_, size);
61}
62
63// FileMapping
64
65FileMapping::FileMapping() : mapping_(NULL), view_(NULL) {
66}
67
68FileMapping::~FileMapping() {
69  Close();
70}
71
72bool FileMapping::InitializeView(size_t size) {
73  DCHECK(view_ == NULL);
74  DCHECK(mapping_ != NULL);
75  view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size);
76  if (!view_) {
77    Close();
78    return false;
79  }
80  return true;
81}
82
83bool FileMapping::Create(HANDLE file, size_t size) {
84  DCHECK(file != INVALID_HANDLE_VALUE);
85  DCHECK(!valid());
86  mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL);
87  if (!mapping_)
88    return false;
89
90  return InitializeView(size);
91}
92
93void FileMapping::Close() {
94  if (view_)
95    ::UnmapViewOfFile(view_);
96  if (mapping_)
97    ::CloseHandle(mapping_);
98  mapping_ = NULL;
99  view_ = NULL;
100}
101
102bool FileMapping::valid() const {
103  return view_ != NULL;
104}
105
106void* FileMapping::view() const {
107  return view_;
108}
109
110// TempMapping
111
112TempMapping::TempMapping() {
113}
114
115TempMapping::~TempMapping() {
116}
117
118bool TempMapping::Initialize(size_t size) {
119  // TODO(tommi): The assumption here is that the alignment of pointers (this)
120  // is as strict or stricter than the alignment of the element type.  This is
121  // not always true, e.g. __m128 has 16-byte alignment.
122  size += sizeof(this);
123  if (!file_.Create() ||
124      !file_.SetSize(size) ||
125      !mapping_.Create(file_.handle(), size)) {
126    file_.Close();
127    return false;
128  }
129
130  TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view());
131  write[0] = this;
132
133  return true;
134}
135
136void* TempMapping::memory() const {
137  uint8* mem = reinterpret_cast<uint8*>(mapping_.view());
138  // The 'this' pointer is written at the start of mapping_.view(), so
139  // go past it. (See Initialize()).
140  if (mem)
141    mem += sizeof(this);
142  DCHECK(mem);
143  return mem;
144}
145
146bool TempMapping::valid() const {
147  return mapping_.valid();
148}
149
150// static
151TempMapping* TempMapping::GetMappingFromPtr(void* mem) {
152  TempMapping* ret = NULL;
153  if (mem) {
154    ret = reinterpret_cast<TempMapping**>(mem)[-1];
155  }
156  DCHECK(ret);
157  return ret;
158}
159
160}  // namespace courgette
161
162#endif  // OS_WIN
163