tiny.choir.composition.invocation
Defined in composition.
API (11)
Actions
Public operations.
Entry.initEntry.invokeInvocation.deinitInvocation.framePointerInvocation.idInvocation.initInvocation.status
Types and contracts
Public types and contracts.
Entry: A context-bound wrapper around one process-local raw fragment address.Invocation: One call's owned ABI resources and state, bound to a liveLoadedComposition.ResourceSpecState
Source
Source: lib/choir/src/composition/invocation.zig
zig
const std = @import("std");const composition = @import("root.zig");const abi = composition.abi;const loaded = composition.loaded;const Allocator = std.mem.Allocator;pub const ResourceSpec = struct { bytes: []u8, access: composition.Access,};pub const State = enum { prepared, running, completed, failed,};/// One call's owned ABI resources and state, bound to a live `LoadedComposition`./// Resource byte slices remain caller-owned and must outlive invocation completion.pub const Invocation = struct { allocator: Allocator, owner: *loaded.LoadedComposition, resources: []abi.Resource, frame: abi.Frame, state: State = .prepared, pub fn init( allocator: Allocator, owner: *loaded.LoadedComposition, specs: []const ResourceSpec, ) (Allocator.Error || error{ CompositionClosing, InvalidResource, TooManyResources })!*Invocation { if (specs.len > abi.max_resources) return error.TooManyResources; for (specs) |spec| { if (spec.bytes.len == 0) return error.InvalidResource; } const invocation_id = owner.reserveInvocation() orelse return error.CompositionClosing; errdefer owner.releaseInvocation(invocation_id); const resources = try allocator.alloc(abi.Resource, specs.len); errdefer allocator.free(resources); for (specs, 0..) |spec, index| { resources[index] = abi.Resource.init(owner.contextPointer().owner_cookie, invocation_id, spec.bytes, spec.access); } const invocation = try allocator.create(Invocation); invocation.* = .{ .allocator = allocator, .owner = owner, .resources = resources, .frame = abi.Frame.init(owner.contextPointer().owner_cookie, invocation_id, resources), }; return invocation; } pub fn deinit(self: *Invocation) void { if (self.state == .running) @panic("invocation destroyed while running"); const allocator = self.allocator; const owner = self.owner; const invocation_id = self.frame.invocation_id; allocator.free(self.resources); self.* = undefined; allocator.destroy(self); owner.releaseInvocation(invocation_id); } pub fn id(self: *const Invocation) u64 { return self.frame.invocation_id; } pub fn framePointer(self: *Invocation) *abi.Frame { return &self.frame; } pub fn status(self: *const Invocation) abi.Status { return self.frame.statusValue(); }};/// A context-bound wrapper around one process-local raw fragment address./// `address` is public for callers that supply the composition's ABI context/// and frame directly; `invoke` additionally requires a prepared invocation/// owned by the same loaded composition.pub const Entry = struct { owner: *loaded.LoadedComposition, address: usize, pub fn init( owner: *loaded.LoadedComposition, fragment_id: composition.FragmentId, export_name: []const u8, ) loaded.EntryError!Entry { return .{ .owner = owner, .address = try owner.entryAddress(fragment_id, export_name), }; } pub fn invoke(self: Entry, invocation: *Invocation) abi.Status { if (invocation.owner != self.owner or invocation.state != .prepared) { invocation.frame.setStatus(.invalid_resource); invocation.state = .failed; return .invalid_resource; } invocation.state = .running; const function: *const fn (i64, i64) callconv(.c) i64 = @ptrFromInt(self.address); const raw_status = function( @bitCast(@as(u64, @intFromPtr(self.owner.contextPointer()))), @bitCast(@as(u64, @intFromPtr(invocation.framePointer()))), ); const status = abi.decodeStatus(raw_status); invocation.frame.setStatus(status); invocation.state = if (status == .ok) .completed else .failed; return status; }};test "composition invocation resources carry one owner and identity" { try std.testing.expectEqual(abi.Status.fragment_failure, abi.decodeStatus(-1)); try std.testing.expectEqual(abi.Status.ok, abi.decodeStatus(@backingInt(abi.Status.ok))); try std.testing.expectEqual(abi.Status.fragment_failure, abi.decodeStatus(9000));}test "composition entries require a durable fragment export" { const init_info = @typeInfo(@TypeOf(Entry.init)).@"fn"; try std.testing.expectEqual(@as(usize, 3), init_info.param_types.len); try std.testing.expect(init_info.param_types[1].? == composition.FragmentId); try std.testing.expect(init_info.param_types[2].? == []const u8);}Source: lib/choir/src/composition/root.zig:12
zig
pub const invocation = @import("invocation.zig");Audit
| Definitions | 12 |
|---|---|
| Public names | 22 |
| Members | 13 |
| Version | 26.7.0 |
| Revision | daab053ee433 |