首页 > 其他分享 >AcDbSmartObjectPointer

AcDbSmartObjectPointer

时间:2022-12-23 13:44:12浏览次数:35  
标签:AcDbSmartObjectPointer 对象 ACDB object 打开 CLASS

描述

这个类与AcDbObjectPointer协议兼容,并且增加了在给定对象id时避免访问对象的开放冲突的功能,此外还有长期存在的总是“关闭”对象或至少将其恢复到分配给指针之前的打开状态的功能。

目的是在未来的版本中用AcDbSmartObjectPointer逻辑替换AcDbObjectPointer的实现。AcDbSmartObjectPointer的工作原理是,如果对象的打开状态已经是请求的状态,则根本不打开对象,或者甚至在以所需的方式打开对象之前多次关闭对象。它还以相同的方式处理kForNotify和kForRead,这实际上是kForRead。虽然这并没有使类变得万无一失,但它确实消除了导致无法访问对象的公开冲突。

仍然可能导致无法打开的其他一些条件如下所示,由相关错误指示:

eNotThatKindOfClass  当指定对象id指向非指定类的对象时返回。
ePermanentlyErased  当指定的对象id没有底层对象时返回,无论是由于撤销创建还是删除/删除。
eObjectWasErased  如果对象被擦除且opendeleted标志为false则返回。
eNullObjectId  当输入对象id为空时返回。
eWasNotifying  当指定的对象正在关闭kForWrite模式,正在发送通知并且再次请求kForWrite模式时返回。此时,撤销记录已经完成,所有反应堆都可以看到相同的对象状态。 这种状态的解决方法是记录通知发生,然后等待AcDbObject::objectClosed(AcDbObjectId)回调,此时可以打开对象进行写入。

像AcDbObjectPointer一样,这个模板也可以“获取”非数据库常驻(NDBR)对象和以前打开的对象,它只会关闭一次。如果DBOBJPTR_EXPOSE_PTR_REF选项被启用,那么访问对象指针成员将禁用模板对称关闭或恢复对象的能力。相反,它只关闭一次,调用者随后负责它。

该模板的所有成员都具有与AcDbObjectPointer对应成员相同的描述和语义,只是消除了开放冲突。

调用者会被提醒,当另一个调用者打开一个对象供写时,修改它并不总是好的。但是,如果调用者希望使用该类的实例来获得对它可能已经打开的对象的读或写访问,并且知道交互是安全的,那么强烈建议使用该类。

条件:

使用AcDbSmartObjectPointer的限制本质上是AcDbObjectPointer的限制,并列出如下:

1.与AcDbObjectPointer一样,一旦一个对象被AcDbSmartObjectPointer, ReadableAcDbObject或WritableAcDbObject打开,它不应该直接打开或关闭;相反,应该通过模板协议来管理它们的打开状态。然而,嵌套函数块可以在对象上使用其他形式的open和close,但是由于开放冲突通常会有失败的可能性,除非它使用这些类的实例。

2.使用基于dbobjprt_expose_ptr_ref的成员将取消对象打开状态将被恢复的保证。一旦使用,对象打开状态必须由调用者管理。

3.使用acdbobjectpointer派生的acquire()成员将恢复前一个对象的状态(除非它也是通过acquire()建立的),但新对象的状态将不会被智能管理;假设它将恰好关闭一次。

4.使用acdbobjectpointer派生的release()成员根本不会恢复对象的打开状态;这成为调用者的责任。

说明:

将自动对象访问合并到AcDbObjectPointer协议的一个不幸的副作用是记录类的预期用途的额外复杂性。通过设计,对象访问将严格由实例的构建和销毁决定,并延迟打开和提前关闭。但是AcDbObjectPointer能够切换对象id和对象的附加协议,以及完全跳过对象管理的能力,使得该协议的描述更加复杂和令人困惑。

使用AcDbSmartObjectPointer、ReadableAcDbObject和WritableAcDbObject的基本要求是,当这些类开始访问对象并终止访问时,打开状态不能不同,通常是在构造函数和析构函数中。插入逻辑可以打开对象,只要它也关闭对象。AcDbSmartObjectPointer和/或ReadableAcDbObject和WritableAcDbObject的实例可以任意嵌套,只要嵌套实例以获取对象的相反顺序释放对象。不遵守这一要求将导致程序错误。

只要构造/析构函数或打开/关闭呼吁这些类是专门使用,即访问管理自动化,AcDbSmartObjectPointer的多个实例,ReadableAcDbObject,和WritableAcDbObject指向一个共同的对象id X设计寿命堆积的对象访问,即去年创建实例(或打开一个对象)必须首先摧毁(或者关闭对象或覆盖一个获得()的成员)。当它们在嵌套代码或函数块中声明时,这种情况自然发生;这就是它们的用途。

尽管实例最好通过在堆栈上声明它们来使用,但如果您能够确保生命周期契约,则可以在堆上分配它们。指向不同对象的实例没有这个限制。

析构函数(或close()成员)本质上反转在构造函数中所做的对象打开状态更改。一个例外是,如果一个输入对象已经在事务中为读打开,而调用者希望该对象为写打开,则对象打开状态将在事务中升级为可写,并且当对象指针被销毁时不会降级。相反,交易的关闭或取消本身就完成了工作。当确定对象已经处于所需的打开模式时,模板状态会记住这一点,并且不会进行后续的打开或关闭调用。

如果多个实例以不同的打开模式访问同一个对象,最强大的模式适用于所有指针客户端。例如,如果AcDbSmartObjectPointer的两个实例打开了同一个对象,一个是kForRead,另一个是kForWrite,那么两个指针客户机都有对该对象的写访问权。因为写访问是读访问的超集,所以读取器客户端应该永远不会注意到任何问题。

如果指针实例发现一个对象已经在kForWrite模式下打开,那么对该指针实例的析构函数或关闭调用将不会生成任何通知。只有最后对对象的实际关闭或取消调用才会导致相应的通知回调。

示例

通过对象id或创建一个新实例获得Object Access:

  // The "natural" way to intialize.
    AcDbSmartObjectPointer(AcDbObjectId   objId,
                           AcDb::OpenMode mode,
                           bool openErased = false);

    // Null constructor to be followed by open() or create() call.
    AcDbSmartObjectPointer();
    Acad::ErrorStatus open(AcDbObjectId   objId,
                           AcDb::OpenMode mode,
                           bool openErased = false);
    // Non-database-resident objects are also supported.
    Acad::ErrorStatus create();

验证对象指针是非空的(即访问成功):

  // If you just want a yes or no, then testing the object() pointer
    // against NULL will work.
    if (xxx.object() != 0) { /* the object is valid */ }
    // But for details on why the failure
    // occured, this function works well.
    Acad::ErrorStatus openStatus() const;

通过提供的各种成员访问对象

 // These are really 3 pairs of synonymous access members, with the operator
    // overload member implementations merely returning object().
    const ACDB_CLASS* object() const;
    ACDB_CLASS*       object();
    const ACDB_CLASS* operator->() const;
    ACDB_CLASS*       operator->();
                      operator const ACDB_CLASS*() const;
                      operator ACDB_CLASS*();

 恢复对象访问。

    virtual ~AcDbSmartObjectPointer();

    // In case you can't, or don't want to, wait for the destructor
    Acad::ErrorStatus close();

 举个综合的例子:

void demoFunction(AcDbObjectId id, AcDb:OpenMode mode, bool openErased) {
    // declare the pointer, then use it as an instance of AcDbObject
    AcDbObjectPointer<AcDbEntity> sop(id, mode, true);
    if (eOk == (sop.openStatus())) {
        // Now, object() returns the object associated with id
        // if openStatus() is eOk, then the object() should be non-null
        assert(sop.object() != 0);
        assert(sop->isKindOf(AcDbEntity::desc()));
        // make read/write/notify calls on the object as desired.
    }
    // sop's destructor will revert the object's open status
}

不使用

相比之下,下面是已经在AcDbObjectPointer中发布的成员,但是它们的使用禁用了智能对象访问管理,并且需要调用方提供更多智能来管理对象打开状态。

恢复对一个对象的访问,并假设一个新对象是打开的:

//调用此成员后,获取的对象将为
//在destroy或close()调用时关闭一次。的
//返回或删除或关闭先前的对象
//关于它如何被引入到对象指针。
Acad::ErrorStatus acquire(ACDB_CLASS *& pObjToAcquire);

忘记对象,让调用者处理它:

 

    // pReleasedObj is set by this member, and after return
    // this pointer will no longer remember it.

    Acad::ErrorStatus release(ACDB_CLASS *& pReleasedObj);

DBOBJPTR_EXPOSE_PTR_REF-dependent成员:

//该构造函数和赋值操作符都调用
// acquire()在新对象上
AcDbSmartObjectPointer (ACDB_CLASS * pObject);
运算符= (ACDB_CLASS * pObject);
//使用此方法与调用release()和调用者相同
//可以选择将对象设置为新的值。
操作符ACDB_CLASS* &();

 

 

 

标签:AcDbSmartObjectPointer,对象,ACDB,object,打开,CLASS
From: https://www.cnblogs.com/HRDK-CADeveloper/p/17000500.html

相关文章