// Сборка мусора: ручное управление памятью в Zig
// Компиляция: zig build-exe gc_demo.zig && ./gc_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. Аллокаторы ---\n", .{});
    try stdout.print("  Zig не имеет сборщика мусора.\n", .{});
    try stdout.print("  Каждая структура получает аллокатор явно.\n", .{});
    try stdout.print("  page_allocator: напрямую из ОС (mmap/VirtualAlloc).\n", .{});
    try stdout.print("  GeneralPurpose: поверх page_allocator, с пулами.\n", .{});
    try stdout.print("  FixedBuffer: из заранее выделенного буфера.\n\n", .{});

    // 2. defer как RAII
    try stdout.print("--- 2. defer — детерминированная очистка ---\n", .{});
    const page_alloc = std.heap.page_allocator;
    {
        const buf = try page_alloc.alloc(u8, 1024);
        defer page_alloc.free(buf);

        buf[0] = 42;
        try stdout.print("  Выделено 1024 байт, buf[0] = {d}\n", .{buf[0]});
        try stdout.print("  defer page_alloc.free(buf) сработает при выходе.\n", .{});
    }
    try stdout.print("  Блок завершён — память освобождена.\n\n", .{});

    // 3. ArrayList с ручным управлением
    try stdout.print("--- 3. ArrayList ---\n", .{});
    {
        var list: std.ArrayList(i32) = .{};
        defer list.deinit(page_alloc);

        try list.append(page_alloc, 10);
        try list.append(page_alloc, 20);
        try list.append(page_alloc, 30);

        var sum: i32 = 0;
        for (list.items) |x| {
            sum += x;
        }
        try stdout.print("  Элементы: {d}, сумма: {d}\n", .{ list.items.len, sum });
        try stdout.print("  defer list.deinit() освобождает при выходе.\n", .{});
    }
    try stdout.print("\n", .{});

    // 4. Арена-аллокатор
    try stdout.print("--- 4. Арена-аллокатор ---\n", .{});
    try stdout.print("  Арена: выделяй сколько хочешь, освобождай всё разом.\n", .{});
    try stdout.print("  Идеально для запросов: обработал — сбросил арену.\n", .{});
    try stdout.print("  Нет фрагментации, нет утечек, одна операция.\n", .{});
    try stdout.print("  std.heap.ArenaAllocator — обёртка над любым аллокатором.\n\n", .{});

    // 5. Сравнение подходов
    try stdout.print("--- 5. Подходы к управлению памятью ---\n", .{});
    try stdout.print("  GC (Go, Java):        автоматически, паузы\n", .{});
    try stdout.print("  Подсчёт ссылок (Swift): автоматически, без пауз, циклы\n", .{});
    try stdout.print("  Владение (Rust):       компилятор проверяет, без пауз\n", .{});
    try stdout.print("  Ручное (Zig, C):       программист решает, максимальный контроль\n\n", .{});

    // 6. Почему нет GC
    try stdout.print("--- 6. Почему Zig без GC ---\n", .{});
    try stdout.print("  Zig — язык для системного программирования.\n", .{});
    try stdout.print("  GC несовместим с: ядрами ОС, драйверами, bare-metal.\n", .{});
    try stdout.print("  GC скрывает аллокации — Zig делает их явными.\n", .{});
    try stdout.print("  Каждый вызов, который может выделить память, возвращает ошибку.\n", .{});

    try stdout.print("\n--- Итог ---\n", .{});
    try stdout.print("Zig: нет GC, нет скрытых аллокаций\n", .{});
    try stdout.print("defer: детерминированная очистка (как RAII)\n", .{});
    try stdout.print("Аллокатор как параметр: контроль над каждым байтом\n", .{});
    try stdout.print("Арена: быстрое освобождение пачки объектов\n", .{});
}
