@@ -162,13 +162,11 @@ pub const Status = enum {
162162const Job = union (enum ) {
163163 incoming_message : std .json .Parsed (Message ),
164164 generate_diagnostics : DocumentStore.Uri ,
165- run_build_on_save ,
166165
167166 fn deinit (self : Job , allocator : std.mem.Allocator ) void {
168167 switch (self ) {
169168 .incoming_message = > | parsed_message | parsed_message .deinit (),
170169 .generate_diagnostics = > | uri | allocator .free (uri ),
171- .run_build_on_save = > {},
172170 }
173171 }
174172
@@ -179,15 +177,12 @@ const Job = union(enum) {
179177 /// this `Job` requires shared access to `Server` and `DocumentStore`
180178 /// other non exclusive jobs can be processed in parallel
181179 shared ,
182- /// this `Job` operates atomically and does not require any synchronisation
183- atomic ,
184180 };
185181
186182 fn syncMode (self : Job ) SynchronizationMode {
187183 return switch (self ) {
188184 .incoming_message = > | parsed_message | if (isBlockingMessage (parsed_message .value )) .exclusive else .shared ,
189185 .generate_diagnostics = > .shared ,
190- .run_build_on_save = > .atomic ,
191186 };
192187 }
193188};
@@ -943,7 +938,7 @@ pub fn updateConfiguration(
943938 server .config .enable_build_on_save != false and
944939 server .client_capabilities .supports_publish_diagnostics )
945940 {
946- try server .pushJob ( .run_build_on_save );
941+ try server .thread_pool . spawn ( runBuildOnSave , .{ server } );
947942 }
948943 }
949944
@@ -1352,7 +1347,7 @@ fn saveDocumentHandler(server: *Server, arena: std.mem.Allocator, notification:
13521347 server .config .enable_build_on_save != false and
13531348 server .client_capabilities .supports_publish_diagnostics )
13541349 {
1355- try server .pushJob ( .run_build_on_save );
1350+ try server .thread_pool . spawn ( runBuildOnSave , .{ server } );
13561351 }
13571352
13581353 if (server .getAutofixMode () == .on_save ) {
@@ -1652,6 +1647,33 @@ fn selectionRangeHandler(server: *Server, arena: std.mem.Allocator, request: typ
16521647 return try selection_range .generateSelectionRanges (arena , handle , request .positions , server .offset_encoding );
16531648}
16541649
1650+ fn runBuildOnSave (server : * Server ) void {
1651+ comptime std .debug .assert (std .process .can_spawn );
1652+
1653+ // TODO data-race on server.workspaces
1654+ for (server .workspaces .items ) | * workspace | {
1655+ const was_build_on_save_running = workspace .is_build_on_save_running .swap (true , .acq_rel );
1656+ if (was_build_on_save_running ) continue ;
1657+ defer workspace .is_build_on_save_running .store (false , .release );
1658+
1659+ var arena_allocator = std .heap .ArenaAllocator .init (server .allocator );
1660+ defer arena_allocator .deinit ();
1661+ var diagnostic_set = std .StringArrayHashMapUnmanaged (std .ArrayListUnmanaged (types .Diagnostic )){};
1662+ diagnostics_gen .generateBuildOnSaveDiagnostics (server , workspace .uri , arena_allocator .allocator (), & diagnostic_set ) catch | err | {
1663+ log .err ("failed to run build on save on {s}: {}" , .{ workspace .uri , err });
1664+ return ;
1665+ };
1666+
1667+ for (diagnostic_set .keys (), diagnostic_set .values ()) | document_uri , diagnostics | {
1668+ const json_message = server .sendToClientNotification ("textDocument/publishDiagnostics" , .{
1669+ .uri = document_uri ,
1670+ .diagnostics = diagnostics .items ,
1671+ }) catch return ;
1672+ server .allocator .free (json_message );
1673+ }
1674+ }
1675+ }
1676+
16551677const HandledRequestParams = union (enum ) {
16561678 initialize : types.InitializeParams ,
16571679 shutdown ,
@@ -1816,23 +1838,17 @@ pub fn loop(server: *Server) !void {
18161838
18171839 while (server .job_queue .readItem ()) | job | {
18181840 if (zig_builtin .single_threaded ) {
1819- server .processJob (job , null );
1841+ server .processJob (job );
18201842 continue ;
18211843 }
18221844
18231845 switch (job .syncMode ()) {
18241846 .exclusive = > {
18251847 server .waitAndWork ();
1826- server .processJob (job , null );
1848+ server .processJob (job );
18271849 },
18281850 .shared = > {
1829- server .wait_group .start ();
1830- errdefer job .deinit (server .allocator );
1831- try server .thread_pool .spawn (processJob , .{ server , job , & server .wait_group });
1832- },
1833- .atomic = > {
1834- errdefer job .deinit (server .allocator );
1835- try server .thread_pool .spawn (processJob , .{ server , job , null });
1851+ server .thread_pool .spawnWg (& server .wait_group , processJob , .{ server , job });
18361852 },
18371853 }
18381854 }
@@ -1990,12 +2006,10 @@ fn processMessageReportError(server: *Server, message: Message) ?[]const u8 {
19902006 };
19912007}
19922008
1993- fn processJob (server : * Server , job : Job , wait_group : ? * std.Thread.WaitGroup ) void {
2009+ fn processJob (server : * Server , job : Job ) void {
19942010 const tracy_zone = tracy .trace (@src ());
19952011 defer tracy_zone .end ();
19962012 tracy_zone .setName (@tagName (job ));
1997- defer if (! zig_builtin .single_threaded and wait_group != null ) wait_group .? .finish ();
1998-
19992013 defer job .deinit (server .allocator );
20002014
20012015 switch (job ) {
@@ -2011,32 +2025,6 @@ fn processJob(server: *Server, job: Job, wait_group: ?*std.Thread.WaitGroup) voi
20112025 const json_message = server .sendToClientNotification ("textDocument/publishDiagnostics" , diagnostics ) catch return ;
20122026 server .allocator .free (json_message );
20132027 },
2014- .run_build_on_save = > {
2015- if (! std .process .can_spawn ) unreachable ;
2016-
2017- // TODO data-race on server.workspaces
2018- for (server .workspaces .items ) | * workspace | {
2019- const was_build_on_save_running = workspace .is_build_on_save_running .swap (true , .acq_rel );
2020- if (was_build_on_save_running ) continue ;
2021- defer workspace .is_build_on_save_running .store (false , .release );
2022-
2023- var arena_allocator = std .heap .ArenaAllocator .init (server .allocator );
2024- defer arena_allocator .deinit ();
2025- var diagnostic_set = std .StringArrayHashMapUnmanaged (std .ArrayListUnmanaged (types .Diagnostic )){};
2026- diagnostics_gen .generateBuildOnSaveDiagnostics (server , workspace .uri , arena_allocator .allocator (), & diagnostic_set ) catch | err | {
2027- log .err ("failed to run build on save on {s}: {}" , .{ workspace .uri , err });
2028- return ;
2029- };
2030-
2031- for (diagnostic_set .keys (), diagnostic_set .values ()) | document_uri , diagnostics | {
2032- const json_message = server .sendToClientNotification ("textDocument/publishDiagnostics" , .{
2033- .uri = document_uri ,
2034- .diagnostics = diagnostics .items ,
2035- }) catch return ;
2036- server .allocator .free (json_message );
2037- }
2038- }
2039- },
20402028 }
20412029}
20422030
0 commit comments