+ advise(advice, 0, size_t(mapLength_));
+}
+
+void MemoryMapping::advise(int advice, size_t offset, size_t length) const {
+ CHECK_LE(offset + length, size_t(mapLength_))
+ << " offset: " << offset
+ << " length: " << length
+ << " mapLength_: " << mapLength_;
+
+ // Include the entire start page: round down to page boundary.
+ const auto offMisalign = offset % options_.pageSize;
+ offset -= offMisalign;
+ length += offMisalign;
+
+ // Round the last page down to page boundary.
+ if (offset + length != size_t(mapLength_)) {
+ length -= length % options_.pageSize;
+ }
+
+ if (length == 0) {
+ return;
+ }
+
+ char* mapStart = static_cast<char*>(mapStart_) + offset;
+ PLOG_IF(WARNING, ::madvise(mapStart, length, advice)) << "madvise";
+}
+
+MemoryMapping& MemoryMapping::operator=(MemoryMapping other) {
+ swap(other);
+ return *this;
+}
+
+void MemoryMapping::swap(MemoryMapping& other) noexcept {
+ using std::swap;
+ swap(this->file_, other.file_);
+ swap(this->mapStart_, other.mapStart_);
+ swap(this->mapLength_, other.mapLength_);
+ swap(this->options_, other.options_);
+ swap(this->locked_, other.locked_);
+ swap(this->data_, other.data_);
+}
+
+void swap(MemoryMapping& a, MemoryMapping& b) noexcept { a.swap(b); }
+
+void alignedForwardMemcpy(void* dst, const void* src, size_t size) {
+ assert(reinterpret_cast<uintptr_t>(src) % alignof(unsigned long) == 0);
+ assert(reinterpret_cast<uintptr_t>(dst) % alignof(unsigned long) == 0);
+
+ auto srcl = static_cast<const unsigned long*>(src);
+ auto dstl = static_cast<unsigned long*>(dst);
+
+ while (size >= sizeof(unsigned long)) {
+ *dstl++ = *srcl++;
+ size -= sizeof(unsigned long);
+ }
+
+ auto srcc = reinterpret_cast<const unsigned char*>(srcl);
+ auto dstc = reinterpret_cast<unsigned char*>(dstl);
+
+ while (size != 0) {
+ *dstc++ = *srcc++;
+ --size;