當Ada應用程序關機/死機時,我想調用一些「清理」調用。Ada關機鉤
舉例來說,如果我是在Java中,我會做這樣的事情,以獲得具有一種叫做在關機的效果:
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
method();
}
});
是否有類似的事情在阿達或另一種方式來實現這一目標?
當Ada應用程序關機/死機時,我想調用一些「清理」調用。Ada關機鉤
舉例來說,如果我是在Java中,我會做這樣的事情,以獲得具有一種叫做在關機的效果:
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
method();
}
});
是否有類似的事情在阿達或另一種方式來實現這一目標?
您可以爲主過程創建一個Controlled(或Limited_Controlled)對象,該過程在其Finalization方法中調用必需的東西。
請注意,您無法訪問主過程的任何局部變量,因此請將任何必需的東西放入受控對象中。
例如:
with Ada.Text_IO;
with Ada.Finalization;
procedure Main is
type Cleaner is new Ada.Finalization.Limited_Controlled with record
Some_Interesting_Data : Integer;
end record;
overriding procedure Finalize (X : in out Cleaner) is
begin
Ada.Text_IO.Put_Line ("Cleaning..." & Integer'Image (X.Some_Interesting_Data));
end Finalize;
The_Cleaner : Cleaner;
begin
Ada.Text_IO.Put_Line ("Main Procedure.");
The_Cleaner.Some_Interesting_Data := 42;
Ada.Text_IO.Put_Line ("Finished.");
end Main;
不錯!我沒有想到這一點。這一個將立即進入我的小聰明的想法書。謝謝。 – 2011-05-19 07:18:50
我不認爲調用Finalize的順序是指定的,所以如果您使用多個Controlled對象,則不應該依賴該順序。 – oenone 2011-05-19 10:51:45
+1這也是我的第一個想法。我有興趣知道Finalization代碼是否在進程被其他進程終止時運行(例如:Unix'kill -9')。 – 2011-05-19 13:17:58
您可以raise an exception,它可以是一個defined by the language或一個defined in your program。然後你的exception handler就會執行。
您也可以使用Ada.Command_Line.Set_Exit_Status
將代碼返回到調用環境。
附錄:您也可以處理外部interrupts,如here所示。
如果它是由用戶或者因爲程序簡單地做了做它發起受控關機,那麼你可以簡單地最後添加調用清除過程。
如果程序因中斷信號而終止,例如發送SIGINT信號的用戶或系統關閉,那麼您可以捕獲這些信號並將清理過程置於註冊的回調中。
我寫了一個關於如何使用Ada捕獲中斷的簡短示例。它可在github和wiki article。
另一種選擇是使用來自libre.adacore.com的Florist POSIX包。也許在posix信號包中有一些用處。
由於一個阿達主程序作爲任務處理,你可以使用Ada.Task_Termination包來管理執行後的清理工作。在Ada 2005 Rationale中有關於此的一篇文章,下面是一個以演示爲例的快速演示。
你必須提供一個庫一級保護終止程序,所以這裏應該是一個包:
with Ada.Task_Termination;
with Ada.Task_Identification;
with Ada.Exceptions;
package Main_Program_Finalization is
protected Shutdown_Handler is
procedure Termination_Finalizer
(Cause : in Ada.Task_Termination.Cause_Of_Termination;
T : in Ada.Task_Identification.Task_Id;
X : in Ada.Exceptions.Exception_Occurrence);
end Shutdown_Handler;
end Main_Program_Finalization;
身體:
with Text_IO; use Text_IO;
package body Main_Program_Finalization is
protected body Shutdown_Handler is
procedure Termination_Finalizer
(Cause : in Ada.Task_Termination.Cause_Of_Termination;
T : in Ada.Task_Identification.Task_Id;
X : in Ada.Exceptions.Exception_Occurrence)
is
use Ada.Task_Termination;
use Ada.Task_Identification;
use Ada.Exceptions;
begin
New_Line;
Put_Line("Shutdown information:");
New_Line;
case Cause is
when Normal =>
Put_Line("Normal, boring termination");
when Abnormal =>
Put_Line("Something nasty happened to task ");
Put_Line(Image(T));
when Unhandled_Exception =>
Put_Line("Unhandled exception occurred in task ");
Put_Line(Image(T));
Put_Line(Exception_Information(X));
end case;
end Termination_Finalizer;
end Shutdown_Handler;
end Main_Program_Finalization;
主程序(它的成立爲正常終止張貼,取消註釋最後兩行並運行它以查看未處理異常觸發終止的效果):
with Main_Program_Finalization;
with Ada.Task_Identification;
with Ada.Task_Termination;
with Text_IO; use Text_IO;
procedure task_term is
use Ada;
Task_ID : Task_Identification.Task_Id
:= Task_Identification.Current_Task;
begin
Put_Line("Main Task ID: " & Task_Identification.Image(Task_ID));
Put_Line("Setting termination finalizer");
Task_Termination.Set_Specific_Handler
(Task_ID,
Main_Program_Finalization.Shutdown_Handler.Termination_Finalizer'Access);
Put_Line("Go off and do things now...");
delay 1.0;
Put_Line("Done with mainline processing, the shutdown handler should now execute");
-- Put_Line("Raise an unhandled exception and see what the shutdown handler does");
-- raise Constraint_Error;
end Task_Term;
我不知道。 JVM通常有一個可用於類似目的的收割線程。 – trashgod 2011-05-19 16:20:39
@trashgod:每當我瀏覽Ada LRM索引的時候,其他一些條目都會引起我的注意。 Task_Termination就是其中之一,因爲導致「部分崩潰」的任務中的未處理異常是我多年前在一個項目中處理的問題,我很高興看到它已被解決。在看到這個問題時,我想起了這個能力,並且研究了在主要計劃任務之後清理是否是一個可行的選擇。它應該是,瞧!所以它是:-) – 2011-05-19 16:43:04
如果允許程序很好地關閉,那麼可以使用標準語言工具(如受控類型)來提供「關閉」行爲。
如果程序不允許由操作系統很好地關閉,那麼沒有語言定義的方式來使用任何語言。你將不得不使用某種操作系統調用來做到這一點。
請注意,您展示的示例不是Java調用,而是JVM調用。 JVM = Java虛擬機...實質上是Java OS。假設您的Ada代碼在JVM上運行,您可以從Ada進行完全相同的調用。如果你在Windows下運行,你必須使用Win32系統調用。你可以製作Ada中的那些,但顯然這些確切的調用在語言中是不可移植的。
優秀的一點。作爲Ada和Java的學生,我學會了對一般的「錯誤同源」(http://en.wikipedia.org/wiki/False_cognate)和特別是語言外特性的警惕。 – trashgod 2011-05-19 16:11:44
@trashgod - 是的。 Ada最大的負擔之一是所有的C編碼器似乎認爲每一次操作系統調用都是「C函數」,Java編碼人員似乎認爲整個JVM都是Java語言的一部分。 – 2011-05-19 17:48:06
您的Java示例僅在JVM關閉時調用,而不是程序本身。 – oenone 2011-05-19 06:47:54