resource management
α1resource management
unique resources (file handles, sockets, device handles, database connections) are managed through region finalizers. there is no special resource type kind. resources are values that register cleanup with their region.
finalizers
region.on_dispose(fn) registers a finalizer with a region. when the region is disposed, all registered finalizers run in lifo order (last registered, first called):
const heap = region.heap();
defer heap.dispose();
const fd = syscall.open(path, flags);
heap.on_dispose(fn() -> Unit {
syscall.close(fd);
});finalization cannot throw. errors during finalization are logged but don't propagate. disposal always completes.
resources as values
a resource is just a struct whose constructor registers a finalizer:
type File = move {
fd: i32,
};
function open(path: String, r: Region) -> File effects [alloc, io] {
const fd = check syscall.open(path, O_RDONLY);
r.on_dispose(fn() -> Unit {
syscall.close(fd);
});
return r :: File { fd: fd };
}this replaces the old "capsule" concept. no special syntax, no separate type kind. resources are move types that register finalizers.
secure zeroing
for sensitive data (keys, passwords, tokens), use secure zeroing that the compiler won't optimize away:
mem.secure_zero(secret_view);resources holding secrets should call this in their finalizer:
heap.on_dispose(fn() -> Unit {
mem.secure_zero(key_buf);
});constant-time operations
types may be annotated as constant-time. the compiler warns if code branches on their contents:
type SecretKey = move {
bytes: View<u8>,
constant_time: true,
};
// compiler warns if code branches on SecretKey contentsthis is a hint for crypto-sensitive types where timing side channels matter.