mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 12:44:43 +00:00
Make ArenaPool, Robots and Env thread safety
This commit is contained in:
@@ -29,6 +29,7 @@ free_list_len: u16 = 0,
|
|||||||
free_list: ?*Entry = null,
|
free_list: ?*Entry = null,
|
||||||
free_list_max: u16,
|
free_list_max: u16,
|
||||||
entry_pool: std.heap.MemoryPool(Entry),
|
entry_pool: std.heap.MemoryPool(Entry),
|
||||||
|
mutex: std.Thread.Mutex = .{},
|
||||||
|
|
||||||
const Entry = struct {
|
const Entry = struct {
|
||||||
next: ?*Entry,
|
next: ?*Entry,
|
||||||
@@ -54,6 +55,9 @@ pub fn deinit(self: *ArenaPool) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn acquire(self: *ArenaPool) !Allocator {
|
pub fn acquire(self: *ArenaPool) !Allocator {
|
||||||
|
self.mutex.lock();
|
||||||
|
defer self.mutex.unlock();
|
||||||
|
|
||||||
if (self.free_list) |entry| {
|
if (self.free_list) |entry| {
|
||||||
self.free_list = entry.next;
|
self.free_list = entry.next;
|
||||||
self.free_list_len -= 1;
|
self.free_list_len -= 1;
|
||||||
@@ -73,6 +77,12 @@ pub fn release(self: *ArenaPool, allocator: Allocator) void {
|
|||||||
const arena: *std.heap.ArenaAllocator = @ptrCast(@alignCast(allocator.ptr));
|
const arena: *std.heap.ArenaAllocator = @ptrCast(@alignCast(allocator.ptr));
|
||||||
const entry: *Entry = @fieldParentPtr("arena", arena);
|
const entry: *Entry = @fieldParentPtr("arena", arena);
|
||||||
|
|
||||||
|
// Reset the arena before acquiring the lock to minimize lock hold time
|
||||||
|
_ = arena.reset(.{ .retain_with_limit = self.retain_bytes });
|
||||||
|
|
||||||
|
self.mutex.lock();
|
||||||
|
defer self.mutex.unlock();
|
||||||
|
|
||||||
const free_list_len = self.free_list_len;
|
const free_list_len = self.free_list_len;
|
||||||
if (free_list_len == self.free_list_max) {
|
if (free_list_len == self.free_list_max) {
|
||||||
arena.deinit();
|
arena.deinit();
|
||||||
@@ -80,7 +90,6 @@ pub fn release(self: *ArenaPool, allocator: Allocator) void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = arena.reset(.{ .retain_with_limit = self.retain_bytes });
|
|
||||||
entry.next = self.free_list;
|
entry.next = self.free_list;
|
||||||
self.free_list_len = free_list_len + 1;
|
self.free_list_len = free_list_len + 1;
|
||||||
self.free_list = entry;
|
self.free_list = entry;
|
||||||
|
|||||||
@@ -111,12 +111,16 @@ pub const RobotStore = struct {
|
|||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
map: RobotsMap,
|
map: RobotsMap,
|
||||||
|
mutex: std.Thread.Mutex = .{},
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) RobotStore {
|
pub fn init(allocator: std.mem.Allocator) RobotStore {
|
||||||
return .{ .allocator = allocator, .map = .empty };
|
return .{ .allocator = allocator, .map = .empty };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *RobotStore) void {
|
pub fn deinit(self: *RobotStore) void {
|
||||||
|
self.mutex.lock();
|
||||||
|
defer self.mutex.unlock();
|
||||||
|
|
||||||
var iter = self.map.iterator();
|
var iter = self.map.iterator();
|
||||||
|
|
||||||
while (iter.next()) |entry| {
|
while (iter.next()) |entry| {
|
||||||
@@ -132,6 +136,9 @@ pub const RobotStore = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: *RobotStore, url: []const u8) ?RobotsEntry {
|
pub fn get(self: *RobotStore, url: []const u8) ?RobotsEntry {
|
||||||
|
self.mutex.lock();
|
||||||
|
defer self.mutex.unlock();
|
||||||
|
|
||||||
return self.map.get(url);
|
return self.map.get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,11 +147,17 @@ pub const RobotStore = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(self: *RobotStore, url: []const u8, robots: Robots) !void {
|
pub fn put(self: *RobotStore, url: []const u8, robots: Robots) !void {
|
||||||
|
self.mutex.lock();
|
||||||
|
defer self.mutex.unlock();
|
||||||
|
|
||||||
const duped = try self.allocator.dupe(u8, url);
|
const duped = try self.allocator.dupe(u8, url);
|
||||||
try self.map.put(self.allocator, duped, .{ .present = robots });
|
try self.map.put(self.allocator, duped, .{ .present = robots });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn putAbsent(self: *RobotStore, url: []const u8) !void {
|
pub fn putAbsent(self: *RobotStore, url: []const u8) !void {
|
||||||
|
self.mutex.lock();
|
||||||
|
defer self.mutex.unlock();
|
||||||
|
|
||||||
const duped = try self.allocator.dupe(u8, url);
|
const duped = try self.allocator.dupe(u8, url);
|
||||||
try self.map.put(self.allocator, duped, .absent);
|
try self.map.put(self.allocator, duped, .absent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ const JsApis = bridge.JsApis;
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const IS_DEBUG = builtin.mode == .Debug;
|
const IS_DEBUG = builtin.mode == .Debug;
|
||||||
|
|
||||||
|
fn initClassIds() void {
|
||||||
|
inline for (JsApis, 0..) |JsApi, i| {
|
||||||
|
JsApi.Meta.class_id = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var class_id_once = std.once(initClassIds);
|
||||||
|
|
||||||
// The Env maps to a V8 isolate, which represents a isolated sandbox for
|
// The Env maps to a V8 isolate, which represents a isolated sandbox for
|
||||||
// executing JavaScript. The Env is where we'll define our V8 <-> Zig bindings,
|
// executing JavaScript. The Env is where we'll define our V8 <-> Zig bindings,
|
||||||
// and it's where we'll start ExecutionWorlds, which actually execute JavaScript.
|
// and it's where we'll start ExecutionWorlds, which actually execute JavaScript.
|
||||||
@@ -90,6 +98,9 @@ pub fn init(app: *App, opts: InitOpts) !Env {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize class IDs once before any V8 work
|
||||||
|
class_id_once.call();
|
||||||
|
|
||||||
const allocator = app.allocator;
|
const allocator = app.allocator;
|
||||||
const snapshot = &app.snapshot;
|
const snapshot = &app.snapshot;
|
||||||
|
|
||||||
@@ -132,8 +143,7 @@ pub fn init(app: *App, opts: InitOpts) !Env {
|
|||||||
temp_scope.init(isolate);
|
temp_scope.init(isolate);
|
||||||
defer temp_scope.deinit();
|
defer temp_scope.deinit();
|
||||||
|
|
||||||
inline for (JsApis, 0..) |JsApi, i| {
|
inline for (JsApis, 0..) |_, i| {
|
||||||
JsApi.Meta.class_id = i;
|
|
||||||
const data = v8.v8__Isolate__GetDataFromSnapshotOnce(isolate_handle, snapshot.data_start + i);
|
const data = v8.v8__Isolate__GetDataFromSnapshotOnce(isolate_handle, snapshot.data_start + i);
|
||||||
const function_handle: *const v8.FunctionTemplate = @ptrCast(data);
|
const function_handle: *const v8.FunctionTemplate = @ptrCast(data);
|
||||||
// Make function template eternal
|
// Make function template eternal
|
||||||
|
|||||||
Reference in New Issue
Block a user