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/strings/stringprintf.h" 11 12 #if defined(OS_WIN) 13 14 namespace courgette { 15 16 // TempFile 17 18 TempFile::TempFile() : file_(base::kInvalidPlatformFileValue) { 19 } 20 21 TempFile::~TempFile() { 22 Close(); 23 } 24 25 void TempFile::Close() { 26 if (valid()) { 27 base::ClosePlatformFile(file_); 28 file_ = base::kInvalidPlatformFileValue; 29 } 30 } 31 32 bool TempFile::Create() { 33 DCHECK(file_ == base::kInvalidPlatformFileValue); 34 base::FilePath path; 35 if (!base::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 51 bool TempFile::valid() const { 52 return file_ != base::kInvalidPlatformFileValue; 53 } 54 55 base::PlatformFile TempFile::handle() const { 56 return file_; 57 } 58 59 bool TempFile::SetSize(size_t size) { 60 return base::TruncatePlatformFile(file_, size); 61 } 62 63 // FileMapping 64 65 FileMapping::FileMapping() : mapping_(NULL), view_(NULL) { 66 } 67 68 FileMapping::~FileMapping() { 69 Close(); 70 } 71 72 bool 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 83 bool 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 93 void FileMapping::Close() { 94 if (view_) 95 ::UnmapViewOfFile(view_); 96 if (mapping_) 97 ::CloseHandle(mapping_); 98 mapping_ = NULL; 99 view_ = NULL; 100 } 101 102 bool FileMapping::valid() const { 103 return view_ != NULL; 104 } 105 106 void* FileMapping::view() const { 107 return view_; 108 } 109 110 // TempMapping 111 112 TempMapping::TempMapping() { 113 } 114 115 TempMapping::~TempMapping() { 116 } 117 118 bool 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 136 void* 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 146 bool TempMapping::valid() const { 147 return mapping_.valid(); 148 } 149 150 // static 151 TempMapping* 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