ADA程序实例(一个简单的智能指针实现)
2011-11-16 22:28
661 查看
普通的ADA并不含有垃圾收集等托管程序的特性,除非当ADA的目标运行时建立在Java Virtual Machine或.NET系统上。所以从这个对象内存分配角度,ADA和C++基本上是等价的。
ADA提供的语言特性,基本上足以使得ADA能够实现智能指针。当然,是不是有必要在ADA中使用智能指针(考虑ADA常用的思考建模方式),其完善程度(指针的类型,对于OO的支持和对于一般数据的支持)又是另一会儿事。智能指针再智能也不能达到托管程序所能达到内存管理功能(例如简单的引用计数是无法应对孤立环路结构的释放的)。
当然,纯粹展现一下ADA的语言特性,这不失为一个好的例子。
首先是声明(autoptr.ads)。这里显然是一个泛型模块,而其核心类型是指针要处理的对象的类型(private约束是一个很松的约束,尚需查明是不是最松的)。对这个类型可赋予初始化和终止化方法各一。指针实现是指针对象指向一个含引用计数和对象内容的封装对象(Wrapper)。这里比较重要的是封装对象从ada.finalization.controlled继承,这使得能够对其赋值和跨域的状态进行跟踪。其重载函数initialize相当于C++中的无参构造函数,finalize相当于C++中的析构函数,他们分别在对象数据(变量)进域(begin)和出域(end)调用,伴随着变量的诞生和销毁。Adjust比较特殊,也比较关键,它在对象数据被赋值完毕后调用。另外finalize在对象数据被赋值之前也会调用(这个在运行了这个程序才发现)。因为ADA数据赋值永远是针对其直接内容的深拷贝,所以Adjust可用于对收入数据的处理,基本上起到了拷贝构造函数或赋值重载的作用。
spec中提供了一些主要的功能,如所指对象的获取,指针相等的判断的等号重载(根据指针所指对象的一致性而非指针对象本身相同性),以及一个新建空对象的操作。
知道spec的这些要点,就能完成实现(autoptr.adb),这其中在关键步骤上进行了打印。注意Finalize函数中一开始的指针判断,这从Finalize的特点看是必须的(这反映在执行结果中)。
最后是一个演示程序(autoptr_demo.adb),只覆盖了一个简单的创建和赋值,未充分测试。
运行结果(其中wrapper is null说明在赋值前的Finalize调用作用在了未赋值指针上了):
initializing
initialized
initializing
initialized
initializing
initialized
creating
step 1
record{ 1; 'rec2 '} created
step 2
step 3
'create' returning
adjusting
adjusted
finalizing
refcount = 1
finalized
finalizing
wrapper is null
adjusting
adjusted
finalizing
refcount = 1
finalized
reference count of p1 is 1
finalizing
wrapper is null
adjusting
adjusted
reference count of p2 is 2
p2.name = 'rec2 '
finalizing
refcount = 1
finalized
finalizing
refcount = 0
finalized
ADA提供的语言特性,基本上足以使得ADA能够实现智能指针。当然,是不是有必要在ADA中使用智能指针(考虑ADA常用的思考建模方式),其完善程度(指针的类型,对于OO的支持和对于一般数据的支持)又是另一会儿事。智能指针再智能也不能达到托管程序所能达到内存管理功能(例如简单的引用计数是无法应对孤立环路结构的释放的)。
当然,纯粹展现一下ADA的语言特性,这不失为一个好的例子。
首先是声明(autoptr.ads)。这里显然是一个泛型模块,而其核心类型是指针要处理的对象的类型(private约束是一个很松的约束,尚需查明是不是最松的)。对这个类型可赋予初始化和终止化方法各一。指针实现是指针对象指向一个含引用计数和对象内容的封装对象(Wrapper)。这里比较重要的是封装对象从ada.finalization.controlled继承,这使得能够对其赋值和跨域的状态进行跟踪。其重载函数initialize相当于C++中的无参构造函数,finalize相当于C++中的析构函数,他们分别在对象数据(变量)进域(begin)和出域(end)调用,伴随着变量的诞生和销毁。Adjust比较特殊,也比较关键,它在对象数据被赋值完毕后调用。另外finalize在对象数据被赋值之前也会调用(这个在运行了这个程序才发现)。因为ADA数据赋值永远是针对其直接内容的深拷贝,所以Adjust可用于对收入数据的处理,基本上起到了拷贝构造函数或赋值重载的作用。
spec中提供了一些主要的功能,如所指对象的获取,指针相等的判断的等号重载(根据指针所指对象的一致性而非指针对象本身相同性),以及一个新建空对象的操作。
with Ada.Finalization; generic -- type of the target the pointer is dealing with type target_t is private; -- handlers invoked on initialization and finalization respectivelys target_initialize : access procedure(target : in out target_t) := null; target_finalize : access procedure(target : in out target_t) := null; package autoptr is type Pointer is new Ada.Finalization.Controlled with private; -- returns the targeted object pointer 'p' points to function target(p : Pointer) return target_t; -- override of equal sign that returns if two pointers are considered equal -- in which case they are pointing to the same wrapper/target function "="(left, right : Pointer) return boolean; -- creates an new instance of target and returns a pointer that points to it function create return Pointer; -- returns the number of pointers referencing the target pointer p points to function numrefs(p : Pointer) return integer; private -- wrapper that wraps around an instance of target type wrapper_t is tagged record target : target_t; reference_counter : integer; end record; -- type of access to wrapper for pointer to point to wrapper type wrapper_access is access all wrapper_t; -- data definition of pointer type type Pointer is new Ada.Finalization.Controlled with record wrapper : wrapper_access; end record; -- initializer overriding procedure Initialize(p : in out Pointer); -- adjuster that is called after assignment of 'p' overriding procedure Adjust(p : in out Pointer); -- finalizer (destructor) of the pointer type for dealing with referencing overriding procedure Finalize(p : in out Pointer); end autoptr;
知道spec的这些要点,就能完成实现(autoptr.adb),这其中在关键步骤上进行了打印。注意Finalize函数中一开始的指针判断,这从Finalize的特点看是必须的(这反映在执行结果中)。
with Ada.Unchecked_Deallocation; with ada.text_io; use Ada.text_io; package body autoptr is -- instantiate a wrapper deallocation procedure procedure free_wrapper is new Ada.Unchecked_Deallocation (Object=> wrapper_t, Name => wrapper_access); -- returns the targeted object poiner 'p' points to function target(p : Pointer) return target_t is begin -- wrapper is guaranteed to be available -- if not an exception should be thrown by the system for now return p.wrapper.target; end target; -- creates an new instance of target and returns a pointer that points to it function create return Pointer is p : Pointer; begin put_line("creating"); p.wrapper := new wrapper_t; put_line(" step 1"); if target_initialize /= null then target_initialize(p.wrapper.target); end if; put_line(" step 2"); p.wrapper.reference_counter := 1; put_line(" step 3"); put_line("'create' returning"); return p; end create; -- override of equal sign that returns if two pointers are considered equal -- in which case they are pointing to the same wrapper/target function "="(left, right : Pointer) return boolean is begin return left.wrapper = right.wrapper; end "="; -- returns the number of pointers referencing the target pointer p points tos function numrefs(p : Pointer) return integer is begin if p.wrapper = null then return 0; end if; return p.wrapper.reference_counter; end numrefs; -- private methods -- finalizes the target and release the allocation procedure finalize_wrapper(p : in out wrapper_access) is begin if target_finalize /= null then target_finalize(p.target); end if; free_wrapper(p); end finalize_wrapper; -- initializer overriding procedure Initialize(p : in out Pointer) is begin put_line("initializing"); null; -- do nothing; what could be done is instantiate a wrapper put_line("initialized"); end Initialize; -- adjuster that is called after assignment of 'p' overriding procedure Adjust(p : in out Pointer) is begin put_line("adjusting"); p.wrapper.reference_counter := p.wrapper.reference_counter + 1; put_line("adjusted"); end Adjust; overriding procedure Finalize(p : in out Pointer) is begin put_line("finalizing"); if p.wrapper = null then put_line(" wrapper is null"); return; end if; p.wrapper.reference_counter := p.wrapper.reference_counter - 1; put(" refcount = "); put_line(integer'Image(p.wrapper.reference_counter)); -- allowing 'less than' is purely for tolerating erroneous condition if p.wrapper.reference_counter <= 0 then finalize_wrapper(p.wrapper); end if; put_line("finalized"); end Finalize; begin null; end autoptr;
最后是一个演示程序(autoptr_demo.adb),只覆盖了一个简单的创建和赋值,未充分测试。
with Ada.Strings; use Ada.Strings; with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with autoptr; procedure autoptr_demo is type myrec_t is tagged record id : integer; name : string(1..10); end record; id : integer := 1; procedure myrecinit(myrec : in out myrec_t) is begin myrec.id := id; id := id + 1; myrec.name := 10 * ' '; myrec.name := overwrite(myrec.name, 1, "rec"); myrec.name := overwrite(myrec.name, 4, trim(integer'Image(id), Both)); put("record{"); put(integer'Image(myrec.id)); put("; '"); put(myrec.name); put_line("'} created"); end myrecinit; package myptr is new autoptr(target_t => myrec_t, target_initialize => myrecinit'Access); p1, p2 : myptr.Pointer; begin p1 := myptr.create; put("reference count of p1 is "); put_line(integer'Image(p1.numrefs)); p2 := p1; put("reference count of p2 is "); put_line(integer'Image(p2.numrefs)); put("p2.name = '"); put(p2.target.name); put_line("'"); end;
运行结果(其中wrapper is null说明在赋值前的Finalize调用作用在了未赋值指针上了):
initializing
initialized
initializing
initialized
initializing
initialized
creating
step 1
record{ 1; 'rec2 '} created
step 2
step 3
'create' returning
adjusting
adjusted
finalizing
refcount = 1
finalized
finalizing
wrapper is null
adjusting
adjusted
finalizing
refcount = 1
finalized
reference count of p1 is 1
finalizing
wrapper is null
adjusting
adjusted
reference count of p2 is 2
p2.name = 'rec2 '
finalizing
refcount = 1
finalized
finalizing
refcount = 0
finalized
相关文章推荐
- ADA程序实例(一个简单的智能指针实现)
- Java实现一个小说采集程序的简单实例
- 本文实现了一个基于servlet技术的简单的csv文件导出的程序实例。
- VC++实现程序只运行一个实例 最简单办法
- 【Qt5开发及实例】15、实现一个简单的文本编辑器4
- 一个简单的jsp+servlet实例,实现简单的登录
- 利用java实现一个简单的远程监控程序
- 实现一个简单的Spring实例
- C#一个简单下载程序实例(可用于更新)
- Python实现一个简单的验证码程序
- 赛码网,简单计算,用C语言自己实现的一个程序,仅供参考
- C语言实现的一个简单的HTTP程序
- 简单SNMP管理程序的VC++代码实例实现
- 一个简单的Android程序,JNI实现Native C/C++
- 一个简单的jsp+servlet实例,实现简单的登录
- VC 实现程序只运行一个实例,并激活已运行的程序
- 利用HttpModuler实现WEB程序同一时间只让一个用户实例登陆
- 一个能实现超链接的最简单程序
- MFC 程序最小化到系统托盘区的一个简单实例
- 使用进程互斥实现WinForm程序只运行一个实例(VB.Net)