std::move-able MemoryMapping
[folly.git] / folly / MemoryMapping.h
1 /*
2  * Copyright 2014 Facebook, Inc.
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 FOLLY_MEMORYMAPPING_H_
18 #define FOLLY_MEMORYMAPPING_H_
19
20 #include "folly/FBString.h"
21 #include "folly/File.h"
22 #include "folly/Range.h"
23 #include <glog/logging.h>
24 #include <boost/noncopyable.hpp>
25
26 namespace folly {
27
28 /**
29  * Maps files in memory (read-only).
30  *
31  * @author Tudor Bosman (tudorb@fb.com)
32  */
33 class MemoryMapping : boost::noncopyable {
34  public:
35   /**
36    * Lock the pages in memory?
37    * TRY_LOCK  = try to lock, log warning if permission denied
38    * MUST_LOCK = lock, fail assertion if permission denied.
39    */
40   enum class LockMode {
41     TRY_LOCK,
42     MUST_LOCK
43   };
44   /**
45    * Map a portion of the file indicated by filename in memory, causing a CHECK
46    * failure on error.
47    *
48    * By default, map the whole file.  length=-1: map from offset to EOF.
49    * Unlike the mmap() system call, offset and length don't need to be
50    * page-aligned.  length is clipped to the end of the file if it's too large.
51    *
52    * The mapping will be destroyed (and the memory pointed-to by data() will
53    * likely become inaccessible) when the MemoryMapping object is destroyed.
54    */
55   explicit MemoryMapping(File file,
56                          off_t offset=0,
57                          off_t length=-1,
58                          off_t pageSize=0);
59
60   explicit MemoryMapping(const char* name,
61                          off_t offset=0,
62                          off_t length=-1,
63                          off_t pageSize=0);
64
65   explicit MemoryMapping(int fd,
66                          off_t offset=0,
67                          off_t length=-1,
68                          off_t pageSize=0);
69
70   MemoryMapping(MemoryMapping&&);
71
72   virtual ~MemoryMapping();
73
74   MemoryMapping& operator=(MemoryMapping);
75
76   void swap(MemoryMapping& other);
77
78   /**
79    * Lock the pages in memory
80    */
81   bool mlock(LockMode lock);
82
83   /**
84    * Unlock the pages.
85    * If dontneed is true, the kernel is instructed to release these pages
86    * (per madvise(MADV_DONTNEED)).
87    */
88   void munlock(bool dontneed = false);
89
90   /**
91    * Hint that these pages will be scanned linearly.
92    * madvise(MADV_SEQUENTIAL)
93    */
94   void hintLinearScan();
95
96   /**
97    * Advise the kernel about memory access.
98    */
99   void advise(int advice) const;
100
101   /**
102    * A bitwise cast of the mapped bytes as range of values. Only intended for
103    * use with POD or in-place usable types.
104    */
105   template<class T>
106   Range<const T*> asRange() const {
107     size_t count = data_.size() / sizeof(T);
108     return Range<const T*>(static_cast<const T*>(
109                              static_cast<const void*>(data_.data())),
110                            count);
111   }
112
113   /**
114    * A range of bytes mapped by this mapping.
115    */
116   Range<const uint8_t*> range() const {
117     return {data_.begin(), data_.end()};
118   }
119
120   /**
121    * Return the memory area where the file was mapped.
122    */
123   StringPiece data() const {
124     return asRange<const char>();
125   }
126
127   bool mlocked() const {
128     return locked_;
129   }
130
131   int fd() const { return file_.fd(); }
132
133  protected:
134   MemoryMapping();
135
136   void init(File file,
137             off_t offset, off_t length,
138             off_t pageSize,
139             int prot,
140             bool grow);
141
142   File file_;
143   void* mapStart_;
144   off_t mapLength_;
145   off_t pageSize_;
146   bool locked_;
147   Range<uint8_t*> data_;
148 };
149
150 /**
151  * Maps files in memory for writing.
152  *
153  * @author Tom Jackson (tjackson@fb.com)
154  */
155 class WritableMemoryMapping : public MemoryMapping {
156  public:
157   explicit WritableMemoryMapping(File file,
158                                  off_t offset = 0,
159                                  off_t length = -1,
160                                  off_t pageSize = 0);
161   /**
162    * A bitwise cast of the mapped bytes as range of mutable values. Only
163    * intended for use with POD or in-place usable types.
164    */
165   template<class T>
166   Range<T*> asWritableRange() const {
167     size_t count = data_.size() / sizeof(T);
168     return Range<T*>(static_cast<T*>(
169                        static_cast<void*>(data_.data())),
170                      count);
171   }
172
173   /**
174    * A range of mutable bytes mapped by this mapping.
175    */
176   Range<uint8_t*> writableRange() const {
177     return data_;
178   }
179 };
180
181 void swap(MemoryMapping&, MemoryMapping&);
182
183 }  // namespace folly
184
185 #endif /* FOLLY_MEMORYMAPPING_H_ */