Files
Clifford Yapp 99855789c2 Precompute late-bound entity attribute layouts
Resolve each flattened inherited attribute layout once after schema
initialization.  Late-bound instance construction now follows descriptor
and index records directly instead of recursively traversing supertypes
and repeating derived and redefined attribute name searches.

Keep the cache outside EntityDescriptor so its object layout and API v1
ABI remain unchanged.  Invalidate cached subtype layouts when descriptor
graphs are edited, and retain lazy preparation for non-module callers.

For the AP242e4 sample's most common entity, constructing 1,531,000
DIRECTION instances improved from 0.84s to 0.63s (-25.0%); user time
improved from 0.82s to 0.61s (-25.6%).  Peak RSS increased by 0.9% and
libstepcore grew by 1.6%.  Twenty full read/write runs remained at 4.9s.

The real file still created and validated 10,609 instances with zero
errors and warnings.  Its 949,685-byte rewrite changed only by its
timestamp.
2026-08-02 06:15:25 -04:00

178 lines
5.5 KiB
C++

#ifndef ENTITYDESCRIPTOR_H
#define ENTITYDESCRIPTOR_H
#include "typeDescriptor.h"
#include "clstepcore/attrDescriptor.h"
#include "uniquenessRule.h"
#include "clstepcore/attrDescriptorList.h"
#include "inverseAttributeList.h"
#include "sc_export.h"
typedef SDAI_Application_instance * ( * Creator )();
class Registry;
/** EntityDescriptor
*
* An instance of this class will be generated for each entity type
* found in the schema. This should probably be derived from the
* CreatorEntry class (see sdaiApplicaton_instance.h). Then the binary tree
* that the current software builds up containing the entities in the schema
* will be building the same thing but using the new schema info.
* nodes (i.e. EntityDesc nodes) for each entity.
*/
class SC_CORE_EXPORT EntityDescriptor : public TypeDescriptor {
private:
void InvalidateLateBoundLayout() const;
protected:
SDAI_LOGICAL _abstractEntity;
SDAI_LOGICAL _extMapping; /**< does external mapping have to be used to create an instance of us? (see STEP Part 21, sect 11.2.5.1) */
EntityDescriptorList _subtypes; // OPTIONAL
EntityDescriptorList _supertypes; // OPTIONAL
AttrDescriptorList _explicitAttr; // OPTIONAL
Inverse_attributeList _inverseAttr; // OPTIONAL
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable: 4251 )
#endif
std::string _supertype_stmt;
#ifdef _MSC_VER
#pragma warning( pop )
#endif
public:
Uniqueness_rule__set_var _uniqueness_rules; // initially a null pointer
// pointer to a function that will create a new instance of a SDAI_Application_instance
Creator NewSTEPentity;
EntityDescriptor( );
EntityDescriptor( const char * name, // i.e. char *
Schema * origSchema,
Logical abstractEntity, // i.e. F U or T
Logical extMapping,
Creator f = 0
);
virtual ~EntityDescriptor();
/** Create an instance of this entity.
*
* Uses the generated early-bound creator when one is installed and
* otherwise constructs a descriptor-backed late-bound instance.
*/
SDAI_Application_instance * CreateEntity() const;
/** Resolve the inherited attribute layout used by late-bound
* instances.
*
* SchemaModule calls this once after descriptor initialization.
* CreateEntity also calls it as a fallback for independently built
* descriptor graphs.
*/
void PrepareLateBoundLayout() const;
void InitIAttrs( Registry & reg, const char * schNm );
const char * GenerateExpress( std::string & buf ) const;
const char * QualifiedName( std::string & s ) const;
const SDAI_LOGICAL & AbstractEntity() const {
return _abstractEntity;
}
const SDAI_LOGICAL & ExtMapping() const {
return _extMapping;
}
void AbstractEntity( SDAI_LOGICAL & ae ) {
_abstractEntity.put( ae.asInt() );
}
void ExtMapping( SDAI_LOGICAL & em ) {
_extMapping.put( em.asInt() );
}
void AbstractEntity( Logical ae ) {
_abstractEntity.put( ae );
}
void ExtMapping( Logical em ) {
_extMapping.put( em );
}
void ExtMapping( const char * em ) {
_extMapping.put( em );
}
const EntityDescriptorList & Subtypes() const {
return _subtypes;
}
const EntityDescriptorList & Supertypes() const {
return _supertypes;
}
const EntityDescriptorList & GetSupertypes() const {
return _supertypes;
}
const AttrDescriptorList & ExplicitAttr() const {
return _explicitAttr;
}
const Inverse_attributeList & InverseAttr() const {
return _inverseAttr;
}
virtual const EntityDescriptor * IsA( const EntityDescriptor * ) const;
virtual const TypeDescriptor * IsA( const TypeDescriptor * td ) const;
virtual const TypeDescriptor * IsA( const char * n ) const {
return TypeDescriptor::IsA( n );
}
virtual const TypeDescriptor * CanBe( const TypeDescriptor * o ) const {
return o -> IsA( this );
}
virtual const TypeDescriptor * CanBe( const char * n ) const {
return TypeDescriptor::CanBe( n );
}
// The following will be used by schema initialization functions
void AddSubtype( EntityDescriptor * ed ) {
_subtypes.AddNode( ed );
}
void AddSupertype_Stmt( const std::string & s ) {
_supertype_stmt = s;
}
const char * Supertype_Stmt() {
return _supertype_stmt.c_str();
}
std::string & supertype_stmt_() {
return _supertype_stmt;
}
void AddSupertype( EntityDescriptor * ed ) {
InvalidateLateBoundLayout();
_supertypes.AddNode( ed );
}
void AddExplicitAttr( AttrDescriptor * ad ) {
InvalidateLateBoundLayout();
_explicitAttr.AddNode( ad );
}
void AddInverseAttr( Inverse_attribute * ia ) {
_inverseAttr.AddNode( ia );
}
void uniqueness_rules_( Uniqueness_rule__set * urs ) {
_uniqueness_rules = urs;
}
Uniqueness_rule__set_var & uniqueness_rules_() {
return _uniqueness_rules;
}
};
#endif //ENTITYDESCRIPTOR_H