1 /* 2 * Copyright (C) 2018 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 NLP_SAFT_COMPONENTS_COMMON_MOBILE_FILE_MMAP_H_ 18 #define NLP_SAFT_COMPONENTS_COMMON_MOBILE_FILE_MMAP_H_ 19 20 #include <stddef.h> 21 22 #include <cstddef> 23 #include <string> 24 25 #include "lang_id/common/lite_strings/stringpiece.h" 26 27 #ifdef _WIN32 28 #define WIN32_LEAN_AND_MEAN 29 #include <windows.h> 30 #endif 31 32 namespace libtextclassifier3 { 33 namespace mobile { 34 35 // Handle for a memory area where a file has been mmapped. 36 // 37 // Similar to a pointer: you "allocate" it using MmapFile(filename) and "delete" 38 // it using Unmap(). Just like a pointer, it is passed around by value (see 39 // signature of MmapFile and Unmap; fortunately, it's a small class, so there 40 // shouldn't be any significant performance penalty) and its usage is not 41 // necessarily scoped (that's why the destructor is not performing the unmap). 42 // 43 // Note: on program termination, each still unmapped file is automatically 44 // unmapped. Hence, it is not an error if you don't call Unmap() (provided you 45 // are ok keeping that file in memory the whole time). 46 class MmapHandle { 47 public: MmapHandle(void * start,size_t num_bytes)48 MmapHandle(void *start, size_t num_bytes) 49 : start_(start), num_bytes_(num_bytes) {} 50 51 // Returns start address for the memory area where a file has been mmapped. start()52 void *start() const { return start_; } 53 54 // Returns number of bytes of the memory area from start(). num_bytes()55 size_t num_bytes() const { return num_bytes_; } 56 57 // Shortcut to simplify checking success of MmapFile(). See usage example 58 // from the doc of that function. ok()59 bool ok() const { return start() != nullptr; } 60 61 // Returns a StringPiece pointing to the same underlying bytes. to_stringpiece()62 StringPiece to_stringpiece() const { 63 return StringPiece(reinterpret_cast<char *>(start_), num_bytes_); 64 } 65 66 private: 67 // See doc for start(). Not owned. 68 void *const start_; 69 70 // See doc for num_bytes(). 71 const size_t num_bytes_; 72 }; 73 74 // Maps the full content of a file in memory (using mmap). 75 // 76 // When done using the file content, one can unmap using Unmap(). Otherwise, 77 // all mapped files are unmapped when the program terminates. 78 // 79 // Sample usage: 80 // 81 // MmapHandle mmap_handle = MmapFile(filename); 82 // CHECK(mmap_handle.ok()) << "Unable to mmap " << filename; 83 // 84 // ... use data from addresses 85 // ... [mmap_handle.start, mmap_handle.start + mmap_handle.num_bytes) 86 // 87 // Unmap(mmap_handle); // Unmap logs errors internally. 88 // 89 // Note: one can read *and* write the num_bytes bytes from start, but those 90 // writes are not propagated to the underlying file, nor to other processes that 91 // may have mmapped that file (all changes are local to current process). 92 MmapHandle MmapFile(const std::string &filename); 93 94 #ifdef _WIN32 95 using FileDescriptorOrHandle = HANDLE; 96 #else 97 using FileDescriptorOrHandle = int; 98 #endif 99 100 // Like MmapFile(const std::string &filename), but uses a file descriptor. 101 // This function maps the entire file content. 102 MmapHandle MmapFile(FileDescriptorOrHandle fd); 103 104 // Like MmapFile(const std::string &filename), but uses a file descriptor, 105 // with an offset relative to the file start and a specified size, such that we 106 // consider only a range of the file content. 107 MmapHandle MmapFile(FileDescriptorOrHandle fd, size_t offset_in_bytes, 108 size_t size_in_bytes); 109 110 // Unmaps a file mapped using MmapFile. Returns true on success, false 111 // otherwise. 112 bool Unmap(MmapHandle mmap_handle); 113 114 // Scoped mmapping of a file. Mmaps a file on construction, unmaps it on 115 // destruction. 116 class ScopedMmap { 117 public: ScopedMmap(const std::string & filename)118 explicit ScopedMmap(const std::string &filename) 119 : handle_(MmapFile(filename)) {} 120 ScopedMmap(FileDescriptorOrHandle fd)121 explicit ScopedMmap(FileDescriptorOrHandle fd) : handle_(MmapFile(fd)) {} 122 ScopedMmap(FileDescriptorOrHandle fd,size_t offset_in_bytes,size_t size_in_bytes)123 explicit ScopedMmap(FileDescriptorOrHandle fd, size_t offset_in_bytes, 124 size_t size_in_bytes) 125 : handle_(MmapFile(fd, offset_in_bytes, size_in_bytes)) {} 126 ~ScopedMmap()127 ~ScopedMmap() { 128 if (handle_.ok()) { 129 Unmap(handle_); 130 } 131 } 132 handle()133 const MmapHandle &handle() { return handle_; } 134 135 private: 136 MmapHandle handle_; 137 }; 138 139 } // namespace mobile 140 } // namespace nlp_saft 141 142 #endif // NLP_SAFT_COMPONENTS_COMMON_MOBILE_FILE_MMAP_H_ 143