在 Ada 中,如何将当前时间(以秒为单位)作为可以打印出来并执行操作的值?
Posted
技术标签:
【中文标题】在 Ada 中,如何将当前时间(以秒为单位)作为可以打印出来并执行操作的值?【英文标题】:In Ada, how do I get the current time in seconds as a value I can print out and perform operations with? 【发布时间】:2013-12-05 20:10:49 【问题描述】:我正在为一个操作系统类做一个项目。我需要编写一个程序,每十秒打印一次当前时间,但还要考虑开销的延迟,以便它在长时间运行时不会漂移。我还需要它至少保持小数点后 1 位。
我被困在第 1 步,因为我不知道如何以秒为单位获取当前时间作为值。我已经搜索但只能找到如何以 HH:MM:SS 格式获取当前时间。
谢谢
【问题讨论】:
您应该在此处发布您的代码。检查指南 How to Ask 和 SSCCE 你看过Ada.Calendar和Ada.Real_Time的定义了吗?你能解释一下为什么那个包中的操作不能满足你的需要吗? 我知道我可能遗漏了一些明显的东西,但我看不到从这些定义中获取值的方法。 “价值”是什么意思?如果您尝试将“当前时间(以秒为单位)”作为单个数字返回,您需要意识到没有这样的事情,除非它与某个其他时间点有关,即“自某个特定时间以来的秒数时间点(例如 1970 年 1 月 1 日午夜)。如果这是您需要的,可以从Ada.Calendar
轻松获得。
【参考方案1】:
这是我想出的:
writing_test.ads
package Writing_Test is
protected Writer is
entry write( Text : String; New_Line : Boolean:= True );
end Writer;
task Timer is
entry Start;
entry Pause;
entry Stop;
end Timer;
private
Timer_Frequency : constant Duration:= 10.0;
end Writing_Test;
writing_test.adb
with
Ada.Calendar,
Ada.Text_IO;
package body Writing_Test is
protected body Writer is
entry write( Text : String; New_Line : Boolean:= True ) when True is
begin
Ada.Text_IO.Put( Text );
if New_Line then
Ada.Text_IO.New_Line;
end if;
end;
end Writer;
task body Timer is
Active,
Stop_Task : Boolean:= False;
Next_Time : Ada.Calendar.Time;
use type Ada.Calendar.Time;
begin
MAIN:
loop
if not Active then
select
accept Start do
Active:= True;
Next_Time:= Ada.Calendar.Clock + Timer_Frequency;
end Start;
or
terminate;
end select;
else
select
accept Pause do
Active:= False;
end Pause;
or
accept Stop do
Stop_Task:= True;
end Stop;
or
delay until Next_Time;
end select;
exit MAIN when Stop_Task;
if Active then
declare
Use Ada.Calendar;
Now : Time renames Clock;
Str : String renames
Day_Duration'Image( Ada.Calendar.Seconds(Now) );
--' Formatter-correction trick
begin
Writer.write(Text => Str);
Next_Time:= Next_Time + Timer_Frequency;
end;
end if;
end if;
end loop MAIN;
end Timer;
end Writing_Test;
【讨论】:
您已经回答了整个班级的问题(而不仅仅是 OP 实际提出的问题)。另外,在受保护的操作中调用Text_IO
不是有界错误吗?
是的,这是一个有界错误;我也不确定我的回答是否正确:对于某些定义,这可能会“漂移”——因为它在操作完成后重置为 10 秒,而不是始终在 Start+(n*10)
n in Integer 处执行。
是的,这两句话都是真的。受保护操作中潜在的阻塞调用是一个错误(参见 rm 9.5.1 受保护的子程序和受保护的操作)。另外,这个程序有偏差,您应该对其进行编辑,以便始终从开始时间计算 Next_Time。
我怀疑这个程序会漂移。 1:计时部分直接按书。 2:Ada中时间相关的类型都是定精度类型。 (但我当然愿意解释为什么它会漂移。)
@Jacob,我改了:Writer.Write 之后的赋值是:Next_Time:= Now + Timer_Frequency;【参考方案2】:
这是一个执行“每 10 秒打印一次”部分的简单程序。您可以轻松地在单独的包中使用此代码。
with Ada.Text_IO;
with Ada.Calendar;
procedure Periodic_Printer is
task type My_Printer_Task is
end My_Printer_Task;
task body My_Printer_Task is
use Ada.Calendar; -- for the "-" and "+" operations on Time
Start_Time : Ada.Calendar.Time;
Next_Cycle : Ada.Calendar.Time;
Period : constant Duration := 10.0;
begin
Start_Time := Ada.Calendar.Clock;
Next_Cycle := Start_Time;
loop
Ada.Text_IO.Put_Line(Duration'Image(Ada.Calendar.Clock - Start_Time)); --'
-- You could use Next_Cycle instead of Ada.Calendar.Clock - Start_Time
-- so the printing does not depend of the time needed to do the elapsed
-- time calculation
delay 3.0; -- like a long operation, takes time......
-- This pattern assumes the each cycle last less than Period
-- If you cannot ensure that, you should consider improving
-- the pattern or reduce the computation load of each cycle
Next_Cycle := Next_Cycle + Period;
delay until Next_Cycle;
end loop;
end My_Printer_Task;
Printer : My_Printer_Task;
begin
delay 90.0; -- You can do your 'real work' here.
-- Unclean way to terminate a task, you should consider improve it for a
-- real world scenario
abort Printer;
Ada.Text_IO.Put_Line("End of program");
end Periodic_Printer;
【讨论】:
以上是关于在 Ada 中,如何将当前时间(以秒为单位)作为可以打印出来并执行操作的值?的主要内容,如果未能解决你的问题,请参考以下文章
返回要使用 AudioTrack 播放的曲目的长度(以秒为单位)
如何测量 powershell 脚本中不同功能的持续时间(以秒为单位)?