Skip to content

Commit 3705224

Browse files
committed
Add job lists for High and Low priorities.
Call `Complete` on `Fence` jobs. Refs #1141
1 parent 47dc44d commit 3705224

File tree

4 files changed

+135
-35
lines changed

4 files changed

+135
-35
lines changed

source/server/lsp-job_schedulers.adb

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,58 @@
1818
with Ada.Unchecked_Conversion;
1919
with Ada.Unchecked_Deallocation;
2020
with System.Storage_Elements;
21-
with LSP.Server_Jobs;
2221

2322
package body LSP.Job_Schedulers is
2423

2524
procedure Free is new Ada.Unchecked_Deallocation
2625
(LSP.Server_Jobs.Server_Job'Class, LSP.Server_Jobs.Server_Job_Access);
2726

27+
procedure Complete_Last_Fence_Job
28+
(Self : in out Job_Scheduler'Class;
29+
Next : LSP.Server_Messages.Server_Message_Access);
30+
-- Call Complete on the last done Fence job (if any) and free it
31+
32+
-----------------------------
33+
-- Complete_Last_Fence_Job --
34+
-----------------------------
35+
36+
procedure Complete_Last_Fence_Job
37+
(Self : in out Job_Scheduler'Class;
38+
Next : LSP.Server_Messages.Server_Message_Access) is
39+
begin
40+
if Self.Done.Assigned then
41+
Self.Done.Complete (Next);
42+
Free (Self.Done);
43+
end if;
44+
end Complete_Last_Fence_Job;
45+
2846
----------------
2947
-- Create_Job --
3048
----------------
3149

3250
procedure Create_Job
3351
(Self : in out Job_Scheduler'Class;
34-
Message : in out LSP.Server_Messages.Server_Message_Access) is
52+
Message : in out LSP.Server_Messages.Server_Message_Access)
53+
is
54+
Cursor : constant Handler_Maps.Cursor :=
55+
Self.Handlers.Find (Message'Tag);
56+
57+
Job : LSP.Server_Jobs.Server_Job_Access;
3558
begin
36-
Self.Message := Message;
37-
Message := null;
59+
if Handler_Maps.Has_Element (Cursor) then
60+
61+
Job := Handler_Maps.Element (Cursor).Create_Job (Message);
62+
63+
if Job.Assigned then
64+
Message := null;
65+
66+
if Job.Priority in Self.Jobs'Range then
67+
Self.Jobs (Job.Priority).Append (Job);
68+
else
69+
Self.Blocker := Job;
70+
end if;
71+
end if;
72+
end if;
3873
end Create_Job;
3974

4075
--------------
@@ -43,7 +78,8 @@ package body LSP.Job_Schedulers is
4378

4479
function Has_Jobs (Self : Job_Scheduler'Class) return Boolean is
4580
begin
46-
return Self.Message.Assigned;
81+
return Self.Blocker.Assigned or else
82+
(for some List of Self.Jobs => not List.Is_Empty);
4783
end Has_Jobs;
4884

4985
----------
@@ -68,43 +104,83 @@ package body LSP.Job_Schedulers is
68104
LSP.Client_Message_Receivers.Client_Message_Receiver'Class;
69105
Waste : out LSP.Server_Messages.Server_Message_Access)
70106
is
71-
Job : LSP.Server_Jobs.Server_Job_Access;
107+
use all type LSP.Server_Jobs.Job_Priority;
108+
109+
procedure Execute (Job : LSP.Server_Jobs.Server_Job_Access);
110+
111+
-------------
112+
-- Execute --
113+
-------------
114+
115+
procedure Execute (Job : LSP.Server_Jobs.Server_Job_Access) is
116+
begin
117+
Self.Complete_Last_Fence_Job (Job.Message);
118+
Waste := Job.Message;
119+
120+
while not Job.Is_Done loop
121+
Job.Execute (Client);
122+
end loop;
123+
end Execute;
124+
125+
Job : LSP.Server_Jobs.Server_Job_Access renames Self.Blocker;
72126
begin
73-
Waste := null;
127+
if not Job.Assigned then
128+
Waste := null;
74129

75-
-- Process the most recent message if any
76-
if Self.Message.Assigned then
77-
declare
78-
Cursor : constant Handler_Maps.Cursor :=
79-
Self.Handlers.Find (Self.Message'Tag);
80-
begin
81-
if Handler_Maps.Has_Element (Cursor) then
82-
Job := Handler_Maps.Element (Cursor).Create_Job (Self.Message);
83-
Self.Message := null;
84-
else
85-
Waste := Self.Message;
86-
Self.Message := null;
130+
return;
131+
end if;
132+
133+
if Job.Priority = Fence then
134+
-- Process other jobs before any Fence job
135+
while (for some List of Self.Jobs => not List.Is_Empty) loop
136+
Self.Process_Job (Client, Waste);
137+
138+
if Waste.Assigned then
87139
return;
88140
end if;
89-
end;
141+
end loop;
142+
143+
Execute (Job);
144+
Self.Done := Job; -- keep Job live till Complete call
145+
Job := null;
90146
else
91-
null; -- TBD: find next job here
147+
Execute (Job);
148+
Free (Job);
92149
end if;
150+
end Process_High_Priority_Job;
93151

94-
while Job.Assigned loop
95-
Job.Execute (Client);
152+
-----------------
153+
-- Process_Job --
154+
-----------------
155+
156+
procedure Process_Job
157+
(Self : in out Job_Scheduler'Class;
158+
Client :
159+
in out LSP.Client_Message_Receivers.Client_Message_Receiver'Class;
160+
Waste : out LSP.Server_Messages.Server_Message_Access) is
161+
begin
162+
for List of reverse Self.Jobs when not List.Is_Empty loop
163+
declare
164+
Job : LSP.Server_Jobs.Server_Job_Access := List.First_Element;
165+
begin
166+
List.Delete_First;
167+
Self.Complete_Last_Fence_Job (Job.Message);
168+
Job.Execute (Client);
169+
170+
if Job.Is_Done then
171+
Waste := Job.Message;
172+
Free (Job);
173+
else
174+
Waste := null;
175+
List.Append (Job); -- Push the job back to the queue
176+
end if;
96177

97-
if Job.Is_Done then
98-
-- TBD: Call complete?
99-
Waste := Job.Message;
100-
Free (Job);
101178
exit;
102-
else
103-
raise Program_Error with "Unimplemeted";
104-
-- TBD: put job back to the queue
105-
end if;
179+
end;
106180
end loop;
107-
end Process_High_Priority_Job;
181+
182+
Self.Complete_Last_Fence_Job (null);
183+
end Process_Job;
108184

109185
----------------------
110186
-- Register_Handler --

source/server/lsp-job_schedulers.ads

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
------------------------------------------------------------------------------
1717

1818
with Ada.Containers.Hashed_Maps;
19+
with Ada.Containers.Doubly_Linked_Lists;
1920
with Ada.Tags;
2021

2122
with LSP.Client_Message_Receivers;
23+
with LSP.Server_Jobs;
2224
with LSP.Server_Message_Handlers;
2325
with LSP.Server_Messages;
2426

@@ -41,6 +43,8 @@ package LSP.Job_Schedulers is
4143
Message : in out LSP.Server_Messages.Server_Message_Access);
4244
-- Create a job to process a server message. The scheduler takes ownership
4345
-- of the message and will return it to the server when the job is done.
46+
-- If there is no handler for the message, then the scheduler doesn't
47+
-- accept message and server should destroy it.
4448

4549
procedure Process_High_Priority_Job
4650
(Self : in out Job_Scheduler'Class;
@@ -56,7 +60,7 @@ package LSP.Job_Schedulers is
5660
(Self : in out Job_Scheduler'Class;
5761
Client :
5862
in out LSP.Client_Message_Receivers.Client_Message_Receiver'Class;
59-
Waste : out LSP.Server_Messages.Server_Message_Access) is null;
63+
Waste : out LSP.Server_Messages.Server_Message_Access);
6064
-- Execute jobs with ordinal priority (Low, High).
6165
-- When a job is done the routine returns (in Waste) the message to be
6266
-- deallocated by the server. The Client is used to send messages during
@@ -73,10 +77,21 @@ private
7377
Ada.Tags."=",
7478
LSP.Server_Message_Handlers."=");
7579

80+
package Job_Lists is new Ada.Containers.Doubly_Linked_Lists
81+
(LSP.Server_Jobs.Server_Job_Access, LSP.Server_Jobs."=");
82+
83+
subtype Ordinal_Priority is LSP.Server_Jobs.Job_Priority
84+
range LSP.Server_Jobs.Low .. LSP.Server_Jobs.High;
85+
86+
type Job_List_Array is array (Ordinal_Priority) of Job_Lists.List;
87+
7688
type Job_Scheduler is tagged limited record
77-
Message : LSP.Server_Messages.Server_Message_Access;
78-
-- Last added message
89+
Blocker : LSP.Server_Jobs.Server_Job_Access;
90+
-- A job with non-ordinal priority (Immediate, Fence)
91+
Done : LSP.Server_Jobs.Server_Job_Access;
92+
-- A job with Fence priority to be completed
7993
Handlers : Handler_Maps.Map;
94+
Jobs : Job_List_Array;
8095
end record;
8196

8297
end LSP.Job_Schedulers;

source/server/lsp-server_jobs.ads

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ package LSP.Server_Jobs is
3434
-- new messages until the job is done. Server execute each job in its
3535
-- queue before executing any Fence job.
3636

37+
subtype Ordinal_Priority is Job_Priority range Low .. High;
38+
3739
type Server_Job is limited interface;
3840

3941
function Priority (Self : Server_Job) return Job_Priority is abstract;
@@ -55,6 +57,7 @@ package LSP.Server_Jobs is
5557
Next : LSP.Server_Messages.Server_Message_Access) is null
5658
with Pre'Class => Is_Done (Self);
5759
-- Complete message execution. The next message is provided if any.
60+
-- Currently this is called only for Fence jobs.
5861

5962
procedure Cancel
6063
(Self : in out Server_Job;
@@ -68,6 +71,7 @@ package LSP.Server_Jobs is
6871

6972
function Message (Self : Server_Job)
7073
return LSP.Server_Messages.Server_Message_Access is abstract;
74+
-- Message to be destroyed when the job is done
7175

7276
function Assigned (Self : access Server_Job'Class) return Boolean is
7377
(Self /= null);

source/server/lsp-servers.adb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,11 @@ package body LSP.Servers is
865865
begin
866866
Server.Scheduler.Create_Job (Message);
867867

868+
if Message.Assigned then
869+
-- Scheduler wasn't able to process message, destroy it
870+
Server.Destroy_Queue.Enqueue (Message);
871+
end if;
872+
868873
loop
869874
declare
870875
Waste : Server_Message_Access;

0 commit comments

Comments
 (0)