2024年6月12日发(作者:)

(19)中华人民共和国国家知识产权局

(12)发明专利说明书

(21)申请号 CN2.0

(22)申请日 2006.12.25

(71)申请人 上海科泰世纪科技有限公司

地址 201203 上海市浦东新区郭守敬路498号17号楼2层

(72)发明人 陈榕 梁宇洲 杨洋

(74)专利代理机构 上海浦一知识产权代理有限公司

代理人 顾继光

(51)

G06F9/46

权利要求说明书 说明书 幅图

(10)申请公布号 CN 101211273 A

(43)申请公布日 2008.07.02

(54)发明名称

在构件编程中自动生成Singleton模

式的方法

(57)摘要

本发明公开了一种在构件编程中自

动生成Singleton模式的方法,包括以下步

骤:定义一个全局对象变量、一个全局状

态值及一个全局锁;对状态值加锁;对全

局状态值进行检测判断,当全局状态值为

未初始化时,对对象初始化,并相应地设

置全局状态值为正在初始化;当全局状态

值为正在初始化时,表明已有其他线程进

行对象的初始化,此时该线程将会进入等

待状态,并且通过全局状态值不断检测正

在分配对象的线程的状况;当全局状态值

为已初始化时,获得全局对象变量的值;

全局状态值解锁并返回对象的值。本发明

直接声明全局变量并进行初始化,同时对

其进行多线程同步管理,当编译相应car

文件后自动生成相关Singleton模式实现代

码,降低用户编程复杂程度。

法律状态

法律状态公告日

法律状态信息

法律状态

权 利 要 求 说 明 书

1.一种在构件编程中自动生成Singleton模式的方法,其特征是,包括以下步骤:

步骤一,定义一个全局对象变量,并定义一个全局状态值,同时定义一个全局锁;

步骤二,对全局状态值加锁;

步骤三,对全局状态值进行检测判断,当全局状态值为未初始化时,对对象进行初

始化工作,并相应地设置全局状态值为正在初始化;当全局状态值为正在初始化时,

表明已经有其他的线程进行对象的初始化工作,此时该线程将会进入等待状态,并

且通过全局状态值不断检测正在分配对象的线程的状况;当全局状态值为已初始化

时,获得全局对象变量的值;

步骤四,全局状态值解锁并返回对象的值。

2.根据权利要求1所述的在构件编程中自动生成Singleton模式的方法,其特征是,

当全局状态值为未初始化时,按照如下步骤完成所述的对对象的状态值进行设置:

步骤1,将全局状态值设置为正在初始化;

步骤2,对状态值解锁;

步骤3,在堆中分配新的构件对象,并将其引用计数加1;

步骤4,判断分配是否成功,当分配不成功时,将全局状态值设为未初始化并返回;

当分配成功时,调用对象的初始化元件方法进行设置并执行下述步骤5;

步骤5,判断设置是否成功,当设置成功时,将对象的状态值设为已初始化并返回;

当设置不成功时,将所述全局状态值设为未初始化并返回。

3.根据权利要求1所述的在构件编程中自动生成Singleton模式的方法,其特征是,

当所述全局状态值为正在初始化时,按如下步骤完成所述的检测其他线程分配对象

的状况:

步骤A,对全局状态值解锁;

步骤B,切换到其他线程;

步骤C,对全局状态值加锁;

步骤D,判断其他线程是否分配对象失败,当其他线程分配对象失败时,全局状态

值解锁并返回所述步骤二重新执行对象初始化工作;当其他线程分配对象成功时,

执行下述步骤E;

步骤E,判断其他线程是否已经完成对象的分配,当其他线程未完成对象的分配时,

跳回步骤A;当其他线程已完成对象的分配时,按所述步骤三获得全局对象变量的

值。

说 明 书

技术领域

本发明涉及一种程序代码的生成方法,特别涉及一种在构件编程中自动生成

Singleton模式的方法。

背景技术

二十世纪八十年代以来,软件编程技术有了很大的发展,其发展可以大致分为以下

几个阶段:

面向对象编程,即通过对软件模块的封装,使其相对独立,从而使复杂的问题简单

化。面向对象编程强调的是对象的封装,但模块(对象)之间的关系在编译的时候已

被固定,模块之间的关系是静态的,这种关系在程序运行时不能改变;也就是说:

在运行时不能换用模块中更小的功能单元。

面向构件编程,即为了使不同软件开发商提供的构件模块(软件对象)可以相互操作

使用,构件之间的连接和调用通过标准的协议来实现。构件化编程模型强调协议标

准,需要提供各厂商都能遵守的协议体系。就像公制螺丝的标准一样,所有符合标

准的螺丝和螺母都可以相互装配。构件化编程模型建立在面向对象技术的基础之上,

是完全面向对象的,提供了动态构造部件模块(在运行中可以构造部件)的机制。构

件在运行时可以动态装入,是可以更换的。但是,现有的面向构件编程技术要求用

户自行定义构件的非自描述接口,使得用户程序的开发依然繁复。

CAR(Component Assembly Runtime)构件技术是一种面向构件编程技术,它定义了

一套网络编程时代的构件编程模型和编程规范,它规定了一组构件间相互调用的标

准,使得二进制构件能够自描述,能够在运行时动态链接。CAR与微软的COM相

比,删除了COM中过时的约定,禁止用户定义COM的非自描述接口;完备了构

件及其接口的自描述功能,并且对用户界面进行了简化包装,易学易用。在一种嵌

入式操作系统上,CAR构件技术由CAR语言(构件描述语言,描述构件的元数据

信息)、CAR编译器、自动代码生成工具以及CAR构件基础库支持。CAR构件技

术体现了网络编程时代的特性,编程界面简单。

在嵌入式操作系统软件开发工具包(SDK)的支持下,CAR技术使得原来高深难懂的

构件编程技术很容易被C/C++程序员理解并掌握。用户只需要用脚本语言设计相关

类和接口的关系以及其属性,并存为.car文件,通过CAR编译器的处理就可以自

动生成相关的代码。

单例模式(Singleton模式)属于设计模式中的一种方法,它的目的是保证一个类仅有

一个实例,并提供一个能够访问它的全局访问点。这种模式在实际开发中的应用也

非常多,例如在嵌入式图形系统应用中,由于内存资源比较宝贵,很多模块都必须

保证在整个过程中只能有一个实例。在实际编程设计中,如果要运用该模式,用户

可以设计一个Singleton的基类,然后在其子类实例中进行各种扩展来配置应用,

也可以直接设计一个不允许继承的Singleton类,里面包含了相关功能。无论采取

哪种方法,用户都必须自行实现Singleton模式的相关代码。如果能找到一种在

CAR构件编程中自动生成singleton模式代码的方法,将大大降低用户编程的复杂

程度。

考虑一个银行帐户管理系统,其中有上百万个客户帐号,要访问每一个客户的帐号,

需要对客户的权限进行验证。在这样的系统里,可以设计一个Singleton类叫做

AccountManager,用来管理系统中的客户帐户,此类的实例在整个系统中只有一个,

如果用C#实现的话,在多线程环境下,可以采用以下方法:

public sealed class AccountManager

{

这个类的其他功能实现代码......

以下是singleton模式的实现代码:

static AccountManager instance_=null;

static readonly object lock_=new Object();

private AccountManager()

{

}

public static AccountManager Instance

{

get

{

lock(lock_)

{

if(instance_==null)

{

instance_=new AccountManager();

}

return instance_;

}

}

}

}

以上是Singleton模式在C#中的基本实现,AccountManager类被设计成不可继承,

当其静态成员变量instance_为空时才在堆中进行类的初始化,其他情况下直接返

回该类的实例instance_的值,这样就保证了系统内始终只有一个该类的实例,整

个过程通过加锁保证多线程下的一致性。可以看到,不同的用户和不同的语言对于

Singleton模式的实现可能不相同,但是都必须自己进行Singleton类的编写,这样

用户在实现类的功能的同时,还必须花精力去实现singleton模式的相关代码,这

给用户的编程带来一定的复杂度。

发明内容

本发明的主要目的在于提供一种在构件编程中自动生成Singleton模式的方法,当

编译相应car文件后就可自动生成实现此类Singleton的相关代码,而用户只需要关

注此构件基本功能的实现,大大降低了用户编程的负担。

为解决上述技术问题,本发明在构件编程中自动生成Singleton模式的方法,基于

CAR构件编程,包括以下步骤:步骤一,定义一个全局对象变量,并定义一个全

局状态值,同时定义一个全局锁;步骤二,对状态值加锁;步骤三,对全局状态值

进行检测判断,对对象进行初始化工作,并相应地设置全局状态值为正在初始化;

当全局状态值为正在初始化时,表明已经有其他的线程进行对象的初始化工作,此

时该线程将会进入等待状态,并且通过全局状态值不断检测正在分配对象的线程的

状况;当全局状态值为已初始化时,获得全局对象变量的值;步骤四,返回对象的

值。

本发明所提供的方法中,singleton的实现并非像java或者.Net通过继承一个

singleton基类来获得相应属性,而是直接声明为全局变量并进行初始化,同时对其

进行多线程同步管理,保证此全局变量只有一个实例,当编译相应car文件后就可

自动生成实现此类Singleton,大大降低了用户编程复杂程度。

附图说明

图1是本发明的流程图;

图2是图1中全局状态值为未初始化时的分支流程图;

图3是图1中全局状态值为正在初始化时的分支流程图;

图4图1中全局状态值为已初始化时的分支流程图。

具体实施方式

下面结合附图对本发明作进一步详细的说明。

按照本发明提供的方法,在CAR构件编程中,singleton模式的实现并非像上述

java或者.Net通过继承一个singleton基类来获得相应属性,而是直接声明为全局变

量并进行初始化,同时对其进行多线程同步管理,保证此全局变量只有一个实例。

当用户在.car文件中指定一个类为singleton属性并编译此.car文件后,CAR编译器

会自动生成相关的处理代码,其处理过程如下:首先会声明几个相关的全局变量,

除了有对应此对象的全局指针之外,还有一个状态值代表此对象当前的状态,以及

一个全局锁进行同步。状态值分为三种:_SingletonObjState_Uninitialize,代表此

对象尚未初始化;_SingletonObjState_Initializing,代表此对象正在进行初始化;

_SingletonObjState_Initialized,代表此对象之前已初始化。

用户在判断以上三种状态值并进行相应的处理之前,首先会执行加锁的动作,因为

状态值为全局变量,对其进行设置時必须要加锁以保证多线程下不会出现读写冲突。

然后用户会根据当前不同的状态值进入相应的程序分支,如图1所示。

当对象状态为_SingletonObjState_Uninitialize時,表明对象还没有被别的线程初始

化过,此时将进行初始化的工作,其过程为首先将对象的全局状态值设为

_SingletonObjState_Initializing,表明当前对象正在进行初始化,由于进入分支之前

已经加锁,所以当此状态值设置完毕后可以进行解锁,让其他线程也可以读写此状

态值。接着在堆中分配一个新的car构件对象,并将此对象的引用计数加1(这个过

程中如果分配失败,就会重新将对象状态设为_SingletonObjState_Uninitialize并返

回,让其他线程进行初始化),然后调用该对象的_InitializeComponent()函数进行一

些设置(这个过程如果失败,同样也会将对象状态设为

_SingletonObjState_Uninitialize并返回),最后在返回前才将对象的状态值设为

_SingletonObjState_Initialized,表明此构件对象已经被当前线程初始化完毕。上述

过程如图2所示。

当对象状态为_SingletonObjState_Initializing時,则表明其他线程正在对此构件对象

进行初始化,由于进入分支前已经加锁,此时可以解锁并切换至其他线程继续进行

处理,然后重新加锁判断全局状态值,如果状态值为

_SingletonObjState_Uninitialize,则表示其他线程可能初始化失败,此时解锁并返

回过程开始处由本线程重新进行初始化;如果状态值仍然是

_SingletonObjState_Initializing,则表明其他线程还没有把对象初始化完毕,此时应

该返回到本分支开始处重新开始解锁以及唤醒其他线程再加锁判断状态值这些步骤,

直到检测到对象状态值为_SingletonObjState_Initialized为止,此时退出此分支进入

_SingletonObjState_Initialized分支。上述过程如图3所示。

当对象状态为_SingletonObjState_Initialized時,表明此时对象的实例已经被其他线

程初始化过了,此时直接将对象的引用计数加1,并返回全局对象的相应值,最后

解锁并返回。上述流程如图4所示。

下面通过一个实施例来说明本发明的技术效果。仍以前述银行帐户管理系统作为例

子,对于AccountManager类,可以在.car文件中这样指定:

module

{

interface IAccountManager{

enter();

}

[singleton]//指定该类为singleton类

class CAccountManager{

interface IAccountManager;

}

}

CAR语言中的module描述表示一个构件模块,让带有singleton属性的

CAccountManager类实现了IAccountManager接口,为了简单起见,

IAccountManager接口中只包含了一个enter()方法。

使用CAR的编译器以及CAR构件的自动代码生成工具对该car文件进行处理就会

生成构件的实现,CAR工具会生成CAccountManager接口函数的空的实现,而用

户只需关心自己定义的接口函数的实现,只要填入自己的代码就可以了。

下面是生成的cpp文件和h文件:

:

#include<stdio.h>

#include″CAccountManager.h″

#include″_″

ECODE CAccountManager::enter()

{

m_cCount++;

printf(″CAccountManager enter %d times.n″,m_cCount);

return NOERROR;

}

其中,是CAR工具生成的有关构件对象底层实现的代码。

可以看到,在enter方法中,设立了一个成员变量m_cCount做为计数,当调用该

方法时就将它的值打印出来,可以通过它可以判断该类是否在全局中只有一个实例。

CAccountManager.h:

#ifndef__CACCOUNTMANAGER_H__

#define__CACCOUNTMANAGER_H__

#include″_CAccountManager.h″

class CAccountManager:public_CAccountManager

{

public:

CARAPI enter();

CAccountManager():m_cCount(0){}

~CAccountManager(){puts(″CAccountManager dtor.″);}

private:

int m_cCount;

};

可以看到成员变量m_cCount在构造函数初始化时会设置成0。

以下是客户端调用此构件方法的一个过程:

#include<stdio.h>

#define_SMARTCLASS

$using ;//引用构件

int main()

{

ECODE ec;

CAccountManagerRef s1,s2;

//初始化两个AccountManager类的实例

ec=tantiate();

if(FAILED(ec))goto ErrorExit;

ec=tantiate();

if(FAILED(ec))goto ErrorExit;

//分别调用两个AccountManager类的enter方法

for(int n=0;n<3;n++){

();

();

}

return 0;

ErrorExit:

printf(″Error,ec=%xn″,ec);

return 1;

}

以下是运行的结果:

CAccountManager enter 1 times.

CAccountManager enter 2 times.

CAccountManager enter 3 times.

CAccountManager enter 4 times.

CAccountManager enter 5 times.

CAccountManager enter 6 times.

CAccountManager dtor.

可以看到,虽然调用的是不同的对象的enter方法,但是最终调用的都是同一方法,

而且最后调用该类析构函数时只调用了一次。

比较一下当没有为AccountManager对象指定singleton属性时的运行结果:

CAccountManager enter 1 times.

CAccountManager enter 1 times.

CAccountManager enter 1 times.

CAccountManager enter 2 times.

CAccountManager enter 1 times.

CAccountManager enter 2 times.

CAccountManager enter 2 times.

CAccountManager enter 3 times.

CAccountManager enter 2 times.

CAccountManager enter 3 times.

CAccountManager enter 3 times.

CAccountManager dtor.

CAccountManager enter 3times.

CAccountManager dtor.

可以看到,没有指定singleton属性时是分别调用了两个不同对象实例的enter方法,

并且最后析构时调用了两次。这个结果是符合预期的。

同时也可看到,在具体的CAccountManager类的实现中,并没有包含任何singleton

模式的管理代码,用户只需要指定CAccountManager类为singleton属性并重新编

译后,相同的实现代码立即有了不同的运行结果。用户通过这种方式,可以很方便

的用singleton模式去解决其他工程问题。