Skip to content

Produce-consume with defer cleanup

Description

Produce-consume with defer cleanup.

  • Push 5 Events into a list (producer).
  • Pop each, sum the codes (consumer).
  • defer frees any items remaining on error, before or after the loop.

Diagram

 alloc.create × 5 ──► list (producer)
      │ list.popFirst × 5
 freeItem per node (consumer)

Source

pub fn produce_consume_with_defer_cleanup(allocator: std.mem.Allocator, io: std.Io) !void {
    _ = io;
    var list: std.DoublyLinkedList = .{};

    defer freeRemaining(&list, allocator);

    var i: i32 = 0;
    while (i < 5) : (i += 1) {
        var slot: Slot = null;
        try items.Event.EventPolyHelper.create(allocator, &slot);
        items.Event.EventPolyHelper.mustIdentifySlotAs(&slot).code = i;
        list.append(&slot.?.*.node);
        slot = null;
    }

    var sum: i32 = 0;
    while (list.popFirst()) |node| {
        const poly: *polynode.PolyNode = @fieldParentPtr("node", node);
        const ev: *items.Event = items.Event.EventPolyHelper.identifyNodeAs(poly) orelse return error.CastFailed;
        sum += ev.*.code;
        items.freeItem(poly, allocator);
    }

    try helpers.expect(error.ProduceConsumeFailed, sum == 0 + 1 + 2 + 3 + 4, "wrong sum");
}

fn freeRemaining(list: *std.DoublyLinkedList, alloc: std.mem.Allocator) void {
    while (list.popFirst()) |node| {
        const poly: *polynode.PolyNode = @fieldParentPtr("node", node);
        items.freeItem(poly, alloc);
    }
}

const items = @import("../items/items.zig");
const helpers = @import("../helpers/helpers.zig");
const polynode = @import("matryoshka").polynode;
const std = @import("std");
const Slot = polynode.Slot;