bun.ptr.Shared: fix dependency loop and add leak/adopt methods (#23024)

Fixes STAB-1292
This commit is contained in:
taylor.fish
2025-09-26 19:46:50 -07:00
committed by GitHub
parent 665ea96076
commit ed72eff2a9
3 changed files with 39 additions and 23 deletions

View File

@@ -7,11 +7,14 @@
/// pub fn deref(T*) void;
/// };
pub fn ExternalShared(comptime T: type) type {
_ = T.external_shared_descriptor.ref; // must define a `ref` function
_ = T.external_shared_descriptor.deref; // must define a `deref` function
return struct {
const Self = @This();
comptime {
_ = T.external_shared_descriptor.ref; // must define a `ref` function
_ = T.external_shared_descriptor.deref; // must define a `deref` function
}
#impl: *T,
/// `incremented_raw` should have already had its ref count incremented by 1.

View File

@@ -34,13 +34,12 @@ pub fn Dynamic(comptime Pointer: type) type {
/// If `Allocator` is a zero-sized type, the owned pointer has no overhead compared to a raw
/// pointer.
pub fn OwnedIn(comptime Pointer: type, comptime Allocator: type) type {
const info = PointerInfo.parse(Pointer, .{});
const NonOptionalPointer = info.NonOptionalPointer;
const Child = info.Child;
const ConstPointer = AddConst(Pointer);
return struct {
const Self = @This();
const info = PointerInfo.parse(Pointer, .{});
const NonOptionalPointer = info.NonOptionalPointer;
const Child = info.Child;
const ConstPointer = AddConst(Pointer);
#pointer: Pointer,
#allocator: Allocator,
@@ -381,10 +380,9 @@ pub fn OwnedIn(comptime Pointer: type, comptime Allocator: type) type {
///
/// This type is accessible as `OwnedIn(Pointer, Allocator).Unmanaged`.
fn Unmanaged(comptime Pointer: type, comptime Allocator: type) type {
const info = PointerInfo.parse(Pointer, .{});
return struct {
const Self = @This();
const info = PointerInfo.parse(Pointer, .{});
#pointer: Pointer,

View File

@@ -61,12 +61,6 @@ pub fn AtomicSharedIn(comptime Pointer: type, comptime Allocator: type) type {
/// Like `Shared`, but takes explicit options.
pub fn WithOptions(comptime Pointer: type, comptime options: Options) type {
const Allocator = options.Allocator;
const info = parsePointer(Pointer);
const Child = info.Child;
const NonOptionalPointer = info.NonOptionalPointer;
const Data = FullData(Child, options);
if (options.allow_weak) {
// Weak pointers only make sense if `deinit` will be called, since their only function
// is to ensure `deinit` can be called before the memory is freed (weak pointers keep
@@ -84,6 +78,11 @@ pub fn WithOptions(comptime Pointer: type, comptime options: Options) type {
return struct {
const Self = @This();
const Allocator = options.Allocator;
const info = parsePointer(Pointer);
const Child = info.Child;
const NonOptionalPointer = info.NonOptionalPointer;
const Data = FullData(Child, options);
#pointer: Pointer,
@@ -239,11 +238,28 @@ pub fn WithOptions(comptime Pointer: type, comptime options: Options) type {
return .fromValuePtr(self.#pointer);
}
/// Turns a shared pointer into a raw pointer without decrementing the reference count.
///
/// This method invalidates `self`. To avoid leaks, the raw pointer should be turned back
/// into a shared pointer with `adoptRawUnsafe`.
pub fn leak(self: *Self) Pointer {
defer self.* = undefined;
return self.#pointer;
}
/// Creates a shared pointer from a raw pointer returned by `leak`.
///
/// `pointer` must have been previously returned by `leak`. `adoptRawUnsafe` should not be
/// called again on this pointer.
pub fn adoptRawUnsafe(pointer: Pointer) Self {
return .{ .#pointer = pointer };
}
/// Clones a shared pointer, given a raw pointer that originally came from a shared pointer.
///
/// `pointer` must have come from a shared pointer (e.g., from `get` or `leak`), and the shared
/// pointer from which it came must remain valid (i.e., not be deinitialized) at least until
/// this function returns.
/// `pointer` must have come from a shared pointer, and the shared pointer from which it
/// came must remain valid (i.e., not be deinitialized) at least until this function
/// returns.
pub fn cloneFromRawUnsafe(pointer: Pointer) Self {
const temp: Self = .{ .#pointer = pointer };
return temp.clone();
@@ -252,11 +268,6 @@ pub fn WithOptions(comptime Pointer: type, comptime options: Options) type {
}
fn Weak(comptime Pointer: type, comptime options: Options) type {
const info = parsePointer(Pointer);
const Child = info.Child;
const NonOptionalPointer = info.NonOptionalPointer;
const Data = FullData(Child, options);
bun.assertf(
options.allow_weak and options.deinit,
"options incompatible with shared.Weak",
@@ -265,6 +276,10 @@ fn Weak(comptime Pointer: type, comptime options: Options) type {
return struct {
const Self = @This();
const info = parsePointer(Pointer);
const Child = info.Child;
const NonOptionalPointer = info.NonOptionalPointer;
const Data = FullData(Child, options);
#pointer: Pointer,