MemoryMappedFile.java revision bffb058e565a97f838247f1e092b0d17b26cb68e
1/*
2 * Copyright (C) 2010 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
17package libcore.io;
18
19import java.io.Closeable;
20import java.io.FileDescriptor;
21import java.io.IOException;
22import java.nio.ByteOrder;
23import java.nio.channels.FileChannel;
24import org.apache.harmony.luni.platform.OSMemory;
25import org.apache.harmony.nio.internal.FileChannelImpl;
26
27/**
28 * A memory-mapped file. Use {@link #mmap} to map a file, {@link #close} to unmap a file,
29 * and either {@link #bigEndianIterator} or {@link #littleEndianIterator} to get a seekable
30 * {@link BufferIterator} over the mapped data.
31 */
32public final class MemoryMappedFile implements Closeable {
33    private int address;
34
35    // Until we have 64-bit address spaces, we only need an int for 'size'.
36    private final int size;
37
38    private MemoryMappedFile(int address, int size) {
39        this.address = address;
40        this.size = size;
41    }
42
43    public static MemoryMappedFile mmap(FileChannel fc, FileChannel.MapMode mapMode, long start, long size) throws IOException {
44        return mmap(((FileChannelImpl) fc).getHandle(), mapMode, start, size);
45    }
46
47    public static MemoryMappedFile mmap(FileDescriptor fd, FileChannel.MapMode mapMode, long start, long size) throws IOException {
48        return mmap(IoUtils.getFd(fd), mapMode, start, size);
49    }
50
51    private static MemoryMappedFile mmap(int fd, FileChannel.MapMode mapMode, long start, long size) throws IOException {
52        if (start < 0) {
53            throw new IllegalArgumentException("start < 0: " + start);
54        }
55        if (size <= 0) {
56            throw new IllegalArgumentException("size <= 0: " + size);
57        }
58        if ((start + size) > Integer.MAX_VALUE) {
59            throw new IllegalArgumentException("(start + size) > Integer.MAX_VALUE");
60        }
61        int address = OSMemory.mmap(fd, start, size, mapMode);
62        return new MemoryMappedFile(address, (int) size);
63    }
64
65    /**
66     * Unmaps this memory-mapped file using munmap(2). This is a no-op if close has already been
67     * called. Note that this class does <i>not</i> use finalization; you must call {@code close}
68     * yourself.
69     *
70     * Calling this method invalidates any iterators over this {@code MemoryMappedFile}. It is an
71     * error to use such an iterator after calling {@code close}.
72     */
73    public synchronized void close() throws IOException {
74        if (address != 0) {
75            OSMemory.munmap(address, size);
76            address = 0;
77        }
78    }
79
80    /**
81     * Returns a new iterator that treats the mapped data as big-endian.
82     */
83    public BufferIterator bigEndianIterator() {
84        return new BufferIterator(address, size, ByteOrder.BIG_ENDIAN.needsSwap);
85    }
86
87    /**
88     * Returns a new iterator that treats the mapped data as little-endian.
89     */
90    public BufferIterator littleEndianIterator() {
91        return new BufferIterator(address, size, ByteOrder.LITTLE_ENDIAN.needsSwap);
92    }
93
94    /**
95     * Returns the size in bytes of the memory-mapped region.
96     */
97    public int size() {
98        return size;
99    }
100}
101