// Виртуальная память: страничный аллокатор и адреса
// Компиляция: zig build-exe vmem_demo.zig && ./vmem_demo

const std = @import("std");

pub fn main() !void {
    const stdout = std.fs.File.stdout().deprecatedWriter();

    try stdout.print("=== Zig: виртуальная память ===\n\n", .{});

    // 1. Страничный аллокатор
    try stdout.print("--- 1. page_allocator ---\n", .{});
    try stdout.print("  page_allocator выделяет память напрямую у ОС.\n", .{});
    try stdout.print("  На Linux: mmap(). На macOS: mmap(). На Windows: VirtualAlloc().\n", .{});
    try stdout.print("  Минимальная единица: одна страница.\n\n", .{});

    const page_alloc = std.heap.page_allocator;

    // 2. Выделение и адреса
    try stdout.print("--- 2. Выделение памяти ---\n", .{});
    const buf1 = try page_alloc.alloc(u8, 4096);
    defer page_alloc.free(buf1);
    const buf2 = try page_alloc.alloc(u8, 4096);
    defer page_alloc.free(buf2);

    try stdout.print("  buf1: {*} ({d} байт)\n", .{ buf1.ptr, buf1.len });
    try stdout.print("  buf2: {*} ({d} байт)\n", .{ buf2.ptr, buf2.len });
    const diff = @intFromPtr(buf2.ptr) -% @intFromPtr(buf1.ptr);
    try stdout.print("  Разница адресов: {d} байт\n", .{diff});
    try stdout.print("  Адреса виртуальные — ОС транслирует в физические.\n\n", .{});

    // 3. Указатели и адресная арифметика
    try stdout.print("--- 3. Указатели ---\n", .{});
    var x: i32 = 42;
    const ptr = &x;
    const addr = @intFromPtr(ptr);
    try stdout.print("  x = {d}, адрес = 0x{x}\n", .{ x, addr });
    try stdout.print("  Zig разрешает @intFromPtr / @ptrFromInt.\n", .{});
    try stdout.print("  В отличие от C: нет неявных приведений указателей.\n\n", .{});

    // 4. Схема памяти
    try stdout.print("--- 4. Схема виртуальной памяти ---\n", .{});
    try stdout.print("  Каждый процесс видит непрерывное пространство адресов.\n", .{});
    try stdout.print("  48-бит на x86-64 = 256 ТБ виртуальной памяти.\n", .{});
    try stdout.print("  57-бит (5-уровневые таблицы) = 128 ПБ.\n", .{});
    try stdout.print("  Физической памяти обычно в тысячи раз меньше.\n\n", .{});

    // 5. Copy-on-Write
    try stdout.print("--- 5. Копирование при записи (CoW) ---\n", .{});
    try stdout.print("  fork() копирует таблицу страниц, не данные.\n", .{});
    try stdout.print("  Обе копии ссылаются на те же физические страницы.\n", .{});
    try stdout.print("  При первой записи — ОС копирует только эту страницу.\n", .{});
    try stdout.print("  Результат: fork() мгновенный даже для больших процессов.\n\n", .{});

    // 6. Zig и контроль над памятью
    try stdout.print("--- 6. Zig: явный контроль ---\n", .{});
    try stdout.print("  Нет скрытых аллокаций (в отличие от Go, Rust, C++).\n", .{});
    try stdout.print("  Аллокатор — параметр, не глобальное состояние.\n", .{});
    try stdout.print("  page_allocator: для больших блоков.\n", .{});
    try stdout.print("  FixedBufferAllocator: из заранее выделенного буфера.\n", .{});
    try stdout.print("  ArenaAllocator: выделяй много, освобождай разом.\n", .{});

    try stdout.print("\n--- Итог ---\n", .{});
    try stdout.print("Виртуальная память: процесс видит своё пространство\n", .{});
    try stdout.print("Страница: единица трансляции (4-16 КБ)\n", .{});
    try stdout.print("CoW: fork() без копирования данных\n", .{});
    try stdout.print("Zig: аллокатор — явный параметр каждой функции\n", .{});
}
