mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
77 lines
2.6 KiB
Zig
77 lines
2.6 KiB
Zig
/// A generic task that runs work on a thread pool and resolves a JavaScript Promise with the result.
|
|
/// This allows CPU-intensive operations to be performed off the main JavaScript thread while
|
|
/// maintaining a Promise-based API for JavaScript consumers.
|
|
///
|
|
/// The Context type must implement:
|
|
/// - `run(*Context)` - performs the work on the thread pool
|
|
/// - `then(*Context, jsc.JSPromise)` - resolves the promise with the result on the JS thread
|
|
pub fn ConcurrentPromiseTask(comptime Context: type) type {
|
|
return struct {
|
|
const This = @This();
|
|
ctx: *Context,
|
|
task: WorkPoolTask = .{ .callback = &runFromThreadPool },
|
|
event_loop: *jsc.EventLoop,
|
|
allocator: std.mem.Allocator,
|
|
promise: jsc.JSPromise.Strong = .{},
|
|
globalThis: *jsc.JSGlobalObject,
|
|
concurrent_task: jsc.ConcurrentTask = .{},
|
|
|
|
// This is a poll because we want it to enter the uSockets loop
|
|
ref: Async.KeepAlive = .{},
|
|
|
|
pub const new = bun.TrivialNew(@This());
|
|
|
|
pub fn createOnJSThread(allocator: std.mem.Allocator, globalThis: *jsc.JSGlobalObject, value: *Context) !*This {
|
|
var this = This.new(.{
|
|
.event_loop = VirtualMachine.get().event_loop,
|
|
.ctx = value,
|
|
.allocator = allocator,
|
|
.globalThis = globalThis,
|
|
});
|
|
var promise = jsc.JSPromise.create(globalThis);
|
|
this.promise.strong.set(globalThis, promise.toJS());
|
|
this.ref.ref(this.event_loop.virtual_machine);
|
|
return this;
|
|
}
|
|
|
|
pub fn runFromThreadPool(task: *WorkPoolTask) void {
|
|
var this: *This = @fieldParentPtr("task", task);
|
|
Context.run(this.ctx);
|
|
this.onFinish();
|
|
}
|
|
|
|
pub fn runFromJS(this: *This) bun.JSTerminated!void {
|
|
const promise = this.promise.swap();
|
|
this.ref.unref(this.event_loop.virtual_machine);
|
|
|
|
var ctx = this.ctx;
|
|
|
|
return ctx.then(promise);
|
|
}
|
|
|
|
pub fn schedule(this: *This) void {
|
|
WorkPool.schedule(&this.task);
|
|
}
|
|
|
|
pub fn onFinish(this: *This) void {
|
|
this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
|
|
}
|
|
|
|
pub fn deinit(this: *This) void {
|
|
this.promise.deinit();
|
|
bun.destroy(this);
|
|
}
|
|
};
|
|
}
|
|
|
|
const std = @import("std");
|
|
|
|
const bun = @import("bun");
|
|
const Async = bun.Async;
|
|
|
|
const jsc = bun.jsc;
|
|
const JSPromise = jsc.JSPromise;
|
|
const VirtualMachine = jsc.VirtualMachine;
|
|
const WorkPool = jsc.WorkPool;
|
|
const WorkPoolTask = jsc.WorkPoolTask;
|