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 <string> 23 24 #include "lang_id/common/lite_strings/stringpiece.h" 25 26 namespace libtextclassifier3 { 27 namespace mobile { 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 // CHECK(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 string &filename); 87 88 // Like MmapFile(const 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 string & filename)99 explicit ScopedMmap(const 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 mobile 118 } // namespace nlp_saft 119 120 #endif // NLP_SAFT_COMPONENTS_COMMON_MOBILE_FILE_MMAP_H_ 121