EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: data access structures, strings
From: "Jeff Hill" <[email protected]>
To: "'Jeff Hill'" <[email protected]>, "'Kay-Uwe Kasemir'" <[email protected]>, <[email protected]>
Date: Mon, 26 Sep 2005 16:47:46 -0600
Kay,

Of course the example I gave does not show how to specify a path for
fetching a MyColor color set from deep within the hierarchy of catalogX, as
was your original usage case. At the moment, when its in a fast access
compile time known structure, the only way to do that is to specify the path
using extra hierarchy in the destination PropertyContainer. Like this.

struct MyContainer
{
private:
    MyColor color; 
    template < class VIEWER >
    static void traverse ( VIEWER & );
};
 
template < class VIEWER >
inline void MyContainer:: traverse ( VIEWER & viewer )
{
    viewer.reveal ( color, & MyContainer::MyColor );
}

Its true that this implies some constraints on fast access compile time
known structure based source and destination containers. However, I agree
that, should the hierarchy become more than a few levels deep and property
selection in the source container is sparse, this approach might become
labor intensive.

So we could provide some support function that removes a generic property
hierarchy path (specified by an sequence of property identifiers) prior to
calling traverse or find. In essence we might call a noop
viewer/manipulator/surveyor until reaching the specified part of the
hierarchy. Another possibility would be to modify the ClassCatalog template
so that when revealing a container its virtual property hierarchy path can
be specified. Another possibility would be to designate this as a CA issue
and allow property hierarchy to be specified in the channel name. In reality
all of the above might be provided by implementing a core capability and
then layering it into successive levels in the system.


I summary, agree that some path specifying capabilities would be nice in the
support libraries. However, AFAICT none of this will have any impact on the
core DA interfaces presented so far as these capabilities can be layered
above the catalog/viewer/manipulator/surveyor interfaces. 

Jeff

> -----Original Message-----
> From: Jeff Hill [mailto:[email protected]]
> Sent: Monday, September 26, 2005 12:13 PM
> To: 'Kay-Uwe Kasemir'; [email protected]
> Subject: RE: data access structures, strings
> 
> 
> Kay,
> 
> 1) In your example you know at compile time that you want to extract the
> red, green, and blue properties out of some unknown PropertyCatalog. Your
> example is therefore unnecessarily complicated. Here is a simplified
> approach. We will use the name catalogX for the unknown PropertCatalog to
> be
> extracted from. We will use the name MyColor for the class that knows it
> wants RGB at compile time.
> 
> In this situation you have control over the content of MyColor and no
> control over the content of catalogX. Since you have control over MyColor
> you can access it in any way MyColor sees fit - with blinding speed.
> 
> MyColor mc;
> mc.set ( catalogX );
> 
> extern PropertyId & colorRed;
> extern PropertyId & colorGreen;
> extern PropertyId & colorBlue;
> 
> struct MyColor
> {
> public:
>     void set ( const & PropertyCatalog );
> private:
>     int r, g, b;
>     template < class VIEWER >
>     static void traverse ( VIEWER & );
> };
> 
> MyColor :: set ( const PropertyCatalog & incoming )
> {
>     ClassCatalog
>         < MyColor, PropertyManipulator, traverse >
> 		manipulator ( *this );
>     manipulator = incoming;
> }
> 
> template < class VIEWER >
> inline void MyColor :: traverse ( VIEWER & viewer )
> {
>     viewer.reveal ( colorRed, & MyColor::r );
>     viewer.reveal ( colorGreen, & MyColor::g );
>     viewer.reveal ( colorBlue, & MyColor::b );
> }
> 
> Note that there is no need for initialization flags above because the
> ClassCatalog guarantees that when making assignments that *all* properties
> on the destination are set.
> 
> Note that there is no implementation of find above (that's because the
> default find now implements find with traverse). You can still optimize
> find
> as you see fit by overriding the base find.
> 
> 2) If you want to have "MyColor->find("color")->find("red")->toDouble()"
> that's easy to. We could do this writing only a very small amount of code
> on
> top of DataAccess reveal interfaces. This code can be written once, placed
> in a library, and reused for any type of property, and is *not* specific
> to
> red green, and blue colors. I noticed in your example that you are writing
> many reveal functions. There is no need for this with C++ templates. C++
> templates are great for situations where the algorithm Is the same, but
> the
> data type varies. I can show you how to automate this if you are
> interested
> (DA internally makes heavy use of this technique).
> 
> Personally, the
> getDouble()/getFloat/getInt/getUnsigned/getTime/getString/... type of
> interface makes me nauseous. It looks from my perspective exactly like the
> negative aspects of the GDD interface design. You have to play that game
> "are you an animal, vegetable, or mineral" with the data. All of the
> design
> guides recommend calling an application specific virtual function that is
> implemented for all of the different data types (using a template of
> course). Many C++ tutorials use the example virtual function
> "displayYourSelf ()".
> 
> 3) Here is a better design compared to
> MyColor->find("color")->find("red")->toDouble()" IMHO. Presumably you are
> using this type of interface because you don't know the properties that
> are
> needed at compile time. Some select applications will need this. For them,
> it would probably be more useful to inflate a property container
> dynamically
> adapting to what is needed. Note that below I have PropertyContainer and
> not
> PropertyCatalog. The intent is that a PropertyContainer would be a new
> class
> for efficiently storing linked lists of data type specific property
> containing objects a) polymorphicly interfaced by DA, b) polymorphicly
> interfaced in whatever way might be appropriate for the
> learn-the-data-at-run-time type of application, and c) with individual
> properties efficiently memory managed using primitive type specific free
> lists.
> 
> Sorry if I am preempting Ralph here, but here goes an over trivialized
> example.
> 
> PropertyContainer & potLuck ( catalogX );
> PropertyContainerIterator iter = potluck.makeIterator ();
> 
> while ( iter != = iter::end () ) {
> 	iter->displayYourSelf ();
> }
> 
> PS: Use of an iterator interface might very well be appropriate for
> private
> use by the probe type of application. The iterator interface approach
> would
> be very inappropriate for passing data between dissimilar components
> because:
> 
> A) Component A, once it has given up an iterator to component B, never
> knows
> when component B is done using its iterator. There can be big problems
> with
> enforcement of mutual exclusion, lifetime management, and above all
> interface responsibility clarity (who is responsible for what on either
> side
> of the fence).
> 
> B) Its possible for component B to make inconsistent and incomplete
> property
> set changes in component A.
> 
> C) An iterator is easy to implement for linked list property container,
> but
> inefficient (and unnecessarily complex) to implement for an application
> that
> is just interfacing a compile time known structure like MyColor. The
> traverse approach works equally well for a linked list of properties and
> also for MyColor and therefore from my humble perspective is the more
> general approach.
> 
> HTH
> 
> Jeff
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> You seem to be mixing up two things that should be viewed as independent
> topics.
> 
> First there is exporting the data. With that we want an interface that is
> a)
> efficient and b) easy for a person that has proprietary data and wants to
> interface it via a standard mechanism.
> 
> Second there is the application's perspective when he wants to access
> unknown proprietary data that has been exported using the standard
> interface.
> 
> 
> > > Here's my example of what
> > > the "pulling"
> > >
> > >    data_catalog->find("color")->find("red")->toInt()
> > >    data_catalog->find("color")->find("green")->toInt()
> > >    data_catalog->find("color")->find("blue")->toInt()
> > >
> > > turns into based on the dataAccess callback mechanism:
> 
> 
> 
> 
> > -----Original Message-----
> > From: Kay-Uwe Kasemir [mailto:[email protected]]
> > Sent: Monday, September 26, 2005 8:58 AM
> > To: [email protected]
> > Subject: Fwd: data access structures, strings
> >
> >
> >
> > Begin forwarded message:
> >
> > > From: Kay-Uwe Kasemir <[email protected]>
> > > Date: September 26, 2005 10:58:02 EDT
> > > To: Jeff Hill <[email protected]>
> > > Subject: Re: data access structures, strings
> > >
> > >
> > >
> > > On Sep 23, 2005, at 18:43 , Jeff Hill wrote:
> > >
> > >> its easy enough to write a
> > >> convenience library that implements "destination->r =
> > >> data_catalog->find("color")->find("red")->toDouble()" on top of
> > >> the data
> > >> access minimalist interfaces.
> > >>
> > > Here's my example of what
> > > the "pulling"
> > >
> > >    data_catalog->find("color")->find("red")->toInt()
> > >    data_catalog->find("color")->find("green")->toInt()
> > >    data_catalog->find("color")->find("blue")->toInt()
> > >
> > > turns into based on the dataAccess callback mechanism:
> > >
> > > class PickRGBPieces : public propertyViewer
> > > {
> > > public:
> > >     PickRGBPieces()
> > >     { in_color = have_r = have_g = have_b = false; }
> > >     bool isValid()
> > >     { return !in_color && have_r && have_g && have_b; }
> > >     int getR()
> > >     { return r; }
> > >     int getG()
> > >     { return g; }
> > >     int getB()
> > >     { return b; }
> > >     void reveal ( const propertyId &, const double &v, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &id, const int &v, const
> > > propertyCatalog &x)
> > >     {
> > >         if (in_color)
> > >         {
> > >             if (id == red_id)
> > >             {
> > >                 r = v;
> > >                 have_r = true;
> > >             }
> > >             else if (id == green_id)
> > >             {
> > >                 g = v;
> > >                 have_g = true;
> > >             }
> > >             else if (id == blue_id)
> > >             {
> > >                 b = v;
> > >                 have_b = true;
> > >             }
> > >         }
> > >     }
> > >     void reveal ( const propertyId &, const unsigned int &v, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &, const long &v, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &, const unsigned long &v, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &, const epicsTime &, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &, const stringSegment &, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &, const enumStateSet & )
> > >     {}
> > >     void reveal ( const propertyId &, const arraySegment &, const
> > > propertyCatalog &x)
> > >     {}
> > >     void reveal ( const propertyId &id, const propertyCatalog &x)
> > >     {
> > >         if (id == color_id)
> > >         {
> > >             in_color = true;
> > >             x.traverse(*this);
> > >             in_color = false;
> > >         }
> > >     }
> > > private:
> > >     bool in_color, have_r, have_g, have_b;
> > >     int r, g, b;
> > > };
> > >
> > > PickRGBPieces rgb;
> > > data_catalog.traverse(rgb);
> > > if (rgb.isValid())
> > > {
> > >     cout << "Red   : " << rgb.getR() << "\n";
> > >     cout << "Green : " << rgb.getG() << "\n";
> > >     cout << "Blue  : " << rgb.getB() << "\n";
> > > }
> > >
> > >
> > > -Kay
> > >



References:
RE: data access structures, strings Jeff Hill

Navigate by Date:
Prev: Re: data access structures, strings Kay-Uwe Kasemir
Next: Re: data access structures, strings Andrew Johnson
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: data access structures, strings Jeff Hill
Next: EPICS Meeting agenda Dalesio, Leo `Bob`
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·