Ada 中的信号量
Semaphore in Ada
这是一项作业,我被要求在 Ada 中实现一个信号量,如下所述。
但是我已经实现了 Semaphore.adb
并在我创建的 producerconsumer_sem.adb
中调用了这个信号量。
我得到如下输出。
我不确定我的信号量初始化是否正确S: CountingSemaphore(1,1);
.
我不知道我在哪里调用 S.wait
和 S.Signal
现在我在生产者将项目放入缓冲区之前随机调用 S.wait
X := I;
和 X := I;
之后的 S.Signal
。
这是正确的方法吗?
Producer-Consumer Problem
The program producerconsumer.adb
implements a non-reliable implemen-
tation of the producer-consumer problem, where data is likely be lost. In
the following, you will use three different communication mechanisms to
achieve a reliable implementation of the producer-consumer problem.
Semaphore
The Ada language does not directly provide library functions for a semaphore.
However, semaphores can be implemented by means of a protected object. Create a package specification Semaphore in the file Semaphores.ads
and the corresponding package body in the file Semaphores.adb
that
implements a counting semaphore. Skeletons for the package are available on the course page.
Use the semaphore package for a reliable implementation of the producer-
consumer problem. Modify the file producerconsumer.adb
and save the
final code as producerconsumer_sem.adb
. In order to use the semaphore
package it shall be installed in the same directory as producerconsumer_sem.adb
.
It can then be accessed by
with Semaphores;
use Semaphores;
输出:
OutPut:
1
1
1
2
2
3
4
4
5
6
6
7
7
8
9
9
9
10
11
11
11
12
12
13
13
13
14
15
15
16
16
17
18
18
18
19
20
20
21
21
22
22
23
24
24
24
24
25
25
26
27
27
28
29
29
30
30
31
31
32
32
33
33
33
34
35
35
35
36
36
37
37
37
38
38
38
39
40
40
40
包
package Semaphores is
protected type CountingSemaphore(Max: Natural; Initial: Natural) is
entry Wait;
entry Signal;
private
Count : Natural := Initial;
MaxCount : Natural := Max;
end CountingSemaphore;
end Semaphores;
我实现的信号量semaphores.adb
。
package body Semaphores is
protected body CountingSemaphore is
entry Wait when Count > 0 is
begin
Count := Count - 1;
end Wait;
entry Signal when Count < MaxCount is
begin
Count := Count + 1;
end Signal;
end CountingSemaphore;
end Semaphores;
producerconsumer_sem.adb
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Real_Time;
use Ada.Real_Time;
with Ada.Numerics.Discrete_Random;
with Semaphores;
use Semaphores;
procedure ProducerConsumer_sem is
X : Integer; -- Shared Variable
N : constant Integer := 40; -- Number of produced and comsumed variables
S: CountingSemaphore(1,1);
--S1: CountingSemaphore(1,1);
pragma Volatile(X); -- For a volatile object all reads and updates of
-- the object as a whole are performed directly
-- to memory (Ada Reference Manual, C.6)
--Random Delays
subtype Delay_Interval is Integer range 50..250;
package Random_Delay is new Ada.Numerics.Discrete_Random
(Delay_Interval);
use Random_Delay;
G : Generator;
task Producer;
task Consumer;
task body Producer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Write to X
S.Wait;
X := I;
S.Signal;
--Next 'Release' in 50..250ms
Next := Next + Milliseconds(Random(G));
Put_Line(Integer'Image(X));
delay until Next;
end loop;
end;
task body Consumer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Read from X
S.Wait;
Put_Line(Integer'Image(X));
S.Signal;
Next := Next + Milliseconds(Random(G));
delay until Next;
end loop;
end;
begin -- main task
null;
end ProducerConsumer_sem;
在 macOS 上,使用 FSF GCC 7.1.0 和 GNAT GPL 2017,我将你的 Put_Line
s 更改为 Put
s 并得到了你在问题中陈述的大部分答案。
问题说创建Semaphore.ads
、.adb
。这将适用于 Windows,并且可能适用于 macOS,但不适用于 Linux,因为 GNAT 的文件命名约定(请参阅 this 的结尾;这是一个好主意养成使用小写文件名的习惯)。
如果您想确保一次只有一个任务可以访问 X
,我认为您的 Wait
、Signal
调用没有太大问题,不过当我在 Producer
的开头放置一个 delay 0.1
时,第一个值输出是 151619216(因为 X
未初始化)。然而!如果重点是一次向 X 传达一个更新(正如名称 producer/consumer 所暗示的那样),您应该
- 初始化信号量为 0(最大为 1)。这使它成为二进制信号量。
- 仅在
Consumer
中 Wait
(即删除 Signal
)
- 仅在
Producer
、Signal
中(即删除 Wait
)。另外,删除 Put
以避免混淆!
这是一项作业,我被要求在 Ada 中实现一个信号量,如下所述。
但是我已经实现了 Semaphore.adb
并在我创建的 producerconsumer_sem.adb
中调用了这个信号量。
我得到如下输出。
我不确定我的信号量初始化是否正确
S: CountingSemaphore(1,1);
.我不知道我在哪里调用
S.wait
和S.Signal
现在我在生产者将项目放入缓冲区之前随机调用S.wait
X := I;
和X := I;
之后的S.Signal
。 这是正确的方法吗?
Producer-Consumer Problem The program
producerconsumer.adb
implements a non-reliable implemen- tation of the producer-consumer problem, where data is likely be lost. In the following, you will use three different communication mechanisms to achieve a reliable implementation of the producer-consumer problem.Semaphore
The Ada language does not directly provide library functions for a semaphore. However, semaphores can be implemented by means of a protected object. Create a package specification Semaphore in the file Semaphores.ads and the corresponding package body in the file
Semaphores.adb
that implements a counting semaphore. Skeletons for the package are available on the course page.Use the semaphore package for a reliable implementation of the producer- consumer problem. Modify the file
producerconsumer.adb
and save the final code asproducerconsumer_sem.adb
. In order to use the semaphore package it shall be installed in the same directory asproducerconsumer_sem.adb
. It can then be accessed by
with Semaphores;
use Semaphores;
输出:
OutPut: 1 1 1 2 2 3 4 4 5 6 6 7 7 8 9 9 9 10 11 11 11 12 12 13 13 13 14 15 15 16 16 17 18 18 18 19 20 20 21 21 22 22 23 24 24 24 24 25 25 26 27 27 28 29 29 30 30 31 31 32 32 33 33 33 34 35 35 35 36 36 37 37 37 38 38 38 39 40 40 40
包
package Semaphores is
protected type CountingSemaphore(Max: Natural; Initial: Natural) is
entry Wait;
entry Signal;
private
Count : Natural := Initial;
MaxCount : Natural := Max;
end CountingSemaphore;
end Semaphores;
我实现的信号量semaphores.adb
。
package body Semaphores is
protected body CountingSemaphore is
entry Wait when Count > 0 is
begin
Count := Count - 1;
end Wait;
entry Signal when Count < MaxCount is
begin
Count := Count + 1;
end Signal;
end CountingSemaphore;
end Semaphores;
producerconsumer_sem.adb
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Real_Time;
use Ada.Real_Time;
with Ada.Numerics.Discrete_Random;
with Semaphores;
use Semaphores;
procedure ProducerConsumer_sem is
X : Integer; -- Shared Variable
N : constant Integer := 40; -- Number of produced and comsumed variables
S: CountingSemaphore(1,1);
--S1: CountingSemaphore(1,1);
pragma Volatile(X); -- For a volatile object all reads and updates of
-- the object as a whole are performed directly
-- to memory (Ada Reference Manual, C.6)
--Random Delays
subtype Delay_Interval is Integer range 50..250;
package Random_Delay is new Ada.Numerics.Discrete_Random
(Delay_Interval);
use Random_Delay;
G : Generator;
task Producer;
task Consumer;
task body Producer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Write to X
S.Wait;
X := I;
S.Signal;
--Next 'Release' in 50..250ms
Next := Next + Milliseconds(Random(G));
Put_Line(Integer'Image(X));
delay until Next;
end loop;
end;
task body Consumer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Read from X
S.Wait;
Put_Line(Integer'Image(X));
S.Signal;
Next := Next + Milliseconds(Random(G));
delay until Next;
end loop;
end;
begin -- main task
null;
end ProducerConsumer_sem;
在 macOS 上,使用 FSF GCC 7.1.0 和 GNAT GPL 2017,我将你的 Put_Line
s 更改为 Put
s 并得到了你在问题中陈述的大部分答案。
问题说创建Semaphore.ads
、.adb
。这将适用于 Windows,并且可能适用于 macOS,但不适用于 Linux,因为 GNAT 的文件命名约定(请参阅 this 的结尾;这是一个好主意养成使用小写文件名的习惯)。
如果您想确保一次只有一个任务可以访问 X
,我认为您的 Wait
、Signal
调用没有太大问题,不过当我在 Producer
的开头放置一个 delay 0.1
时,第一个值输出是 151619216(因为 X
未初始化)。然而!如果重点是一次向 X 传达一个更新(正如名称 producer/consumer 所暗示的那样),您应该
- 初始化信号量为 0(最大为 1)。这使它成为二进制信号量。
- 仅在
Consumer
中Wait
(即删除Signal
) - 仅在
Producer
、Signal
中(即删除Wait
)。另外,删除Put
以避免混淆!