Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef LIBTEXTCLASSIFIER_COMMON_MMAP_H_
     18 #define LIBTEXTCLASSIFIER_COMMON_MMAP_H_
     19 
     20 #include <stddef.h>
     21 
     22 #include <string>
     23 
     24 #include "util/strings/stringpiece.h"
     25 
     26 namespace libtextclassifier {
     27 namespace nlp_core {
     28 
     29 // Handle for a memory area where a file has been mmapped.
     30 //
     31 // Similar to a pointer: you "allocate" it using MmapFile(filename) and "delete"
     32 // it using Unmap().  Just like a pointer, it is passed around by value (see
     33 // signature of MmapFile and Unmap; fortunately, it's a small class, so there
     34 // shouldn't be any significant performance penalty) and its usage is not
     35 // necessarily scoped (that's why the destructor is not performing the unmap).
     36 //
     37 // Note: on program termination, each still unmapped file is automatically
     38 // unmapped.  Hence, it is not an error if you don't call Unmap() (provided you
     39 // are ok keeping that file in memory the whole time).
     40 class MmapHandle {
     41  public:
     42   MmapHandle(void *start, size_t num_bytes)
     43       : start_(start), num_bytes_(num_bytes) {}
     44 
     45   // Returns start address for the memory area where a file has been mmapped.
     46   void *start() const { return start_; }
     47 
     48   // Returns number of bytes of the memory area from start().
     49   size_t num_bytes() const { return num_bytes_; }
     50 
     51   // Shortcut to simplify checking success of MmapFile().  See usage example
     52   // from the doc of that function.
     53   bool ok() const { return start() != nullptr; }
     54 
     55   // Returns a StringPiece pointing to the same underlying bytes.
     56   StringPiece to_stringpiece() const {
     57     return StringPiece(reinterpret_cast<char *>(start_), num_bytes_);
     58   }
     59 
     60  private:
     61   // See doc for start().  Not owned.
     62   void *const start_;
     63 
     64   // See doc for num_bytes().
     65   const size_t num_bytes_;
     66 };
     67 
     68 // Maps the full content of a file in memory (using mmap).
     69 //
     70 // When done using the file content, one can unmap using Unmap().  Otherwise,
     71 // all mapped files are unmapped when the program terminates.
     72 //
     73 // Sample usage:
     74 //
     75 // MmapHandle mmap_handle = MmapFile(filename);
     76 // TC_DCHECK(mmap_handle.ok()) << "Unable to mmap " << filename;
     77 //
     78 // ... use data from addresses
     79 // ... [mmap_handle.start, mmap_handle.start + mmap_handle.num_bytes)
     80 //
     81 // Unmap(mmap_handle);  // Unmap logs errors internally.
     82 //
     83 // Note: one can read *and* write the num_bytes bytes from start, but those
     84 // writes are not propagated to the underlying file, nor to other processes that
     85 // may have mmapped that file (all changes are local to current process).
     86 MmapHandle MmapFile(const std::string &filename);
     87 
     88 // Like MmapFile(const std::string &filename), but uses a file descriptor.
     89 MmapHandle MmapFile(int fd);
     90 
     91 // Unmaps a file mapped using MmapFile.  Returns true on success, false
     92 // otherwise.
     93 bool Unmap(MmapHandle mmap_handle);
     94 
     95 // Scoped mmapping of a file.  Mmaps a file on construction, unmaps it on
     96 // destruction.
     97 class ScopedMmap {
     98  public:
     99   explicit ScopedMmap(const std::string &filename)
    100       : handle_(MmapFile(filename)) {}
    101 
    102   explicit ScopedMmap(int fd)
    103       : handle_(MmapFile(fd)) {}
    104 
    105   ~ScopedMmap() {
    106     if (handle_.ok()) {
    107       Unmap(handle_);
    108     }
    109   }
    110 
    111   const MmapHandle &handle() { return handle_; }
    112 
    113  private:
    114   MmapHandle handle_;
    115 };
    116 
    117 }  // namespace nlp_core
    118 }  // namespace libtextclassifier
    119 
    120 #endif  // LIBTEXTCLASSIFIER_COMMON_MMAP_H_
    121