1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 | -- --
-- package Copyright (c) Dmitry A. Kazakov --
-- Synchronization. Luebeck --
-- Generic_Events_Array Spring, 2008 --
-- Interface Spring, 2008 --
-- --
-- Last revision : 16:09 11 May 2008 --
-- --
-- This library is free software; you can redistribute it and/or --
-- modify it under the terms of the GNU General Public License as --
-- published by the Free Software Foundation; either version 2 of --
-- the License, or (at your option) any later version. This library --
-- is distributed in the hope that it will be useful, but WITHOUT --
-- ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
-- General Public License for more details. You should have --
-- received a copy of the GNU General Public License along with --
-- this library; if not, write to the Free Software Foundation, --
-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
-- --
-- As a special exception, if other files instantiate generics from --
-- this unit, or you link this unit with other files to produce an --
-- executable, this unit does not by itself cause the resulting --
-- executable to be covered by the GNU General Public License. This --
-- exception does not however invalidate any other reasons why the --
-- executable file might be covered by the GNU Public License. --
--____________________________________________________________________--
--
-- This package provides arrays of events. Any combination of events
-- from the array can be signaled, reset or awaited for. The
-- implementation represented here is free of race conditions. When the
-- state of the events is being changed it is guarantee that all tasks
-- awaiting for the state are released before any consequent state
-- change. Another class race condition problems is eliminated by
-- providing atomic signal-then-wait operations. For instance a set of
-- tasks may synchronize themselves at dedicated points by signaling an
-- event and then awaiting for all events signaled. If the task later
-- resets its event, that would constitute a race condition. Because a
-- task might reset its event before other tasks queue for all events
-- set. The following figure illustrates the case:
--
-- task A task B
-- |
-- |
-- |
-- | working
-- |______________________.
-- | working
-- |
-- .______________________|
-- | signal event A
-- |
-- | wait for events A, B
-- | (blocked)
-- |______________________.
-- | signal event B
-- .______________________|
-- | (released)
-- | reset event A
-- |______________________.
-- |
-- | wait for events A, B
-- _______________________| (deadlocked, because A is
-- prematurely reset)
--
-- The race condition is between the task A reseting the event A and
-- the task B awaiting for the event A. The condition is broken when
-- each task atomically signals its event and queues for waiting.
--
with Ada.Finalization;
generic
type Event_Type is (<>);
package Synchronization.Generic_Events_Array is
--
-- Events_State -- The array of event states
--
type Events_State is array (Event_Type) of Boolean;
function "or" (Left, Right : Event_Type) return Events_State;
function "or" (Left : Events_State; Right : Event_Type)
return Events_State;
function "or" (Left : Event_Type; Right : Events_State)
return Events_State;
function "not" (Left : Event_Type) return Events_State;
--
-- Abstract_Condition -- An abstract condition to wait for. The entries
-- of the events array awaits for instances of the
-- types derived from this base type. The derived type shall override
-- the abstract primitive operation Satisfied.
--
type Abstract_Condition is abstract
new Ada.Finalization.Controlled with null record;
--
-- Satisfied -- Condition check
--
-- Condition - The check for
-- State - The current state of the events
--
-- This function is used to check if the condition is satisfied. Note
-- that the function is called in the course of a protected action. That
-- means, that it shall neither block, nor invoke any other protected
-- actions. Further if it accesses shared non-local data, the user shall
-- warranty that these data are either atomic or else are never accessed
-- outside the protected actions of Events_Array.
--
-- Returns :
--
-- True if the condition is satisfied by State
--
function Satisfied
( Condition : Abstract_Condition;
State : Events_State
) return Boolean is abstract;
--
-- Some frequently used conditions
--
-- Always_Signaled - No wait, the condition is always satisfied
-- All_Signaled - Satisfied when all events are signaled
-- Any_Signaled - Satisfied when at least one event is signaled
-- No_Signaled - Satisfied when no event is signaled
--
Always_Signaled : constant Abstract_Condition'Class;
All_Signaled : constant Abstract_Condition'Class;
Any_Signaled : constant Abstract_Condition'Class;
No_Signaled : constant Abstract_Condition'Class;
--
-- Event_Signaled -- Satisfied when a particular event is signaled
--
-- Event - The event to wait for
--
-- This condition can be used as follows:
--
-- Flags.Wait (Signaled (Event));
--
type Event_Signaled (Event : Event_Type) is
new Abstract_Condition with null record;
function Satisfied (Condition : Event_Signaled; State : Events_State)
return Boolean;
function Signaled (Event : Event_Type) return Event_Signaled;
--
-- Event_Reset -- Satisfied when a particular event is reset
--
-- Event - The event to wait for
--
-- This condition can be used as follows:
--
-- Flags.Wait (Reset (Event));
--
type Event_Reset (Event : Event_Type) is
new Abstract_Condition with null record;
function Satisfied (Condition : Event_Reset; State : Events_State)
return Boolean;
function Reset (Event : Event_Type) return Event_Reset;
--
-- Events_Array -- An array of events. Initially all events in the array
-- are non-signaled.
--
protected type Events_Array is
--
-- Get_State -- The current state of the events
--
-- This function returns the state of the array. The result is an
-- array which for each event contains True if the event is signaled.
--
-- Returns :
--
-- The current state of events
--
function Get_State return Events_State;
--
-- Is_Signaled -- The current event state
--
-- Event - The event to get the state of
--
-- Returns :
--
-- True if the event is signaled
--
function Is_Signaled (Event : Event_Type) return Boolean;
--
-- Reset -- Event(s) to the non-signaled state
--
-- Event[s] - An array, or else an event
-- Condition - A condition to wait for after resetting the events
--
-- When the parameter is an event, then the event is set to the
-- non-signaled state. When the parameter is an array, then each
-- event for which the array contains True is set to the non-signaled
-- state. The parameter Condition is the condition to wait for
-- immediately after resetting the events. The default value is
-- Always_Signaled, i.e. Reset returns after changing the events
-- without waiting.
--
entry Reset
( Events : Events_State;
Condition : Abstract_Condition'Class := Always_Signaled
);
entry Reset
( Event : Event_Type;
Condition : Abstract_Condition'Class := Always_Signaled
);
--
-- Signal -- Event(s)
--
-- Event[s] - An array, or else an event
-- Condition - A condition to wait for after signaling the events
--
-- When the parameter is an event, then the event is set to the
-- signaled state. When the parameter is an array, then each event
-- for which the array contains True is set to the signaled state.
-- The parameter Condition specifies the condition to wait for
-- immediately after signaling the events. The default value is
-- Always_Signaled, i.e. Signal returns after changing the events
-- without waiting.
--
entry Signal
( Events : Events_State;
Condition : Abstract_Condition'Class := Always_Signaled
);
entry Signal
( Event : Event_Type;
Condition : Abstract_Condition'Class := Always_Signaled
);
--
-- Set -- Events to a definite state
--
-- State - To set
-- Condition - A condition to wait for
--
-- This entry sets all events according to the value io State. The
-- parameter Condition specifies the condition to wait for,
-- immediately after setting the events. The default value is
-- Always_Signaled, i.e. Set returns after changing the events
-- without waiting.
--
entry Set
( State : Events_State;
Condition : Abstract_Condition'Class := Always_Signaled
);
--
-- Wait -- For a condition
--
-- Condition - Wait condition
--
-- This entries waits for Condition. See also Signal, Reset and Set
-- entries which also are capable of waiting for a certain condition.
--
entry Wait (Condition : Abstract_Condition'Class);
private
pragma Inline (Is_Signaled);
pragma Inline (Get_State);
--
-- Empty_Lounges -- Check if all current longues are empty
--
function Empty_Lounges return Boolean;
pragma Inline (Empty_Lounges);
--
-- Lounge_* -- Waiting rooms for not yet satisfied conditions
--
entry Lounge_Set_Multiple (Boolean)
( Events : Events_State;
Condition : Abstract_Condition'Class
);
entry Lounge_Set_Single (Boolean)
( Event : Event_Type;
Condition : Abstract_Condition'Class
);
entry Lounge_Wait (Boolean)
( Condition : Abstract_Condition'Class
);
Current : Boolean := False;
State : Events_State := (others => False);
end Events_Array;
private
type Always is new Abstract_Condition with null record;
function Satisfied (Condition : Always; State : Events_State)
return Boolean;
type Any is new Abstract_Condition with null record;
function Satisfied (Condition : Any; State : Events_State)
return Boolean;
type Each is new Abstract_Condition with null record;
function Satisfied (Condition : Each; State : Events_State)
return Boolean;
type None is new Abstract_Condition with null record;
function Satisfied (Condition : None; State : Events_State)
return Boolean;
Always_Signaled : constant Abstract_Condition'Class :=
Always'(Ada.Finalization.Controlled with null record);
All_Signaled : constant Abstract_Condition'Class :=
Each'(Ada.Finalization.Controlled with null record);
Any_Signaled : constant Abstract_Condition'Class :=
Any'(Ada.Finalization.Controlled with null record);
No_Signaled : constant Abstract_Condition'Class :=
None'(Ada.Finalization.Controlled with null record);
pragma Inline (Satisfied);
pragma Inline (Signaled);
pragma Inline (Reset);
pragma Inline ("or", "not");
end Synchronization.Generic_Events_Array;
|