Home | History | Annotate | Download | only in files
      1 // Copyright 2013 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 #ifndef BASE_FILES_MEMORY_MAPPED_FILE_H_
      6 #define BASE_FILES_MEMORY_MAPPED_FILE_H_
      7 
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 #include "base/base_export.h"
     12 #include "base/files/file.h"
     13 #include "base/macros.h"
     14 #include "build/build_config.h"
     15 
     16 #if defined(OS_WIN)
     17 #include <windows.h>
     18 #endif
     19 
     20 namespace base {
     21 
     22 class FilePath;
     23 
     24 class BASE_EXPORT MemoryMappedFile {
     25  public:
     26   enum Access {
     27     // Mapping a file into memory effectively allows for file I/O on any thread.
     28     // The accessing thread could be paused while data from the file is paged
     29     // into memory. Worse, a corrupted filesystem could cause a SEGV within the
     30     // program instead of just an I/O error.
     31     READ_ONLY,
     32 
     33     // This provides read/write access to a file and must be used with care of
     34     // the additional subtleties involved in doing so. Though the OS will do
     35     // the writing of data on its own time, too many dirty pages can cause
     36     // the OS to pause the thread while it writes them out. The pause can
     37     // be as much as 1s on some systems.
     38     READ_WRITE,
     39 
     40     // This provides read/write access but with the ability to write beyond
     41     // the end of the existing file up to a maximum size specified as the
     42     // "region". Depending on the OS, the file may or may not be immediately
     43     // extended to the maximum size though it won't be loaded in RAM until
     44     // needed. Note, however, that the maximum size will still be reserved
     45     // in the process address space.
     46     READ_WRITE_EXTEND,
     47   };
     48 
     49   // The default constructor sets all members to invalid/null values.
     50   MemoryMappedFile();
     51   ~MemoryMappedFile();
     52 
     53   // Used to hold information about a region [offset + size] of a file.
     54   struct BASE_EXPORT Region {
     55     static const Region kWholeFile;
     56 
     57     bool operator==(const Region& other) const;
     58     bool operator!=(const Region& other) const;
     59 
     60     // Start of the region (measured in bytes from the beginning of the file).
     61     int64_t offset;
     62 
     63     // Length of the region in bytes.
     64     int64_t size;
     65   };
     66 
     67   // Opens an existing file and maps it into memory. |access| can be read-only
     68   // or read/write but not read/write+extend. If this object already points
     69   // to a valid memory mapped file then this method will fail and return
     70   // false. If it cannot open the file, the file does not exist, or the
     71   // memory mapping fails, it will return false.
     72   bool Initialize(const FilePath& file_name, Access access);
     73   bool Initialize(const FilePath& file_name) {
     74     return Initialize(file_name, READ_ONLY);
     75   }
     76 
     77   // As above, but works with an already-opened file. |access| can be read-only
     78   // or read/write but not read/write+extend. MemoryMappedFile takes ownership
     79   // of |file| and closes it when done. |file| must have been opened with
     80   // permissions suitable for |access|. If the memory mapping fails, it will
     81   // return false.
     82   bool Initialize(File file, Access access);
     83   bool Initialize(File file) {
     84     return Initialize(std::move(file), READ_ONLY);
     85   }
     86 
     87   // As above, but works with a region of an already-opened file. All forms of
     88   // |access| are allowed. If READ_WRITE_EXTEND is specified then |region|
     89   // provides the maximum size of the file. If the memory mapping fails, it
     90   // return false.
     91   bool Initialize(File file, const Region& region, Access access);
     92   bool Initialize(File file, const Region& region) {
     93     return Initialize(std::move(file), region, READ_ONLY);
     94   }
     95 
     96   const uint8_t* data() const { return data_; }
     97   uint8_t* data() { return data_; }
     98   size_t length() const { return length_; }
     99 
    100   // Is file_ a valid file handle that points to an open, memory mapped file?
    101   bool IsValid() const;
    102 
    103  private:
    104   // Given the arbitrarily aligned memory region [start, size], returns the
    105   // boundaries of the region aligned to the granularity specified by the OS,
    106   // (a page on Linux, ~32k on Windows) as follows:
    107   // - |aligned_start| is page aligned and <= |start|.
    108   // - |aligned_size| is a multiple of the VM granularity and >= |size|.
    109   // - |offset| is the displacement of |start| w.r.t |aligned_start|.
    110   static void CalculateVMAlignedBoundaries(int64_t start,
    111                                            int64_t size,
    112                                            int64_t* aligned_start,
    113                                            int64_t* aligned_size,
    114                                            int32_t* offset);
    115 
    116   // Map the file to memory, set data_ to that memory address. Return true on
    117   // success, false on any kind of failure. This is a helper for Initialize().
    118   bool MapFileRegionToMemory(const Region& region, Access access);
    119 
    120   // Closes all open handles.
    121   void CloseHandles();
    122 
    123   File file_;
    124   uint8_t* data_;
    125   size_t length_;
    126 
    127 #if defined(OS_WIN)
    128   win::ScopedHandle file_mapping_;
    129 #endif
    130 
    131   DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
    132 };
    133 
    134 }  // namespace base
    135 
    136 #endif  // BASE_FILES_MEMORY_MAPPED_FILE_H_
    137