feat: use a signal instead of spinning in pid.call()

This commit is contained in:
CJ van den Berg 2024-04-02 23:02:58 +02:00
parent 1a769c056a
commit 21a0b60366

View file

@ -665,15 +665,13 @@ const CallContext = struct {
request: message, request: message,
response: ?message, response: ?message,
a: std.mem.Allocator, a: std.mem.Allocator,
mut: std.Thread.Mutex = std.Thread.Mutex{},
cond: std.Thread.Condition = std.Thread.Condition{},
const Self = @This(); const Self = @This();
const ReceiverT = Receiver(*Self); const ReceiverT = Receiver(*Self);
pub fn call(to: pid_ref, request: message) !message { pub fn call(a: std.mem.Allocator, to: pid_ref, request: message) error{ OutOfMemory, ThespianSpawnFailed }!message {
var heap: [32 + 1024]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&heap);
const a = fba.allocator();
var self: Self = undefined; var self: Self = undefined;
const rec = ReceiverT.init(receive_, &self); const rec = ReceiverT.init(receive_, &self);
@ -685,20 +683,19 @@ const CallContext = struct {
.a = a, .a = a,
}; };
self.mut.lock();
errdefer self.mut.unlock();
const proc = try spawn_link(a, &self, start, @typeName(Self)); const proc = try spawn_link(a, &self, start, @typeName(Self));
while (!proc.expired()) { defer proc.deinit();
std.time.sleep(50);
} self.cond.wait(&self.mut);
if (self.response) |resp| {
const m = message_buffer[0..resp.buf.len]; return self.response orelse .{};
@memcpy(m, resp.buf);
return .{ .buf = m };
} else {
return .{};
}
} }
fn start(self: *Self) result { fn start(self: *Self) result {
errdefer self.cond.signal();
_ = set_trap(true); _ = set_trap(true);
try self.to.link(); try self.to.link();
try self.to.send_raw(self.request); try self.to.send_raw(self.request);
@ -706,6 +703,7 @@ const CallContext = struct {
} }
fn receive_(self: *Self, from: pid_ref, m: message) result { fn receive_(self: *Self, from: pid_ref, m: message) result {
defer self.cond.signal();
_ = from; _ = from;
self.response = m.clone(self.a) catch |e| return exit_error(e); self.response = m.clone(self.a) catch |e| return exit_error(e);
try exit_normal(); try exit_normal();