OOB via send_oob
Description
OOB via send_oob.
- Send 3 Events via mailbox.send, queued in order.
- Send a ShutdownCommand via mailbox.send_oob, jumps to queue front.
- processingLoop receives 4 items: OOB signal first, then the 3 Events.
- Free every received item, verify the arrival order.
Diagram
mailbox.send (Event×3) ──► queue tail
mailbox.send_oob (ShutdownCommand) ──► queue front
│ mailbox.receive ×4
▼
OOB ShutdownCommand arrives first, then Events in send order
freeSlot per item
Source
pub fn oob_via_send_oob(allocator: std.mem.Allocator, io: std.Io) !void {
const mbh: MailboxHandle = try mailbox.new(io, allocator);
defer {
var rem: std.DoublyLinkedList = mailbox.close(mbh);
items.freeList(&rem, allocator);
mailbox.destroy(mbh, allocator);
}
try sendItems(mbh, allocator);
try sendOobItem(mbh, allocator);
std.log.info("sent 3 Events (regular) + 1 ShutdownCommand (OOB)", .{});
try processingLoop(mbh, allocator);
}
fn sendItems(mbh: MailboxHandle, alloc: std.mem.Allocator) !void {
for (0..3) |i| {
var slot: Slot = null;
defer items.Event.EventPolyHelper.destroy(alloc, &slot);
try items.Event.EventPolyHelper.create(alloc, &slot);
items.Event.EventPolyHelper.mustIdentifySlotAs(&slot).code = @intCast(i + 1);
try mailbox.send(mbh, &slot);
}
}
fn sendOobItem(mbh: MailboxHandle, alloc: std.mem.Allocator) !void {
var slot: Slot = null;
defer items.ShutdownCommand.ShutdownCommandPolyHelper.destroy(alloc, &slot);
try items.ShutdownCommand.ShutdownCommandPolyHelper.create(alloc, &slot);
try mailbox.send_oob(mbh, &slot);
}
fn processingLoop(mbh: MailboxHandle, alloc: std.mem.Allocator) !void {
var shutdown_seen: bool = false;
var event_count: usize = 0;
for (0..4) |_| {
var slot: Slot = null;
defer items.freeSlot(&slot, alloc);
try mailbox.receive(mbh, &slot, null);
const poly: *PolyNode = slot.?;
if (items.ShutdownCommand.ShutdownCommandPolyHelper.identifyNodeAs(poly)) |_| {
try helpers.expect(error.OobOrderFailed, !shutdown_seen, "OOB ShutdownCommand must arrive before any Event");
try helpers.expect(error.OobOrderFailed, event_count == 0, "OOB must be first item received");
shutdown_seen = true;
std.log.info("received OOB ShutdownCommand (first, as expected)", .{});
items.freeSlot(&slot, alloc);
} else if (items.Event.EventPolyHelper.identifyNodeAs(poly)) |ev| {
try helpers.expect(error.OobOrderFailed, shutdown_seen, "Events must arrive after the OOB item");
event_count += 1;
std.log.info("received Event code={d} (event {d}/3)", .{ ev.code, event_count });
items.freeSlot(&slot, alloc);
} else {
return error.OobOrderFailed;
}
}
try helpers.expect(error.OobOrderFailed, shutdown_seen, "OOB item not received");
try helpers.expect(error.OobOrderFailed, event_count == 3, "expected 3 Events");
std.log.info("OOB ordering verified: shutdown came first, then {d} events", .{event_count});
}
const items = @import("../items/items.zig");
const helpers = @import("../helpers/helpers.zig");
const matryoshka = @import("matryoshka");
const std = @import("std");
const mailbox = matryoshka.mailbox;
const polynode = matryoshka.polynode;
const PolyNode = polynode.PolyNode;
const Slot = polynode.Slot;
const MailboxHandle = mailbox.MailboxHandle;