Current section

Files

Jump to
zigler lib zig templates threaded.zig.eex
Raw

lib/zig/templates/threaded.zig.eex

const Thread_<%= @type.name %> = beam.Thread(nif.<%= @type.name %>);
pub const ThreadResource_<%= @type.name %> = beam.Resource(*Thread_<%= @type.name %>, @This(), .{
.Callbacks = beam.ThreadedCallbacks(Thread_<%= @type.name %>)
});
<% needs_make? = Enum.any?(@type.params, &Type.needs_make?/1) %>
fn @"<%= @type.name %>-launch"(env: beam.env, argc: c_int, args: [*c] const e.ErlNifTerm) callconv(.C) e.ErlNifTerm {
// always use the raw_allocator, we can set it to managed allocation elsewhere.
beam.allocator = beam.raw_allocator;
<%= for {param_type, index} <- Nif.indexed_parameters(@type.params), Type.missing_size?(param_type) do %>
var size<%= index %>:usize = undefined;
<% end %>
<%= if needs_make? do %>
var error_info = beam.make_empty_list(env);
<% end %>
const payload_opts = .{
<%= for {param_type, index} <- Nif.indexed_parameters(@type.params) do %>
.{
<%= if needs_make? do %>.error_info = &error_info,<% end %>
<%= if Type.missing_size?(param_type) do%>.size = &size<%= index %>,<% end %>
<%= if match?(%Zig.Type.Resource{}, param_type) do%>.root = @This() <% end %>
},
<% end %>
};
const result = Thread_<%= @type.name %>.launch(ThreadResource_<%= @type.name %>, env, argc, args, .{.arg_opts = payload_opts}) catch {
@panic("error launching thread");
};
return result.v;
}
fn @"<%= @type.name %>-join"(env: beam.env, argc: c_int, args: [*c] const e.ErlNifTerm) callconv(.C) e.ErlNifTerm {
_ = argc;
// set beam.allocator due to reentry
beam.allocator = beam.raw_allocator;
const thread_rsrc = beam.get(ThreadResource_<%= @type.name %>, env, .{.v = args[0]}, .{}) catch {
@panic("error getting thread resource");
};
const thread = ThreadResource_<%= @type.name %>.unpack(thread_rsrc);
const result = thread.join() catch {
// TODO: fix this
@panic("error joining thread");
};
if (comptime Thread_<%= @type.name %>.makes_error_result()) {
const result_term = switch(result) {
.ok => |ok_result| beam.make(env, ok_result, .{}),
.error_return_trace => |error_result| beam.raise_exception(env, beam.copy(env, error_result)),
};
return result_term.v;
} else {
return beam.make(env, result, .{}).v;
}
}