Skip to content

Commit 29f0e71

Browse files
authored
Merge pull request #1158 from lightpanda-io/concurrent-waitformodule
handle multiple waiters for the same module
2 parents 1a47f7b + 9f4e3bf commit 29f0e71

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

src/browser/ScriptManager.zig

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,16 +326,31 @@ pub fn waitForModule(self: *ScriptManager, url: [:0]const u8) !GetResult {
326326
};
327327
const sync = entry.value_ptr.*;
328328

329+
// We can have multiple scripts waiting for the same module in concurrency.
330+
// We use the waiters to ensures only the last waiter deinit the resources.
331+
sync.waiters += 1;
332+
defer sync.waiters -= 1;
333+
329334
var client = self.client;
330335
while (true) {
331336
switch (sync.state) {
332337
.loading => {},
333338
.done => {
334-
// Our caller has its own higher level cache (caching the
335-
// actual compiled module). There's no reason for us to keep this
336-
defer self.sync_module_pool.destroy(sync);
337-
defer self.sync_modules.removeByPtr(entry.key_ptr);
339+
if (sync.waiters == 1) {
340+
// Our caller has its own higher level cache (caching the
341+
// actual compiled module). There's no reason for us to keep
342+
// this if we are the last waiter.
343+
defer self.sync_module_pool.destroy(sync);
344+
defer self.sync_modules.removeByPtr(entry.key_ptr);
345+
return .{
346+
.shared = false,
347+
.buffer = sync.buffer,
348+
.buffer_pool = &self.buffer_pool,
349+
};
350+
}
351+
338352
return .{
353+
.shared = true,
339354
.buffer = sync.buffer,
340355
.buffer_pool = &self.buffer_pool,
341356
};
@@ -882,6 +897,8 @@ const SyncModule = struct {
882897
manager: *ScriptManager,
883898
buffer: std.ArrayListUnmanaged(u8) = .{},
884899
state: State = .loading,
900+
// number of waiters for the module.
901+
waiters: u8 = 0,
885902

886903
const State = union(enum) {
887904
done,
@@ -997,6 +1014,7 @@ pub const AsyncModule = struct {
9971014
var self: *AsyncModule = @ptrCast(@alignCast(ctx));
9981015
defer self.manager.async_module_pool.destroy(self);
9991016
self.cb(self.cb_data, .{
1017+
.shared = false,
10001018
.buffer = self.buffer,
10011019
.buffer_pool = &self.manager.buffer_pool,
10021020
});
@@ -1020,8 +1038,13 @@ pub const AsyncModule = struct {
10201038
pub const GetResult = struct {
10211039
buffer: std.ArrayListUnmanaged(u8),
10221040
buffer_pool: *BufferPool,
1041+
shared: bool,
10231042

10241043
pub fn deinit(self: *GetResult) void {
1044+
// if the result is shared, don't deinit.
1045+
if (self.shared) {
1046+
return;
1047+
}
10251048
self.buffer_pool.release(self.buffer);
10261049
}
10271050

0 commit comments

Comments
 (0)