Difference between revisions of "Talk:V4 CA Interfaces"

From EPICSWIKI
Line 1: Line 1:
From Andrew Johnson:
Some comments from Andrew Johnson:


In your presentation about CA V4, you included the method  
In your presentation about CA V4, you included the method  
Line 14: Line 14:
createAllPropertiesReadRequest() method.  I'm only looking for you to  
createAllPropertiesReadRequest() method.  I'm only looking for you to  
support "*", no pattern matching or regex stuff.
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 quite 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 not really right is that all three of the traverse functions are nearly identical. Personally, I don’t like to see common code managed with cut and paste.
So I had a look at what level of Data Access library support might be provided so that they might avoid needing to write three traverse functions. The following is an example of how they might structure their application. This level of complication appears to be reasonable for end user applications.
PropertyId propertyX;
PropertyId propertyY;
class MyContainer :
    private PropertyCatalog {
    int x;
    float y;
    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 >
void MyContainer::traverseTempl (
    const REFERENCE & ref, MANIPULATOR & manipulator )
{
    manipulator.reveal (
        ref.propertyFactory ( propertyX, & MyContainer::x ) );
    manipulator.reveal (
        ref.propertyFactory ( propertyY, & MyContainer::y ) );
}
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;
}
Here is a summary of the changes:
* A new "static void traverse ( PropertyDescriptionViewer & );" in the application. This interface might be bound at run time with an ordinary function pointer, and not bound through a pure virtual base. Since data description is accessed through a static member function then ordinary function pointers appear to be a plausible way to bind to this interface. There may not be justification to juxtapose an additional layer of overhead for a virtual interface. That might be necessary only if there was more than one function of this type.
* To allow all three traverse functions to be implemented with a template the properties are revealed using three new property handle types corresponding to the three types of traversal supported.
Here are the slightly revised Data Access interfaces.
enum propertyHandleType {
    phMutable,
    phImmutable,
    phDescription
};
template < propertyHandleType PHT, class T >
class PropertyHandle;
template < class T >
class PropertyHandle < phMutable, T > {
public:
    PropertyHandle (
        const PropertyId & id, T & value, 
        PropertyCatalog & subordinate = voidContainer );
    T & value () const;
    const PropertyId & id () const;
    PropertyCatalog & subordinate () const;
private:
    T & _scalar;
    const PropertyId & _id;
    PropertyCatalog & _subordinateProperties;
};
template < class T >
class PropertyHandle < phImmutable, T > {
public:
    PropertyHandle (
        const PropertyId & id, const T & value, 
        const PropertyCatalog & subordinate = voidContainer );
    const T & value () const;
    const PropertyId & id () const;
    const PropertyCatalog & subordinate () const;
private:
    const T & _scalar;
    const PropertyId & _id;
    const PropertyCatalog & _subordinateProperties;
};
template < class T >
class PropertyHandle < phDescription, T > {
public:
    PropertyHandle ( const PropertyId & id, 
        const PropertyCatalog & = voidContainer );
    const PropertyId & id () const;
    const PropertyCatalog & subordinate () const;
private:
    const PropertyId & _id;
    const PropertyCatalog & _subordinateProperties;
};
template <
    propertyHandleType PHT,
    template < propertyHandleType PHT, class T > class PROP_HANDLE >
class PropertyManipulatorBase {
public:
    virtual void reveal ( const PROP_HANDLE < PHT, float > & )  = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, double > & )  = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, char > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, signed char > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, unsigned char > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, short > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, unsigned short > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, int > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, unsigned int > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, long > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, unsigned long > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, Time > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, StringSegment > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, EnumStateSet > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, ArraySegment > & ) = 0;
    virtual void reveal ( const PROP_HANDLE < PHT, PropertyCatalog > & ) = 0;
};
class PropertyManipulator :
    public PropertyManipulatorBase < phMutable, PropertyHandle > {
};
class PropertyViewer :
    public PropertyManipulatorBase < phImmutable, PropertyHandle > {
};
class PropertyDescriptionViewer :
    public PropertyManipulatorBase < phDescription, PropertyHandle > {
};
class PropertyCatalog {
public:
    virtual void traverse (
        PropertyManipulator & ) = 0;
    virtual void traverse (
        PropertyViewer & ) const = 0;
    // false returned when the property does not exist, otherwise true
    virtual bool find (
        const PropertyId & id, PropertyViewer & ) const = 0;
};

Revision as of 17:01, 20 May 2005

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 quite 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 not really right is that all three of the traverse functions are nearly identical. Personally, I don’t like to see common code managed with cut and paste.

So I had a look at what level of Data Access library support might be provided so that they might avoid needing to write three traverse functions. The following is an example of how they might structure their application. This level of complication appears to be reasonable for end user applications.

PropertyId propertyX; PropertyId propertyY;

class MyContainer :

   private PropertyCatalog {
   int x;
   float y;
   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 > void MyContainer::traverseTempl (

   const REFERENCE & ref, MANIPULATOR & manipulator )

{

   manipulator.reveal ( 
       ref.propertyFactory ( propertyX, & MyContainer::x ) );
   manipulator.reveal ( 
       ref.propertyFactory ( propertyY, & MyContainer::y ) );

}

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;

}

Here is a summary of the changes:

  • A new "static void traverse ( PropertyDescriptionViewer & );" in the application. This interface might be bound at run time with an ordinary function pointer, and not bound through a pure virtual base. Since data description is accessed through a static member function then ordinary function pointers appear to be a plausible way to bind to this interface. There may not be justification to juxtapose an additional layer of overhead for a virtual interface. That might be necessary only if there was more than one function of this type.
  • To allow all three traverse functions to be implemented with a template the properties are revealed using three new property handle types corresponding to the three types of traversal supported.

Here are the slightly revised Data Access interfaces.

enum propertyHandleType {

   phMutable,
   phImmutable,
   phDescription

};

template < propertyHandleType PHT, class T > class PropertyHandle;

template < class T > class PropertyHandle < phMutable, T > { public:

   PropertyHandle ( 
       const PropertyId & id, T & value,  
       PropertyCatalog & subordinate = voidContainer );
   T & value () const;
   const PropertyId & id () const;
   PropertyCatalog & subordinate () const;

private:

   T & _scalar;
   const PropertyId & _id;
   PropertyCatalog & _subordinateProperties;

};

template < class T > class PropertyHandle < phImmutable, T > { public:

   PropertyHandle ( 
       const PropertyId & id, const T & value,  
       const PropertyCatalog & subordinate = voidContainer );
   const T & value () const;
   const PropertyId & id () const;
   const PropertyCatalog & subordinate () const;

private:

   const T & _scalar;
   const PropertyId & _id;
   const PropertyCatalog & _subordinateProperties;

};

template < class T > class PropertyHandle < phDescription, T > { public:

   PropertyHandle ( const PropertyId & id,  
       const PropertyCatalog & = voidContainer );
   const PropertyId & id () const;
   const PropertyCatalog & subordinate () const;

private:

   const PropertyId & _id;
   const PropertyCatalog & _subordinateProperties;

};

template <

   propertyHandleType PHT, 
   template < propertyHandleType PHT, class T > class PROP_HANDLE >

class PropertyManipulatorBase { public:

   virtual void reveal ( const PROP_HANDLE < PHT, float > & )  = 0;
   virtual void reveal ( const PROP_HANDLE < PHT, double > & )  = 0;
   virtual void reveal ( const PROP_HANDLE < PHT, char > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, signed char > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, unsigned char > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, short > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, unsigned short > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, int > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, unsigned int > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, long > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, unsigned long > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, Time > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, StringSegment > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, EnumStateSet > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, ArraySegment > & ) = 0; 
   virtual void reveal ( const PROP_HANDLE < PHT, PropertyCatalog > & ) = 0; 

};

class PropertyManipulator :

   public PropertyManipulatorBase < phMutable, PropertyHandle > {

};

class PropertyViewer :

   public PropertyManipulatorBase < phImmutable, PropertyHandle > {

};

class PropertyDescriptionViewer :

   public PropertyManipulatorBase < phDescription, PropertyHandle > {

};

class PropertyCatalog { public:

   virtual void traverse ( 
       PropertyManipulator & ) = 0;
   virtual void traverse ( 
       PropertyViewer & ) const = 0;
   // false returned when the property does not exist, otherwise true
   virtual bool find ( 
       const PropertyId & id, PropertyViewer & ) const = 0;

};