Talk:V4 CA Interfaces

From EPICSWIKI
Revision as of 19:35, 20 May 2005 by JeffHill (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Some comments from Andrew Johnson:

In your presentation about CA V4, you included the method channel::createAllPropertiesReadRequest(). I agree that we need a way to be able to read all of the properties available from the server for a particular PV name, but I want more flexibility than just being able to put that wild-card at the top of my request.

I think we need the ability to be able to subscribe with a property catalog having a specific set of properties at one level but to wild-card a sub-property catalog at some level below. Is this currently possible? If not, please consider this a request to add that capability, which might then remove the need for the seperate createAllPropertiesReadRequest() method. I'm only looking for you to support "*", no pattern matching or regex stuff.

Some comments from Jeff Hill:

During our meeting I raised a question; do we may need a Data Access interface allowing traversal of the structure of the property hierarchy, learning the native type of the properties, but not require instances of the properties?

There may be legitimate situations where the property catalog egg must come before the property catalog chicken. Furthermore, it might be inconvenient from a memory management perspective to require an instance of an array before it is really used. I think that this negative could be perhaps minimized if we state in the CA manual that the array bounds alone will be examined, and the array elements will not be traversed, when scanning a property catalog to learn its structure.

Probably the only negative associated with adding a property catalog structure traverse capability to the interface would be that the application would need to provide one additional function. They are already providing an immutable traverse, a mutable traverse function, and an immutable find function. What is vexing is that in many situations all three of the traverse functions are nearly identical. Personally, I don’t like to see common code managed with cut and paste. I am even less fond of that eventuality should it be repeated for many, many data structures in a proliferation of applications.

So I had a look at what level of Data Access library support might be provided so that they need write the guts of the traverse function only once. The following is an example of how they might structure their application. There are still three traverse functions because cross library binding requires the virtual base class interfaced technique, but now they can use a template to implement the traversing only once.

This level of complication appears to be reasonable for end user applications.


PropertyId propertyX;
PropertyId propertyY;
PropertyId propertyZ;
PropertyId propertyI;

class MyContainer : private PropertyCatalog {
public:

private:
    int x;
    float y;
    double z;
    char i;
    static void traverse ( 
        PropertyDescriptionViewer & );
    void traverse ( 
        PropertyManipulator & );
    void traverse ( 
        PropertyViewer & ) const;
    bool find ( 
        const PropertyId & id, PropertyViewer & ) const;
    template < class REFERENCE, class MANIPULATOR >
    static void traverseTempl ( 
        const REFERENCE &, MANIPULATOR & );
};

template < class REFERENCE, class MANIPULATOR >
inline void MyContainer::traverseTempl ( 
    const REFERENCE & ref, MANIPULATOR & manipulator )
{
    ref.reveal ( 
        manipulator, propertyX, & MyContainer::x );
    ref.reveal ( 
        manipulator, propertyY, & MyContainer::y );
    ref.reveal ( 
        manipulator, propertyZ, & MyContainer::z );
    ref.reveal ( 
        manipulator, propertyI, & MyContainer::i );
}

void MyContainer::traverse ( 
    PropertyManipulator & manipulator ) 
{
    MyContainer::traverseTempl ( 
        reference < MyContainer > ( *this ), manipulator );
}

void MyContainer::traverse ( 
    PropertyViewer & viewer ) const 
{
    MyContainer::traverseTempl ( 
        reference < const MyContainer > ( *this ), viewer );
}

void MyContainer::traverse ( 
    PropertyDescriptionViewer & viewer )
{
    MyContainer::traverseTempl ( reference < void > (), viewer );
}
    
bool MyContainer::find ( 
    const PropertyId & id, 
    PropertyManipulator < Property > & manipulator ) const 
{
    bool status = false;
    if ( id == propertyX ) {
    	manipulator.reveal ( 
    	    Property < const int > ( propertyX, this->x ) );
        status = true;
    }
    else ( id == propertyY ) {
    	manipulator.reveal ( 
    	    Property < const int > ( propertyY, this->y ) );
        status = true;
    }
    return status;
}