aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-16 05:04:23 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-16 05:04:23 -0700
commit3b78cfe71ad4ce7732266a8b5db5bd0f5fda992e (patch)
treeb118db2b622ae989ae06bbed27958c45c2c03897 /src
parent422bdf692a94e808bd96e9d429ba79becb5b2676 (diff)
downloadbun-3b78cfe71ad4ce7732266a8b5db5bd0f5fda992e.tar.gz
bun-3b78cfe71ad4ce7732266a8b5db5bd0f5fda992e.tar.zst
bun-3b78cfe71ad4ce7732266a8b5db5bd0f5fda992e.zip
Add a way to run serial tasks on a different thread
Diffstat (limited to 'src')
-rw-r--r--src/javascript/jsc/javascript.zig68
1 files changed, 65 insertions, 3 deletions
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 8757f653d..9e9a8c9f8 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -1529,12 +1529,13 @@ const bun_file_import_path = "/node_modules.server.bun";
const FetchTasklet = Fetch.FetchTasklet;
const TaggedPointerUnion = @import("../../tagged_pointer.zig").TaggedPointerUnion;
-const WorkPool = @import("../../work_pool.zig");
+const WorkPool = @import("../../work_pool.zig").WorkPool;
+const WorkPoolTask = @import("../../work_pool.zig").Task;
pub fn ConcurrentPromiseTask(comptime Context: type) type {
return struct {
const This = @This();
ctx: *Context,
- task: WorkPool.Task = .{ .callback = runFromThreadPool },
+ task: WorkPoolTask = .{ .callback = runFromThreadPool },
event_loop: *VirtualMachine.EventLoop,
allocator: std.mem.Allocator,
promise: JSValue,
@@ -1554,7 +1555,7 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type {
return this;
}
- pub fn runFromThreadPool(task: *WorkPool.Task) void {
+ pub fn runFromThreadPool(task: *WorkPoolTask) void {
var this = @fieldParentPtr(This, "task", task);
Context.run(this.ctx);
this.onFinish();
@@ -1589,6 +1590,67 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type {
};
}
+pub fn SerialPromiseTask(comptime Context: type) type {
+ return struct {
+ const SerialWorkPool = @import("../../work_pool.zig").NewWorkPool(1);
+ const This = @This();
+
+ ctx: *Context,
+ task: WorkPoolTask = .{ .callback = runFromThreadPool },
+ event_loop: *VirtualMachine.EventLoop,
+ allocator: std.mem.Allocator,
+ promise: JSValue,
+ globalThis: *JSGlobalObject,
+
+ pub fn createOnJSThread(allocator: std.mem.Allocator, globalThis: *JSGlobalObject, value: *Context) !*This {
+ var this = try allocator.create(This);
+ this.* = .{
+ .event_loop = VirtualMachine.vm.event_loop,
+ .ctx = value,
+ .allocator = allocator,
+ .promise = JSValue.createInternalPromise(globalThis),
+ .globalThis = globalThis,
+ };
+ js.JSValueProtect(globalThis.ref(), this.promise.asObjectRef());
+ VirtualMachine.vm.active_tasks +|= 1;
+ return this;
+ }
+
+ pub fn runFromThreadPool(task: *WorkPoolTask) void {
+ var this = @fieldParentPtr(This, "task", task);
+ Context.run(this.ctx);
+ this.onFinish();
+ }
+
+ pub fn runFromJS(this: This) void {
+ var promise_value = this.promise;
+ var promise = promise_value.asInternalPromise() orelse {
+ if (comptime @hasDecl(Context, "deinit")) {
+ @call(.{}, Context.deinit, .{this.ctx});
+ }
+ return;
+ };
+
+ var ctx = this.ctx;
+
+ js.JSValueUnprotect(this.globalThis.ref(), promise_value.asObjectRef());
+ ctx.then(promise, this.globalThis);
+ }
+
+ pub fn schedule(this: *This) void {
+ SerialWorkPool.schedule(&this.task);
+ }
+
+ pub fn onFinish(this: *This) void {
+ this.event_loop.enqueueTaskConcurrent(Task.init(this));
+ }
+
+ pub fn deinit(this: *This) void {
+ this.allocator.destroy(this);
+ }
+ };
+}
+
pub fn IOTask(comptime Context: type) type {
return struct {
const This = @This();