summaryrefslogtreecommitdiffstats
path: root/courgette/memory_allocator.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-01 00:19:02 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-01 00:19:02 +0000
commitfbd31eb81436cf7f6d4f9ea3683c100f112361e6 (patch)
treeb0c191290d86ac3a70209fb0984320a88c1e3c07 /courgette/memory_allocator.cc
parent4b764ded93509c0a58a1a8cca10b0964fdcca41d (diff)
downloadchromium_src-fbd31eb81436cf7f6d4f9ea3683c100f112361e6.zip
chromium_src-fbd31eb81436cf7f6d4f9ea3683c100f112361e6.tar.gz
chromium_src-fbd31eb81436cf7f6d4f9ea3683c100f112361e6.tar.bz2
Implementation of an STL compatible allocator for Courgette on Windows.
This is to better handle low memory situations when applying a differential patch to a large Chrome setup. For reading input files, I'm also switching to using memory mapped files instead of ReadFileToString to reduce the load on the heap. TEST=courgette.exe should succeed in applying a patch between two chrome 10.x archives on an XP machine with 180MB of physical memory and no page file. BUG=72459,73209 Review URL: http://codereview.chromium.org/6597038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76320 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette/memory_allocator.cc')
-rw-r--r--courgette/memory_allocator.cc152
1 files changed, 152 insertions, 0 deletions
diff --git a/courgette/memory_allocator.cc b/courgette/memory_allocator.cc
new file mode 100644
index 0000000..06a0653
--- /dev/null
+++ b/courgette/memory_allocator.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "courgette/memory_allocator.h"
+
+#include <map>
+
+#include "base/file_util.h"
+
+#ifdef OS_WIN
+
+namespace courgette {
+
+// TempFile
+
+TempFile::TempFile() : file_(base::kInvalidPlatformFileValue), size_(0) {
+}
+
+TempFile::~TempFile() {
+ Close();
+}
+
+void TempFile::Close() {
+ if (valid()) {
+ base::ClosePlatformFile(file_);
+ file_ = base::kInvalidPlatformFileValue;
+ size_ = 0;
+ }
+}
+
+bool TempFile::Create() {
+ DCHECK(file_ == base::kInvalidPlatformFileValue);
+ FilePath path;
+ if (file_util::CreateTemporaryFile(&path)) {
+ bool created = false;
+ base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
+ int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE |
+ base::PLATFORM_FILE_DELETE_ON_CLOSE |
+ base::PLATFORM_FILE_TEMPORARY;
+ file_ = base::CreatePlatformFile(path, flags, &created, &error_code);
+ PLOG_IF(ERROR, file_ == base::kInvalidPlatformFileValue)
+ << "CreatePlatformFile";
+ }
+ return valid();
+}
+
+bool TempFile::valid() const {
+ return file_ != base::kInvalidPlatformFileValue;
+}
+
+base::PlatformFile TempFile::handle() const {
+ return file_;
+}
+
+size_t TempFile::size() const {
+ return size_;
+}
+
+bool TempFile::SetSize(size_t size) {
+ bool ret = base::TruncatePlatformFile(file_, size);
+ if (ret)
+ size_ = size;
+ return ret;
+}
+
+// FileMapping
+
+FileMapping::FileMapping() : mapping_(NULL), view_(NULL) {
+}
+
+FileMapping::~FileMapping() {
+ Close();
+}
+
+bool FileMapping::Create(HANDLE file, size_t size) {
+ DCHECK(file != INVALID_HANDLE_VALUE);
+ DCHECK(!valid());
+ mapping_ = ::CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 0, NULL);
+ if (mapping_)
+ view_ = ::MapViewOfFile(mapping_, FILE_MAP_WRITE, 0, 0, size);
+
+ if (!valid()) {
+ PLOG(ERROR) << "Failed to map file";
+ Close();
+ }
+
+ return valid();
+}
+
+void FileMapping::Close() {
+ if (view_)
+ ::UnmapViewOfFile(view_);
+ if (mapping_)
+ ::CloseHandle(mapping_);
+ mapping_ = NULL;
+ view_ = NULL;
+}
+
+bool FileMapping::valid() const {
+ return view_ != NULL;
+}
+
+void* FileMapping::view() const {
+ return view_;
+}
+
+// TempMapping
+
+TempMapping::TempMapping() {
+}
+
+TempMapping::~TempMapping() {
+}
+
+bool TempMapping::Initialize(size_t size) {
+ // TODO(tommi): The assumption here is that the alignment of pointers (this)
+ // is as strict or stricter than the alignment of the element type. This is
+ // not always true, e.g. __m128 has 16-byte alignment.
+ size += sizeof(this);
+ bool ret = file_.Create() && file_.SetSize(size) &&
+ mapping_.Create(file_.handle(), size);
+ if (ret) {
+ TempMapping** write = reinterpret_cast<TempMapping**>(mapping_.view());
+ write[0] = this;
+ }
+
+ return ret;
+}
+
+void* TempMapping::memory() const {
+ uint8* mem = reinterpret_cast<uint8*>(mapping_.view());
+ if (mem)
+ mem += sizeof(this);
+ DCHECK(mem);
+ return mem;
+}
+
+// static
+TempMapping* TempMapping::GetMappingFromPtr(void* mem) {
+ TempMapping* ret = NULL;
+ if (mem) {
+ ret = reinterpret_cast<TempMapping**>(mem)[-1];
+ }
+ DCHECK(ret);
+ return ret;
+}
+
+} // namespace courgette
+
+#endif // OS_WIN