aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/base.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-04-25 21:47:42 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-04-25 21:47:42 -0700
commit6259dfdfd1a954f5e42314988fd58306cccc453c (patch)
tree8227356c3ed19bce717cc0c004d581cac7b7e715 /src/bun.js/base.zig
parent0846a4fa809430a77f1284a7a526a946007484e0 (diff)
downloadbun-6259dfdfd1a954f5e42314988fd58306cccc453c.tar.gz
bun-6259dfdfd1a954f5e42314988fd58306cccc453c.tar.zst
bun-6259dfdfd1a954f5e42314988fd58306cccc453c.zip
Fix crash
Diffstat (limited to 'src/bun.js/base.zig')
-rw-r--r--src/bun.js/base.zig88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig
index cbd80db87..1e5069de8 100644
--- a/src/bun.js/base.zig
+++ b/src/bun.js/base.zig
@@ -4144,3 +4144,91 @@ pub const BinaryType = enum {
}
}
};
+
+pub const FinalizationCallback = struct {
+ context: Ptr = Ptr{},
+ callback: ?*const fn (*anyopaque) void = null,
+
+ pub const Ptr = packed struct(u64) {
+ address: u60 = 0,
+
+ // Really should only have 2 references maximum
+ ref_count: u4 = 0,
+
+ pub fn ref(this: *Ptr) void {
+ this.ref_count += 1;
+ }
+
+ pub fn unref(this: *Ptr) void {
+ this.ref_count -= 1;
+ }
+
+ pub fn ptr(this: *Ptr) ?*anyopaque {
+ if (this.address == 0)
+ return null;
+
+ return @intToPtr(*anyopaque, @as(usize, this.addrress));
+ }
+
+ pub fn init(addr: *anyopaque) Ptr {
+ return .{
+ .address = @truncate(u60, @ptrToInt(addr)),
+ .ref_count = 1,
+ };
+ }
+ };
+
+ pub const Pool = bun.HiveArray(FinalizationCallback, 512).Fallback;
+
+ pub fn call(this: *FinalizationCallback, pool: *Pool) void {
+ var callback = this.callback orelse {
+ this.unregister();
+ pool.put(this);
+ return;
+ };
+ var ctx = this.context.ptr() orelse {
+ this.unregister();
+ pool.put(this);
+ return;
+ };
+ this.unregister();
+ pool.put(this);
+
+ callback(ctx);
+ }
+
+ /// Pointers to FinalizationCallback are invalidated immediately **before** the callback is called.
+ pub fn create(pool: *Pool, comptime Context: type, context: *Context, callback: *const fn (*Context) void) *FinalizationCallback {
+ var this: *FinalizationCallback = pool.get();
+ this.set(Context, context, callback);
+ return this;
+ }
+
+ pub fn set(this: *FinalizationCallback, comptime Context: type, context: *Context, callback: *const fn (*Context) void) void {
+ this.* = .{
+ .context = Ptr.init(bun.cast(*anyopaque, context)),
+ .callback = bun.cast(*const fn (*anyopaque) void, callback),
+ };
+ }
+
+ fn unregister(this: *FinalizationCallback) void {
+ this.* = .{};
+ }
+
+ pub fn ref(this: *FinalizationCallback) void {
+ this.context.ref();
+ }
+
+ pub fn detach(this: *FinalizationCallback, pool: *Pool) void {
+ this.unregister();
+ this.unref(pool);
+ }
+
+ pub fn unref(this: *FinalizationCallback, pool: *Pool) void {
+ this.context.unref();
+ if (this.context.ref_count == 0) {
+ this.unregister();
+ pool.put(this);
+ }
+ }
+};