• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MmapHandle(void * start,size_t num_bytes)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.
start()46   void *start() const { return start_; }
47 
48   // Returns number of bytes of the memory area from start().
num_bytes()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.
ok()53   bool ok() const { return start() != nullptr; }
54 
55   // Returns a StringPiece pointing to the same underlying bytes.
to_stringpiece()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:
ScopedMmap(const std::string & filename)99   explicit ScopedMmap(const std::string &filename)
100       : handle_(MmapFile(filename)) {}
101 
ScopedMmap(int fd)102   explicit ScopedMmap(int fd)
103       : handle_(MmapFile(fd)) {}
104 
~ScopedMmap()105   ~ScopedMmap() {
106     if (handle_.ok()) {
107       Unmap(handle_);
108     }
109   }
110 
handle()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