diff --git a/src/DocumentStore.zig b/src/DocumentStore.zig index d584b5095..ea5c1753d 100644 --- a/src/DocumentStore.zig +++ b/src/DocumentStore.zig @@ -483,6 +483,7 @@ config: *const Config, /// the DocumentStore assumes that `runtime_zig_version` is not modified while calling one of its functions. runtime_zig_version: *const ?ZigVersionWrapper, lock: std.Thread.RwLock = .{}, +thread_pool: if (builtin.single_threaded) void else *std.Thread.Pool, handles: std.StringArrayHashMapUnmanaged(*Handle) = .{}, build_files: std.StringArrayHashMapUnmanaged(*BuildFile) = .{}, cimports: std.AutoArrayHashMapUnmanaged(Hash, translate_c.Result) = .{}, @@ -671,6 +672,19 @@ pub fn invalidateBuildFile(self: *DocumentStore, build_file_uri: Uri) error{OutO if (self.config.build_runner_path == null) return; if (self.config.global_cache_path == null) return; + const uri = try self.allocator.dupe(u8, build_file_uri); + errdefer self.allocator.free(uri); + + if (builtin.single_threaded) { + self.invalidateBuildFileWorker(uri); + } else { + try self.thread_pool.spawn(invalidateBuildFileWorker, .{ self, uri }); + } +} + +fn invalidateBuildFileWorker(self: *DocumentStore, build_file_uri: Uri) void { + defer self.allocator.free(build_file_uri); + const build_config = loadBuildConfiguration(self, build_file_uri) catch |err| { log.err("Failed to load build configuration for {s} (error: {})", .{ build_file_uri, err }); return; @@ -1006,16 +1020,7 @@ fn createBuildFile(self: *DocumentStore, uri: Uri) error{OutOfMemory}!BuildFile } if (std.process.can_spawn) { - const Server = @import("Server.zig"); - const server = @fieldParentPtr(Server, "document_store", self); - - server.job_queue_lock.lock(); - defer server.job_queue_lock.unlock(); - - try server.job_queue.ensureUnusedCapacity(1); - server.job_queue.writeItemAssumeCapacity(.{ - .load_build_configuration = try server.allocator.dupe(u8, build_file.uri), - }); + try self.invalidateBuildFile(build_file.uri); } return build_file; diff --git a/src/Server.zig b/src/Server.zig index c10042468..0077691f5 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -142,14 +142,12 @@ pub const Status = enum { const Job = union(enum) { incoming_message: std.json.Parsed(Message), generate_diagnostics: DocumentStore.Uri, - load_build_configuration: DocumentStore.Uri, run_build_on_save, fn deinit(self: Job, allocator: std.mem.Allocator) void { switch (self) { .incoming_message => |parsed_message| parsed_message.deinit(), .generate_diagnostics => |uri| allocator.free(uri), - .load_build_configuration => |uri| allocator.free(uri), .run_build_on_save => {}, } } @@ -169,9 +167,7 @@ const Job = union(enum) { return switch (self) { .incoming_message => |parsed_message| if (parsed_message.value.isBlocking()) .exclusive else .shared, .generate_diagnostics => .shared, - .load_build_configuration, - .run_build_on_save, - => .atomic, + .run_build_on_save => .atomic, }; } }; @@ -669,23 +665,6 @@ fn registerCapability(server: *Server, method: []const u8) Error!void { server.allocator.free(json_message); } -fn invalidateAllBuildFiles(server: *Server) error{OutOfMemory}!void { - if (!std.process.can_spawn) return; - - server.document_store.lock.lockShared(); - defer server.document_store.lock.unlockShared(); - - server.job_queue_lock.lock(); - defer server.job_queue_lock.unlock(); - - try server.job_queue.ensureUnusedCapacity(server.document_store.build_files.count()); - for (server.document_store.build_files.keys()) |build_file_uri| { - server.job_queue.writeItemAssumeCapacity(.{ - .load_build_configuration = try server.allocator.dupe(u8, build_file_uri), - }); - } -} - fn requestConfiguration(server: *Server) Error!void { if (server.recording_enabled) { log.info("workspace/configuration are disabled during a recording session!", .{}); @@ -883,8 +862,12 @@ pub fn updateConfiguration(server: *Server, new_config: configuration.Configurat server.runtime_zig_version = null; } - if (new_zig_exe_path or new_build_runner_path) { - try server.invalidateAllBuildFiles(); + if (new_zig_exe_path or new_build_runner_path) blk: { + if (!std.process.can_spawn) break :blk; + + for (server.document_store.build_files.keys()) |build_file_uri| { + try server.document_store.invalidateBuildFile(build_file_uri); + } } if (new_zig_exe_path or new_zig_lib_path) { @@ -1194,9 +1177,7 @@ fn saveDocumentHandler(server: *Server, arena: std.mem.Allocator, notification: const uri = notification.textDocument.uri; if (std.process.can_spawn and DocumentStore.isBuildFile(uri)) { - try server.pushJob(.{ - .load_build_configuration = try server.allocator.dupe(u8, uri), - }); + try server.document_store.invalidateBuildFile(uri); } if (std.process.can_spawn and server.config.enable_build_on_save) { @@ -1768,6 +1749,7 @@ pub fn create(allocator: std.mem.Allocator) !*Server { .allocator = allocator, .config = &server.config, .runtime_zig_version = &server.runtime_zig_version, + .thread_pool = if (zig_builtin.single_threaded) {} else undefined, // set below }, .job_queue = std.fifo.LinearFifo(Job, .Dynamic).init(allocator), .thread_pool = undefined, // set below @@ -1781,6 +1763,7 @@ pub fn create(allocator: std.mem.Allocator) !*Server { .allocator = allocator, .n_jobs = 4, // what is a good value here? }); + server.document_store.thread_pool = &server.thread_pool; } server.ip = try InternPool.init(allocator); @@ -2031,11 +2014,6 @@ fn processJob(server: *Server, job: Job, wait_group: ?*std.Thread.WaitGroup) voi const json_message = server.sendToClientNotification("textDocument/publishDiagnostics", diagnostics) catch return; server.allocator.free(json_message); }, - .load_build_configuration => |build_file_uri| { - std.debug.assert(std.process.can_spawn); - if (!std.process.can_spawn) return; - server.document_store.invalidateBuildFile(build_file_uri) catch return; - }, .run_build_on_save => { std.debug.assert(std.process.can_spawn); if (!std.process.can_spawn) return;