feat: add unlinked-spawn to the C and Zig APIs

This commit is contained in:
CJ van den Berg 2026-03-07 17:40:24 +01:00
parent 87c4a6f32c
commit e90009074a
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
3 changed files with 51 additions and 0 deletions

View file

@ -28,6 +28,9 @@ thespian_handle thespian_self();
int thespian_spawn_link(thespian_behaviour, thespian_behaviour_state, int thespian_spawn_link(thespian_behaviour, thespian_behaviour_state,
const char *name, thespian_env, thespian_handle *); const char *name, thespian_env, thespian_handle *);
int thespian_spawn(thespian_behaviour, thespian_behaviour_state,
const char *name, thespian_env, thespian_handle *);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -96,4 +96,30 @@ auto thespian_spawn_link(thespian_behaviour b, thespian_behaviour_state s,
new thespian::handle{ret.value()}); new thespian::handle{ret.value()});
return 0; return 0;
} }
auto thespian_spawn(thespian_behaviour b, thespian_behaviour_state s,
const char *name, thespian_env env, thespian_handle *handle)
-> int {
const thespian::env_t empty_env_{};
thespian::env_t env_ =
env ? *reinterpret_cast<thespian::env_t *>(env) : empty_env_; // NOLINT
auto ret = spawn(
[b, s]() -> thespian::result {
auto *ret = b(s);
if (ret) {
auto err = cbor::buffer();
const uint8_t *data = ret->base; // NOLINT
std::copy(data, data + ret->len, back_inserter(err)); // NOLINT
return thespian::to_error(err);
}
return thespian::ok();
},
string_view(name), std::move(env_));
if (!ret)
return -1;
*handle = reinterpret_cast<thespian_handle>( // NOLINT
new thespian::handle{ret.value()});
return 0;
}
} }

View file

@ -584,6 +584,28 @@ pub fn spawn_link(
return spawn_link_env(a, data, f, name, env.get()); return spawn_link_env(a, data, f, name, env.get());
} }
/// Spawn a new actor WITHOUT creating a link to the calling actor.
/// The new actor runs independently; its exit does not propagate to the
/// caller. Think twice before you use this form of spawn. It's rarely want
/// you want to do.
pub fn spawn(
a: std.mem.Allocator,
data: anytype,
f: Behaviour(@TypeOf(data)).FunT,
name: [:0]const u8,
) error{ OutOfMemory, ThespianSpawnFailed }!pid {
const Tclosure = Behaviour(@TypeOf(data));
var handle_: c.thespian_handle = null;
try neg_to_error(c.thespian_spawn(
Tclosure.run,
try Tclosure.create(a, f, data),
name,
env.get().env,
&handle_,
), error.ThespianSpawnFailed);
return wrap_pid(handle_);
}
pub fn spawn_link_env( pub fn spawn_link_env(
a: std.mem.Allocator, a: std.mem.Allocator,
data: anytype, data: anytype,