MemoryMapping
[folly.git] / folly / MemoryMapping.h
1 /*
2  * Copyright 2013 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
59   virtual ~MemoryMapping();
60
61   /**
62    * Lock the pages in memory
63    */
64   bool mlock(LockMode lock);
65
66   /**
67    * Unlock the pages.
68    * If dontneed is true, the kernel is instructed to release these pages
69    * (per madvise(MADV_DONTNEED)).
70    */
71   void munlock(bool dontneed=false);
72
73   /**
74    * Hint that these pages will be scanned linearly.
75    * madvise(MADV_SEQUENTIAL)
76    */
77   void hintLinearScan();
78
79   /**
80    * Advise the kernel about memory access.
81    */
82   void advise(int advice) const;
83
84   /**
85    * A bitwise cast of the mapped bytes as range of values. Only intended for
86    * use with POD or in-place usable types.
87    */
88   template<class T>
89   Range<const T*> asRange() const {
90     CHECK(mapStart_);
91     size_t count = data_.size() / sizeof(T);
92     return Range<const T*>(static_cast<const T*>(
93                              static_cast<const void*>(data_.data())),
94                            count);
95   }
96
97   /**
98    * A range of bytes mapped by this mapping.
99    */
100   Range<const uint8_t*> range() const {
101     return {data_.begin(), data_.end()};
102   }
103
104   /**
105    * Return the memory area where the file was mapped.
106    */
107   ByteRange data() const {
108     return range();
109   }
110
111   bool mlocked() const {
112     return locked_;
113   }
114
115  protected:
116   MemoryMapping();
117
118   void init(File file,
119             off_t offset, off_t length,
120             int prot,
121             bool grow);
122
123   File file_;
124   void* mapStart_;
125   off_t mapLength_;
126   bool locked_;
127   Range<uint8_t*> data_;
128 };
129
130 /**
131  * Maps files in memory for writing.
132  *
133  * @author Tom Jackson (tjackson@fb.com)
134  */
135 class WritableMemoryMapping : public MemoryMapping {
136  public:
137   explicit WritableMemoryMapping(File file,
138                                  off_t offset = 0,
139                                  off_t length = -1);
140   /**
141    * A bitwise cast of the mapped bytes as range of mutable values. Only
142    * intended for use with POD or in-place usable types.
143    */
144   template<class T>
145   Range<T*> asWritableRange() const {
146     CHECK(mapStart_);
147     size_t count = data_.size() / sizeof(T);
148     return Range<T*>(static_cast<T*>(
149                        static_cast<void*>(data_.data())),
150                      count);
151   }
152
153   /**
154    * A range of mutable bytes mapped by this mapping.
155    */
156   Range<uint8_t*> writableRange() const {
157     return data_;
158   }
159 };
160
161 }  // namespace folly
162
163 #endif /* FOLLY_MEMORYMAPPING_H_ */