Home | History | Annotate | Download | only in courgette
      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