mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 06:44:50 +01:00
113 lines
4.6 KiB
Zig
113 lines
4.6 KiB
Zig
const MemoryMap = @This();
|
|
|
|
const builtin = @import("builtin");
|
|
const native_os = builtin.os.tag;
|
|
const is_windows = native_os == .windows;
|
|
|
|
const std = @import("../../std.zig");
|
|
const Io = std.Io;
|
|
const File = Io.File;
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
file: File,
|
|
/// Byte index inside `file` where `memory` starts. Page-aligned.
|
|
offset: u64,
|
|
/// Memory that may or may not remain consistent with file contents. Use `read`
|
|
/// and `write` to ensure synchronization points. Length has no alignment
|
|
/// requirement.
|
|
memory: []align(std.heap.page_size_min) u8,
|
|
/// Tells whether it is memory-mapped or file operations. On Windows this also
|
|
/// has a section handle.
|
|
section: ?Section,
|
|
|
|
pub const Section = if (is_windows) std.os.windows.HANDLE else void;
|
|
|
|
pub const CreateError = error{
|
|
/// One of the following:
|
|
/// * The `File.Kind` is not `file`.
|
|
/// * The file is not open for reading and read access protections enabled.
|
|
/// * The file is not open for writing and write access protections enabled.
|
|
AccessDenied,
|
|
/// The `prot` argument asks for `PROT_EXEC` but the mapped area belongs to a file on
|
|
/// a filesystem that was mounted no-exec.
|
|
PermissionDenied,
|
|
LockedMemoryLimitExceeded,
|
|
ProcessFdQuotaExceeded,
|
|
SystemFdQuotaExceeded,
|
|
} || Allocator.Error || File.ReadPositionalError;
|
|
|
|
pub const CreateOptions = struct {
|
|
/// Size of the mapping, in bytes. If this is longer than the file size,
|
|
/// `memory` beyond the file end will be filled with zeroes and it is
|
|
/// unspecified whether, after calling `write`, the file length will be
|
|
/// set to `len` or remain unchanged.
|
|
///
|
|
/// This value has no minimum alignment requirement, but may gain
|
|
/// efficiency benefits from being a multiple of `File.Stat.block_size`.
|
|
len: usize,
|
|
/// When this has read set to false, bytes that are not modified before a
|
|
/// sync may have the original file contents, or may be set to zero.
|
|
protection: std.process.MemoryProtection = .{ .read = true, .write = true },
|
|
/// If set to `true`, allows bytes observed before calling `read` to be
|
|
/// undefined, and bytes unwritten before calling `write` to write
|
|
/// undefined memory to the file.
|
|
undefined_contents: bool = false,
|
|
/// Prefault the pages. If this option is unsupported, it is silently
|
|
/// ignored. Aside from custom Io implementations, this option is only
|
|
/// supported on Linux.
|
|
populate: bool = true,
|
|
/// Asserted to be a multiple of page size which can be obtained via
|
|
/// `std.heap.pageSize`.
|
|
offset: u64 = 0,
|
|
};
|
|
|
|
/// To release the resources associated with the returned `MemoryMap`, call
|
|
/// `destroy`.
|
|
pub fn create(io: Io, file: File, options: CreateOptions) CreateError!MemoryMap {
|
|
return io.vtable.fileMemoryMapCreate(io.userdata, file, options);
|
|
}
|
|
|
|
/// If `write` is not called before this function, changes to `memory` may or may
|
|
/// not be synchronized to `file`.
|
|
pub fn destroy(mm: *MemoryMap, io: Io) void {
|
|
io.vtable.fileMemoryMapDestroy(io.userdata, mm);
|
|
}
|
|
|
|
pub const SetLengthError = error{
|
|
/// Changing the mapping length could not be done atomically. Caller must
|
|
/// use `destroy` and `create` to resize the mapping.
|
|
OperationUnsupported,
|
|
/// One of the following:
|
|
/// * The `File.Kind` is not `file`.
|
|
/// * The file is not open for reading and read access protections enabled.
|
|
/// * The file is not open for writing and write access protections enabled.
|
|
AccessDenied,
|
|
/// The `prot` argument asks for `PROT_EXEC` but the mapped area belongs to a file on
|
|
/// a filesystem that was mounted no-exec.
|
|
PermissionDenied,
|
|
LockedMemoryLimitExceeded,
|
|
ProcessFdQuotaExceeded,
|
|
SystemFdQuotaExceeded,
|
|
} || Allocator.Error || File.SetLengthError;
|
|
|
|
/// Change the size of the mapping. This does not sync the contents. The size
|
|
/// of the file after calling this is unspecified until `write` is called.
|
|
///
|
|
/// May change the pointer address of `memory`.
|
|
pub fn setLength(mm: *MemoryMap, io: Io, new_len: usize) SetLengthError!void {
|
|
return io.vtable.fileMemoryMapSetLength(io.userdata, mm, new_len);
|
|
}
|
|
|
|
/// Synchronizes the contents of `memory` from `file`.
|
|
pub fn read(mm: *MemoryMap, io: Io) File.ReadPositionalError!void {
|
|
return io.vtable.fileMemoryMapRead(io.userdata, mm);
|
|
}
|
|
|
|
/// Synchronizes the contents of `memory` to `file`.
|
|
///
|
|
/// If `memory.len` is greater than file size, the bytes beyond the end of the
|
|
/// file may be dropped, or they may be written, extending the size of the
|
|
/// file.
|
|
pub fn write(mm: *MemoryMap, io: Io) File.WritePositionalError!void {
|
|
return io.vtable.fileMemoryMapWrite(io.userdata, mm);
|
|
}
|