OpenAccess Observers


Topics:

Overview

An application can use OpenAccess observers to receive notification whenever certain changes occur to the state and contents of open databases. Observers notify applications of changes to a particular class of objects. For example, the oaShape observer sends notifications if a shape is created, modified, or destroyed. A complex application can use observers to ensure that its internal state is consistent with changes made by other code in the same process.

The oaObserver class is an abstract class template used as the base class for observers in OpenAccess. OpenAccess defines which classes can have observers. Observers are allowed at the level of the managed class hierarchy that maps to the most common needs of applications. For example, there is an observer for oaNet, but not for oaBitNet, oaBundleNet, or oaBusNet.

Working with Observers

To use an observer, an application must do the following:

See the Observer<oaLibDefList> Code Example for a simple declaration and implementation of a user observer class derived from the oaObserver<oaLibDefList> template specialization.

Enabling Observers and Setting Priorities

Observers can be enabled or disabled. This can be done either during construction (see oaObserver::oaObserver) or by calling the observer's enable function). Disabled observers are not called. The enabled status of an observer can be checked by calling isEnabled.

Observers are ordered by priority. Observers with higher priority (which means those with lower priority numbers) are called first. The priority of each observer is established during construction of the observer (see oaObserver::oaObserver ).

Observer Notifications

There are two general types of observers in OpenAccess, standard observers and special observers.

Standard Observer Notifications

Standard observers, which are derived from oaStdObserver, notify applications when objects are created, modified, or destroyed. The standard observers have the following interface:

virtual void 
onPostCreate (T *object)
virtual void 
onPreDestroy (T *object)
virtual void 
onPreModify (T *object, D modType)
virtual void 
onPostModify (T *object, D modType)
Where:
object  Pointer to the observed object
modType  Type of modification made to the observed object

Most standard observers have onPreModify and onPostModify event notification functions that pass a modTypeEnum denoting the type of modification. For these standard observers, the modType Enum column of the OpenAccess Observer Table lists the name of the modTypeEnum whose values are passed to the onPreModify and onPostModify functions. For all other observers (those with "N/A" in the right column), the onPreModify and onPostModify functions are not implemented.

Special Observer Notifications

Special observers provide unique notification functions for particular OpenAccess objects. For example, the oaObserver<oaLibDefList> special observer provides the following notification functions:

virtual oaBoolean 	oaObserver<oaLibDefList>::onPreOpenLibs(oaLibDefList    *defList)
virtual void            oaObserver<oaLibDefList>::onPostOpenLibs(oaLibDefList   *defList)
virtual oaBoolean 	oaObserver<oaLibDefList>::onLoadWarnings(oaLibDefList                 *defList,
                                                                 const oaString                &msg,
                                                                 oaLibDefListWarningTypeEnum   type)
																   

The special observers are as follows:

Some special observers have onPreModify and onPostModify event notification functions that pass a modTypeEnum value denoting the type of modification. For these special observers, the modType Enum column of the OpenAccess Observer Table lists the name of the modTypeEnum whose values are passed to the onPreModify and onPostModify functions. For all other observers (those with an "N/A" in the right column), the onPreModify and onPostModify functions are not implemented.

Special observers can report on a variety of events or circumstances. Some special observers provide notifications when there is conflicting data. For example, oaObserver<oaConstraintGroupDef>::onConflict issues a notification when an on-disk oaConstraintGroupDef conflicts with an existing oaConstraintGroupDef definition. There are also special observer notifications for conflicting objects or attribute values across a graph of incremental technology databases, for example, the oaObserver<oaTech>::onClearanceMeasureConflict observer. There are also special observers that report when there is a change to the state of a database, and special observers that report on binding issues.

Observer Notification Sequence

A single action in the API can trigger a number of observer notifications on multiple objects. For example, when an oaNet is deleted, any oaTerms connected to the net are automatically deleted. The net is also disconnected from any oaInstTerms. Each of these events can trigger observer notifications.

To better understand the sequencing of observer notifications, it's useful to understand the two types of relationships between objects in the database:

The sequence of events that occur during the destruction of a managed object are the opposite of the sequence of events that occurred when the application created and built-up the object. The destruction sequence for a managed object first removes all the association relationships between objects, then destroys all the dependent objects. Observers are issued as follows:

To handle circular relationships between objects, OpenAccess must first remove the relationship between any dependent object and association objects, then remove all association relationships between the originating object and other objects. This makes it possible to handle the destruction of dependent objects in order. For example, consider the relationship of an oaNet to other connection objects in the database.

Scoped Observer Notifications

A single, high level OpenAccess function call can map to a state change that includes multiple lower level state changes (or side effects). Such changes are known as hierarchical state changes. Applications that need to understand which changes are side effects of other changes can use the onBeginCreate, onEndCreate, onBeginDestroy, and onEndDestroy observer notifications. These notifications are referred to as scoped because they span the entire range of the create() and destroy() function calls.

Consider an oaNet::destroy operation. This operation has several side effects:

The onBeginDestroy scoped observer marks the beginning of the set of scoped changes. Note that the onBeginDestroy observer notification is an object without a valid handle. Applications monitor the standard observers that occur within the set of scoped changes (between the onBeginDestroy and onEndDestroy, for example). The order of the sequence of standard observer notifications within a set of scoped changes must be maintained.

The onBeginCreate and onEndDestroy notifications are unique. They pass in a pointer to the object that owns the object for which the notifications are being sent. The owners for the OpenAccess objects (for which scoped observer notifications are available) are as follows.

OpenAccess Object Owning Object Package Notes
oaAnalysisLib oaTech oaTech
oaAnalysisOpPoint oaAnalysisPoint oaDesign
oaAnalysisPoint oaDesign oaDesign
oaAppObject oaObject (database) oaBase
oaAssignment oaInst oaDesign
oaBlock oaDesign oaDesign
oaBlockage oaBlockObject oaDesign
oaBoundary oaBlock oaDesign
oaBusNetDef oaBlock oaDesign
oaBusTermDef oaBlock oaDesign
oaCell oaLib oaDM
oaCellView oaLib oaDM
oaCluster oaBlock oaDesign
oaCMap oaBlock oaDesign onBeginCreate only
oaConnectDef oaBlockObject (oaTerm/oaNet) oaDesign
oaConstraint oaObject (database) oaBase
oaConstraintDef oaSession oaBase
oaConstraintGroup oaObject (owner/database) oaBase
oaConstraintGroupDef oaSession oaBase
oaConstraintGroupMem oaConstraintGroup oaBase
oaConstraintParam oaObject (database) oaBase
oaConstraintParamDef oaSession oaBase
oaDerivedLayerDef oaSession oaTech
oaDerivedLayerParam oaTech oaTech
oaDerivedLayerParamDef oaSession oaTech
oaDesignInst oaReticle/oaFrame oaWafer
oaDevice oaParasiticNetwork oaDesign
oaDMFile oaLib oaDM
oaElmore oaReducedModel oaDesign
oaFigGroup oaBlock oaDesign
oaFigGroupMem oaFigGroup oaDesign
oaFrame oaWafer oaWafer
oaFrameInst oaReticle/oaFrame oaWafer
oaGCellPattern oaBlock oaDesign
oaGroup oaObject (database) oaBase
oaGroupDef oaSession oaBase
oaGroupMember oaGroup oaBase
oaGuide oaBlock oaDesign
oaImage oaReticle/oaReticleRef oaWafer
oaInst oaBlock oaDesign
oaInstHeader oaBlock oaDesign
oaInstTerm oaInst oaDesign
oaLayer oaTech oaTech
oaLayerHeader oaBlock oaDesign
oaLibDefList oaSession oaDM
oaLibDefListMem oaSession oaDM
oaLPPHeader oaBlock oaDesign
oaMarker oaBlock oaDesign
oaNet oaBlock oaDesign
oaNode oaParasiticNetwork oaDesign
oaOpPoint oaAnalysisLib oaTech
oaOpPointHeader oaDesign oaDesign
oaParasiticNetwork oaDesign oaDesign
oaPin oaTerm oaDesign
oaPoleResidue oaReducedModel oaDesign
oaProp oaObject (owner) oaBase
oaPurpose oaTech oaTech
oaReducedModel oaAnalysisPoint oaDesign
oaReticle oaWafer oaWafer
oaRoute oaBlock oaDesign
oaRow oaBlock oaDesign
oaScanChain oaBlock oaDesign
oaScanChainInst oaScanChainSet oaDesign
oaScanChainSet oaScanChain oaDesign
oaShape oaBlock oaDesign
oaSiteDef oaTech oaTech
oaSteiner oaBlock oaDesign
oaStepperMap oaWaferDesc oaWafer
oaSubNetwork oaParasiticNetwork oaDesign
oaTechHeader oaTech oaTech
oaTechLayerHeader oaTech oaTech
oaTechViaDefHeader oaTech oaTech
oaTerm oaNet oaDesign
oaTrackPattern oaBlock oaDesign
oaValue oaObject (database) oaBase
oaVectorInstDef oaBlock oaDesign
oaVia oaBlock oaDesign
oaViaDef oaTech oaTech
oaViaHeader oaBlock oaDesign
oaViaSpec oaTech oaTech
oaViaVariant oaDesign/oaTech oaTech
oaViaVariantHeader oaDesign/oaTech oaTech
oaView oaLib oaDM
oaViewType oaSession oaDM onBeginCreate only
oaWaferDesc oaWafer oaWafer
oaWaferFeature oaWaferDesc oaWafer

To access the scoped observer notifications, derive your observer class from the oaObserver<T, oaRevisionTraits <T> ::scopedObserverRevision> class, for example:

       class myRouteObserver : public oaVersionedObserver<oaRoute, oaRevisionTraits<oaRoute>::scopedObserverRevision> >
       {
                           myRouteObserver(oaUInt4 priorityIn);
                           ~myRouteObserver(); 

              virtual void  onBeginCreate(oaObject *owner, oaUInt4 scopeID);
              virtual void  onEndCreate(oaRoute *object, oaUInt4 scopeID);
              virtual void  onBeginDestroy(oaRoute *object, oaUInt4 scopeID);
              virtual void  oaEndDestroy(oaObject      *owner, oaUInt4 scopeID);
       };

Then redefine the onBeginCreate, onEndCreate, onBeginDestroy, and onEndDestroy virtual functions to suit your needs. Note that you continue to have access to all the default observer notifications.

oaLibDefList Observer Example

Below is a class declaration for an observer class derived from oaObserver<oaLibDefList> followed by the implementation for the derived observer's constructor and it onLoadWarnings notification function. The constructor passes the derived observer's priority and enabled settings to the parent's constructor. The onLoadWarnings notification function sends any received warning messages to cout.

This technique of declaring and implementing a user observer class that is derived from a specialized oaObserver template (in this example, derived from oaObserver<oaLibdefList>) is the typical approach for deriving and using OpenAccess observers in applications. Refer to the Observer<oaClassName> column of the OpenAccess Observer Table for a complete list of specialized oaObserver templates that can be used in this fashion.

class myLibDefListObserver : public oaObserver<oaLibDefList> {
public:
    myLibDefListObserver(oaUInt4      priorityIn, 
                         oaBoolean    enabledIn = true); 
    oaBoolean onLoadWarnings(oaLibDefList                   *obj,
                             const oaString                 &msg,
                             oaLibDefListWarningTypeEnum    type);
};

myLibDefListObserver::myLibDefListObserver(oaUInt4       priorityIn, 
                                           oaBoolean     enabledIn)
										   
:	oaObserver<oaLibDefList>(priorityIn, enabledIn)            // The constructor passes the                     
{                                                                  // priority and enabled status.
}
oaBoolean
myLibDefListObserver::onLoadWarnings(oaLibDefList                   *obj,              // The onLoadWarnings function
                                     const oaString                 &msg,              // sends messages to cout.
                                     oaLibDefListWarningTypeEnum    type)
{
     if (!obj) {
        cout << "Error trying to open default libs.def file: " << msg << endl;
     } else {
        oaString libDefPath;
        obj->getPath(libDefPath);
        switch(type) {
            case oacSyntaxErrorLibDefListWarning:
                cout << "Syntax error in " << libDefPath << ": " << msg << endl;
                break;
            default:
                cout << libDefPath <<  " load warning: " << msg << endl;
                break;
        }
    }
    return true;
}

Related Documentation

Return to top of page

Return to Programmers Guide topics



Copyright © 2001-2010 Cadence Design Systems, Inc.
All rights reserved.