From 047de406428f952871a54e92ba31e04a4d2c9790 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Mon, 10 Nov 2014 09:06:35 -0500 Subject: [PATCH] change date, this version, and previous version --- documentation/pvDataCPP.html | 8 +- documentation/pvDataCPP_20141110.html | 5478 +++++++++++++++++++++++++ 2 files changed, 5482 insertions(+), 4 deletions(-) create mode 100644 documentation/pvDataCPP_20141110.html diff --git a/documentation/pvDataCPP.html b/documentation/pvDataCPP.html index c430a2c..dc7e2ea 100644 --- a/documentation/pvDataCPP.html +++ b/documentation/pvDataCPP.html @@ -37,7 +37,7 @@

EPICS pvDataCPP

-

EPICS v4 Working Group, Working Draft, 08-Oct-2014

+

EPICS v4 Working Group, Working Draft, 10-Nov-2014

Latest version:
@@ -46,11 +46,11 @@
This version:
pvDataCPP_20140723.html + href="pvDataCPP_20141110.html">pvDataCPP_20141110.html
Previous version:
pvDataCPP_20140708.html + href="pvDataCPP_20140723.html">pvDataCPP_20140723.html
Editors:
Marty Kraimer, BNL
@@ -79,7 +79,7 @@ V4 control system programming environment:

Status of this Document

-

This is the 08-Oct-2014 version of the C++ implementation of pvData. +

This is the 10-Nov-2014 version of the C++ implementation of pvData.

RELEASE_NOTES.md provides changes since the last release. diff --git a/documentation/pvDataCPP_20141110.html b/documentation/pvDataCPP_20141110.html new file mode 100644 index 0000000..dc7e2ea --- /dev/null +++ b/documentation/pvDataCPP_20141110.html @@ -0,0 +1,5478 @@ + + + + + + EPICS pvDataCPP + + + + + + + + +

+

EPICS pvDataCPP

+ + +

EPICS v4 Working Group, Working Draft, 10-Nov-2014

+ +
+
Latest version:
+
pvDataCPP.html +
+
This version:
+
pvDataCPP_20141110.html +
+
Previous version:
+
pvDataCPP_20140723.html +
+
Editors:
+
Marty Kraimer, BNL
+
Michael Davidsaver, BNL
+
Matej Sekoranja, CosyLab
+
David Hickin, Diamond Light Source
+
+ + +
+
+ +

Abstract

+ +

EPICS Version 4 provides efficient +storage, access, and communication, of memory resident structured data. +pvData is the storage component. +pvDataCPP is the C++ implementation of pvData. +It is one part of the set of related products in the EPICS +V4 control system programming environment:
+relatedDocumentsV4.html +

+ + +

Status of this Document

+ +

This is the 10-Nov-2014 version of the C++ implementation of pvData. +

+ +

RELEASE_NOTES.md provides changes since the last release. +TODO.md describes things to do before the next release. +

+ + + +
+

Table of Contents

+
+
+ +

Introduction

+ +

pvData is one of a set of related projects. It describes and implements +data that the other projects support. Thus it is not useful by itself but +understanding pvData is required in order to understand the other projects. The +reader should also become familiar with project pvAccess, which is +located via the same sourceforge site as this project.

+ +

The Java and C++ implementation of pvData implement the same data model but +differ in implementation because of the differences between Java and C++.

+ +

It is a good idea to read all of pvDataJava.html but read at least the +first two chapters:

+
+
Introduction
+
A brief description of pvData.
+
PVData Meta Language
+
A language used to describe data.
+
+ +

The material in these two chapters is NOT repeated in this documentation.

+ +

Doxygen documentation is available at doxygenDoc

+

The next section provides some examples of creating and accessing data. +

+

This document discusses the following:

+
+
src/pv
+
This subdirectory contains all the public interfaces that describe pvData. + The section from Namespace and Memory Management + through Conversion discuss these interfaces. +
+
src/property
+
This section has support for managing "standard" fields. +
+
src/misc
+
This section has support for facilities required by implementation code.
+
src/copy and src/monitor
+
These sections provide pvData support for implementing pvAccess providers.
+
+ +

Examples

+

This section provides some examples of creating and accessing both introspection and +data interfaces. The first time reader may not understand them but hopefully will get an +idea of how pvData works. After reading the rest of this document the examples will +be much easier to understand. +

+

The documentation directory for this project has a file examples.zip. +It has the code for the examples. +After it is unzipped:

+
+cd examples/configure
+cp ExampleRELEASE.local RELEASE.local
+#edit RELEASE.local
+cd ..
+make
+
+Now you are ready to run the examples: +
+bin/linux-x86_64/introspectMain 
+bin/linux-x86_64/dataMain
+
+

The examples assume that the following statements have been issued:

+
+using std::cout;
+using std::endl;
+FieldCreatePtr fieldCreate = getFieldCreate();
+PVDataCreatePtr pvDataCreate = getPVDataCreate();
+StandardFieldPtr standardField = getStandardField();
+StandardPVFieldPtr standardPVField = getStandardPVField();
+
+

These provide access to most of pvData:

+
+
fieldCreate
+
This creates instances of introspection objects. + It also provides fieldBuilder, which provides an easier way to create introspection objects. +
+
pvDataCreate
+
This creates instances of data objects. +
+
standardField
+
This provides support for introspection objects for standard fields, + Standard fields are alarm, timeStamp, display, enumerated structure, and value alarm. +
+
standardPVField
+
This provides support for data objects for standard fields, +
+
+ + +

Introspection Examples

+

The examples all produce a top level structure. +The reason is that top level structures are what pvAccess passes between client and server +and what pvDatabaseCPP supports.

+

Three ways to create a structure

+

The following is the hardest way to create structure that has a double value field and a time stamp field: +It uses only createField. +

+
+    size_t n = 3;
+    StringArray names;
+    names.reserve(n);
+    FieldConstPtrArray fields;
+    fields.reserve(n);
+    names.push_back("secondsPastEpoch");
+    fields.push_back(fieldCreate->createScalar(pvLong));
+    names.push_back("nanoseconds");
+    fields.push_back(fieldCreate->createScalar(pvInt));
+    names.push_back("userTag");
+    fields.push_back(fieldCreate->createScalar(pvInt));
+    StructureConstPtr timeStamp = fieldCreate->createStructure(names,fields);
+    size_t ntop = 2;
+    StringArray topnames;
+    topnames.reserve(ntop);
+    FieldConstPtrArray topfields;
+    topfields.reserve(ntop);
+    topnames.push_back("value");
+    topfields.push_back(fieldCreate->createScalar(pvDouble));
+    topnames.push_back("timeStamp");
+    topfields.push_back(timeStamp);
+    StructureConstPtr doubleScalar =
+        fieldCreate->createStructure(topnames,topfields);
+    cout << *doubleScalar << endl;
+
+

Using FieldBuilder the same can be done via:

+
+    StructureConstPtr doubleScalarHard =
+    getFieldCreate()->createFieldBuilder()->
+        add("value",pvDouble) ->
+        addNestedStructure("timeStamp")->
+            setId("time_t")->
+            add("secondsPastEpoch", pvLong)->
+            add("nanoseconds", pvInt)->
+            add("userTag", pvInt)->
+            endNested()->
+        createStructure();
+    cout << *doubleScalarHard << endl;
+
+

The easiest way to produce the structure is:

+
+    StructureConstPtr stringArrayEasy =
+         getStandardField()->scalarArray(pvString,"alarm,timeStamp");
+    cout << *stringArrayEasy << "\n\n";
+
+These three ways produce: +
+hardest way
+structure
+    double value
+    structure timeStamp
+        long secsPastEpoch
+        int nanoseconds
+        int userTag
+
+hard way
+structure
+    double value
+    time_t timeStamp
+        long secsPastEpoch
+        int nanoseconds
+        int userTag
+
+easy way
+epics:nt/NTScalarArray:1.0
+    string[] value
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+
+

An easy way to create a structure with a string array value field and an alarm and time stamp is +via standardField:

+
+    StructureConstPtr stringArrayEasy =
+        standardField->scalarArray(pvString,"alarm,timeStamp");
+    cout << *stringArrayEasy << endl;
+
+It produces : +
+epics:nt/NTScalarArray:1.0
+    string[] value
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+0x607188
+
+

enumerated structure

+

An enumerated structure is a structure with two subfields: +index, which is an int, and choices, which is an array of string. +The following examples create a structure which has a field names value, which +is an enumerated structure and additional fields. +A hard way to create an structure with an enumerated value field and a time stamp is:

+
+    StructureConstPtr enum_t =
+    fieldCreate->createFieldBuilder()->
+        setId("enum_t")->
+        add("index", pvInt)->
+        addArray("choices", pvString)->
+        createStructure();
+
+    StructureConstPtr ntEnumHard =
+    fieldCreate->createFieldBuilder()->
+        setId("epics:nt/NTEnum:1.0")->
+        add("value", enum_t)->
+        addNestedStructure("timeStamp")->
+            setId("time_t")->
+            add("secondsPastEpoch", pvLong)->
+            add("nanoseconds", pvInt)->
+            add("userTag", pvInt)->
+            endNested()->
+        createStructure();
+    cout << *ntEnumHard << endl;
+
+It produces: +
+epics:nt/NTEnum:1.0
+    enum_t value
+        int index
+        string[] choices
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+
+

The following is an easy way. Note that it has two additional +fields: alarm and timeStamp:

+
+    StructureConstPtr ntEnumEasy = getStandardField()->enumerated("alarm,timeStamp");
+    cout << *ntEnumEasy << endl;
+
+It produces: +
+epics:nt/NTEnum
+    enum_t value
+        int index
+        string[] choices
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+
+ +

union example

+

The following creates a union and a structure with a union value field:

+ +
+    UnionConstPtr ntunion =
+    fieldCreate->createFieldBuilder()->
+        add("doubleValue", pvDouble)->
+        add("intValue", pvInt)->
+        add("timeStamp",standardField->timeStamp())->
+        createUnion();
+    cout << *ntunion << endl;
+
+    StructureConstPtr unionValue = standardField->regUnion(punion,"alarm,timeStamp");
+    cout << *unionValue << endl;
+
+It produces: +
+union
+    double doubleValue
+    int intValue
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+
+structure with value field being a union
+epics:nt/NTUnion:1.0
+    union value
+        double doubleValue
+        int intValue
+        time_t timeStamp
+            long secondsPastEpoch
+            int nanoseconds
+            int userTag
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+
+ +

union array example

+

The following:

+
+    UnionArrayConstPtr unionArray = fieldCreate->createUnionArray(
+        fieldCreate->createVariantUnion());
+    cout << *unionArray << "\n\n";
+
+

Produces

+
+any[]
+any
+0x607188
+
+

power supply

+

The following creates a more complex structure:

+
+    StructureConstPtr powerSupply =
+    fieldCreate->createFieldBuilder()->
+        add("alarm",standardField->alarm()) ->
+        add("timestamp",standardField->timeStamp()) ->
+        addNestedStructure("power") ->
+           add("value",pvDouble) ->
+           add("alarm",standardField->alarm()) ->
+           endNested()->
+        addNestedStructure("voltage") ->
+           add("value",pvDouble) ->
+           add("alarm",standardField->alarm()) ->
+           endNested()->
+        addNestedStructure("current") ->
+           add("value",pvDouble) ->
+           add("alarm",standardField->alarm()) ->
+           endNested()->
+        createStructure();
+    std::cout << *powerSupply <<std::endl;
+
+It produces: +
+structure
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    time_t timestamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+    structure power
+        double value
+        alarm_t alarm
+            int severity
+            int status
+            string message
+    structure voltage
+        double value
+        alarm_t alarm
+            int severity
+            int status
+            string message
+    structure current
+        double value
+        alarm_t alarm
+            int severity
+            int status
+            string message
+
+

Data Examples

+

The examples all produce a top level structure.

+

scalar example

+
+    PVStructurePtr doubleValue = getPVDataCreate()->createPVStructure(
+        getStandardField()->scalar(pvDouble,"alarm,timeStamp"));
+    PVDoublePtr pvdouble =
+        doubleValue->getSubField<PVDouble>("value");
+    pvdouble->put(1e5);
+    cout << *doubleValue << endl;
+    double value = doubleValue->getSubField<PVDouble>("value")->get();
+    cout << "from get " << value << "\n\n";
+
+This produces: +
+epics:nt/NTScalar:1.0
+    double value 100000
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message 
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x607268
+from get 100000
+
+

array example

+
+    PVStructurePtr doubleArrayValue = pvDataCreate->createPVStructure(
+        standardField->scalarArray(pvDouble,"alarm,timeStamp"));
+    PVDoubleArrayPtr pvDoubleArray =
+         doubleArrayValue->getSubField<PVDoubleArray>("value");
+    size_t len = 10;
+    shared_vector<double> xxx(len);
+    for(size_t i=0; i< len; ++i) xxx[i] = i;
+    shared_vector<const double> data(freeze(xxx));
+    pvDoubleArray->replace(data);
+    cout << *doubleArrayValue << endl;
+    
+    shared_vector<const double>  getData = pvDoubleArray->view();
+    cout << "via getData";
+    for (size_t i=0; i< len; ++i) cout << " " << getData[i];
+    cout << endl;
+
+This produces: +
+epics:nt/NTScalarArray:1.0
+    double[] value [0,1,2,3,4,5,6,7,8,9]
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message 
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x607268
+via getData 0 1 2 3 4 5 6 7 8 9
+
+

enumerated example

+
+    PVStructurePtr pvntenum = pvDataCreate->createPVStructure(
+         standardField->enumerated("alarm,timeStamp"));
+    cout << *pvntenum << "\n\n";
+
+This produces: +
+epics:nt/NTEnum:1.0
+    enum_t value
+        int index 0
+        string[] choices []
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message 
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x607268
+
+

power supply example

+
+    StructureConstPtr powerSupply =
+    fieldCreate->createFieldBuilder()->
+        add("alarm",alarm) ->
+        add("timestamp",timeStamp) ->
+        addNestedStructure("power") ->
+           add("value",pvDouble) ->
+           add("alarm",alarm) ->
+           endNested()->
+        addNestedStructure("voltage") ->
+           add("value",pvDouble) ->
+           add("alarm",alarm) ->
+           endNested()->
+        addNestedStructure("current") ->
+           add("value",pvDouble) ->
+           add("alarm",alarm) ->
+           endNested()->
+        createStructure();
+    PVStructurePtr pvpowerSupply = pvDataCreate->createPVStructure(powerSupply);
+    cout << *pvpowerSupply << endl;
+
+This produces: +
+structure 
+    alarm_t alarm_t
+        int severity 0
+        int status 0
+        string message 
+    time_t timestamp_t
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+    structure power
+        double value 0
+        alarm_t alarm
+            int severity 0
+            int status 0
+            string message 
+    structure voltage
+        double value 0
+        alarm_t alarm
+            int severity 0
+            int status 0
+            string message 
+    structure current
+        double value 0
+        alarm_t alarm
+            int severity 0
+            int status 0
+            string message 
+0x607268
+
+

union example

+
+    PVStructurePtr pvStructure = pvDataCreate->createPVStructure(
+        standardField->regUnion(
+            fieldCreate->createFieldBuilder()->
+                add("doubleValue", pvDouble)->
+                add("intValue", pvInt)->
+                add("timeStamp",standardField->timeStamp())->
+                createUnion(),
+            "alarm,timeStamp"));
+    PVStructurePtr pvTimeStamp =
+        pvStructure->getSubField<PVUnion>("value")->select<PVStructure>(2);
+    pvTimeStamp->getSubField<PVLong>("secondsPastEpoch")->put(1000);
+    cout << *pvStructure) << "\n";
+    pvStructure->getSubField<PVUnion>("value")->select<PVDouble>(0)->put(1e5);
+    cout << *pvStructure << "\n\n";
+
+This produces: +
+epics:nt/NTUnion:1.0
+    union value
+        time_t
+            long secondsPastEpoch 1000
+            int nanoseconds 0
+            int userTag 0
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+epics:nt/NTUnion:1.0
+    union value
+        double  100000
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+
+ +

variant union example

+
+    PVStructurePtr pvStructure = pvDataCreate->createPVStructure(
+        standardField->variantUnion("alarm,timeStamp"));
+    PVStructurePtr pvTimeStamp =
+        pvDataCreate->createPVStructure(standardField->timeStamp());
+    pvStructure->getSubField<PVUnion>("value")->set(pvTimeStamp);
+    pvTimeStamp->getSubField<PVLong>("secondsPastEpoch")->put(1000);
+    cout << *pvStructure << "\n";
+    pvStructure->getSubField<PVUnion>("value")->set(
+        pvDataCreate->createPVScalar(pvDouble));
+    PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
+        pvStructure->getSubField<PVUnion>("value")->get());
+    pvValue->put(1e5);
+    cout << *pvStructure << "\n\n";
+
+This produces: +
+epics:nt/NTUnion:1.0
+    any value
+        time_t
+            long secondsPastEpoch 1000
+            int nanoseconds 0
+            int userTag 0
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+epics:nt/NTUnion:1.0
+    any value
+        double  100000
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+
+ +

big union example

+
+    PVStructurePtr pvStructure = pvDataCreate->createPVStructure(
+        standardField->regUnion(
+            fieldCreate->createFieldBuilder()->
+                add("doubleValue", pvDouble)->
+                addArray("doubleArrayValue",pvDouble)->
+                addNestedUnion("unionValue") ->
+                    add("doubleValue", pvDouble)->
+                    add("alarm",standardField->alarm()) ->
+                    endNested() ->
+                addNestedStructure("structValue") ->
+                    add("doubleValue", pvDouble)->
+                    addArray("doubleArrayValue",pvDouble)->
+                    endNested() ->
+                addNestedUnionArray("unionArrayValue") ->
+                    add("doubleValue", pvDouble)->
+                    add("alarm",standardField->alarm()) ->
+                    endNested() ->
+                addNestedStructureArray("structArrayValue") ->
+                    add("doubleValue", pvDouble)->
+                    addArray("doubleArrayValue",pvDouble)->
+                    endNested() ->
+                createUnion(),
+            "alarm,timeStamp"));
+    cout << "introspection\n";
+    cout << *pvStructure->getStructure() << endl;
+    cout << "data\n";
+    cout << *pvStructure << "\n";
+    PVUnionPtr pvUnion = pvStructure->getSubField<PVUnion>("value");;
+    pvUnion->select("doubleValue");
+    PVDoublePtr pvDouble = pvUnion->get<PVDouble>();
+    pvDouble->put(1.55);
+    cout << "select valueDouble\n";
+    cout << *pvStructure << "\n";
+    cout << "value = " << pvDouble->get() << "\n";
+    pvUnion->select("structValue");
+    pvDouble = pvUnion->get<PVStructure>()->getSubField<PVDouble>("doubleValue");
+    pvDouble->put(1.65);
+    cout << "select structValue\n";
+    cout << *pvStructure << "\n";
+    cout << "value = " << pvDouble->get() << "\n";
+
+This produces: +
+introspection
+epics:nt/NTUnion:1.0
+    union value
+        double doubleValue
+        double[] doubleArrayValue
+        union unionValue
+            double doubleValue
+            alarm_t alarm
+                int severity
+                int status
+                string message
+        structure structValue
+            double doubleValue
+            double[] doubleArrayValue
+        union[] unionArrayValue
+            union[]
+                union
+                    double doubleValue
+                    alarm_t alarm
+                        int severity
+                        int status
+                        string message
+        structure[] structArrayValue
+            structure[]
+                structure
+                    double doubleValue
+                    double[] doubleArrayValue
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    time_t timeStamp
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+0x60a2c8
+data
+epics:nt/NTUnion:1.0
+    union value
+        (none)
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+select valueDouble
+epics:nt/NTUnion:1.0
+    union value
+        double  1.55
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+value = 1.55
+select structValue
+epics:nt/NTUnion:1.0
+    union value
+        structure
+            double doubleValue 1.65
+            double[] doubleArrayValue []
+    alarm_t alarm
+        int severity 0
+        int status 0
+        string message
+    time_t timeStamp
+        long secondsPastEpoch 0
+        int nanoseconds 0
+        int userTag 0
+0x60a2c8
+value = 1.65
+
+ +

Namespace and Memory Management

+ +

Namespace

+ +

All code in project pvDataCPP appears in namespace:

+
namespace epics { namespace pvData {
+     // ...
+}}
+ +

Memory Management

+ +

Many pvDataCPP introspection and data objects are designed to be shared. They are +made available via std::tr1::shared_ptr. +The following naming convention is used +in typedefs:

+
+
Ptr
+
When Ptr appears it stands for std::tr1::shared_ptr. +
+
+

For example:

+
+typedef PVScalarValue<boolean> PVBoolean;
+typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
+
+ +

src/pv

+ +

Directory src/pv has header files that completely describe pvData. +The implementation is provided in directory src/factory. +Test programs appears in testApp/pv.

+ +

NOTES:

+
+
interface
+
The documentation uses the word interface. + This is an analogy with how Java defines interface. + C++ does not have interfaces but directory pv defines classes + with public members that are similar to the Java interfaces. Most of the + implementation is in factory.
+
Naming Conventions
+
The naming conventions for variables, methods, and classes follow the + Java conventions, i. e. class name begin with an upper case letter, + variables and methods begin with a lower case letter.
+
+ +

A PVStructure is a field that contains an array of subfields. Each field has +code for accessing the field. The interface for each field is an interface that +extends PVField. Each field also has an introspection interface, which an +extension of Field. The next few sections describes the complete set of C++ +introspection and data interfaces for pvData.

+ +

Class FieldCreate creates introspection objects. Class PVDataCreate creates +data objects. Class Convert provides a rich set of methods for converting and +copying data between fields.

+ +

Directory src/pv has the following header files:

+
+
pvType.h
+
C++ definitions for primitive types.
+
pvIntrospect.h
+
A complete description of the introspection interfaces.
+
pvData.h
+
A complete description of the data interfaces.
+
convert.h
+
A facility that converts between data fields.
+
pvSubArrayCopy.h
+
This provides a facility that performs array coping between + arrays that have the same type.
+
standardField.h
+
Provides access to introspection interfaces for standard structures + like timeStamp, alarm, etc.
+
standardPVField.h
+
Creates data interfaces for standard data structures like timeStamp, + alarm, etc.
+
+ +

pvType.h

+ +

This provides C/C++ definitions for the pvData primitive types: boolean, +byte, short, int, long, ubyte, ushort, uint, ulong, float, double, and string. +Because pvData is network data, the C++ implementation must implement the +proper semantics for the primitive types.

+ +

pvType.h provides the proper semantics.

+ +

It includes the definitions:

+
+typedef /*lots of stuff*/ boolean
+
+typedef int8_t   int8;
+typedef int16_t  int16;
+typedef int32_t  int32;
+typedef int64_t  int64;
+typedef uint8_t   uint8;
+typedef uint16_t  uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+// float and double are types
+
+typedef std::vector<std::string> StringArray;
+typedef std::tr1::shared_ptr<StringArray> StringArrayPtr;
+inline std::string * get(StringArray &value);
+inline std::string const * get(StringArray const &value);
+inline std::string * get(StringArrayPtr &value);
+inline std::string const * get(StringArrayPtr const &value);
+}
+inline StringArray & getVector(StringArrayPtr &value);
+inline StringArray const & getVector(StringArrayPtr const &value);
+typedef std::vector<std::string>::iterator StringArray_iterator;
+typedef std::vector<std::string>::const_iterator StringArray_const_iterator;
+
+ +

where

+
+
boolean
+
A c++ bool has the semantics required for boolean. Only the name is + different. C++ code can use either bool or boolean.
+
int8,...,uint64
+
Integers present a problem because short, int, and long are C++ + reserved words but do not have a well defined number of bits. Thus for + C++ the definitions above are used in C++ code. The above definitions + have worked on all C++ implementations tested at present. If they break + in a future implementation they should be changes via "#ifdef" + preprocessor statements.
+
std::string
+
pvData requires that a string be an immutable string that is transferred + over the network as a UTF8 encoded string. Since std::string implements + copy on write semantics, it can be used for support for immutable + strings. It can also be serialized/deserialized as a UTF8 encoded string. + Note that std::string is treated like a primitive type.
+
StringArray definitions
+
typedefs are provided for an array of std::strings, + which is a std::vector<std::string>. + This is used by introspection. +
+
+

TBD

+
+
boolean
+
Question for Michael. Why isn't the definition of boolean just +
+typedef uint8_t boolean;
+    
+
+
printer.h
+
Not documented. Is this needed? Nothing currently uses it.
+
+ +

pvIntrospect.h

+ +

This subsection describes pvIntrospect.h This file is quite big so rather +than showing the entire file, it will be described in parts.

+ +

The primary purpose for pvData is to support network access to structured data. +pvAccess transports top level pvStructures. In addition a pvAccess server holds +a set of pvnames, where each name is a unique name in the local network. +This is also referred to as the channel name. +

+ +

Given a pvname, it is possible to introspect the types of the associated data +access to data. The reflection and data interfaces are separate because the +data may not be available. For example when a pvAccess client connects to a pvname, +the client library can obtain the reflection information without obtaining any +data. Only when a client issues an I/O request will data be available. This +separation is especially important for arrays and structures so that a client +can discover the type without requiring that a large data array or structure be +transported over the network.

+ +

Type Description

+ +

Types are defined as:

+
enum Type {
+    scalar,
+    scalarArray,
+    structure,
+    structureArray,
+    union_,
+    unionArray
+};
+
+class TypeFunc {
+public:
+    epicsShareExtern const char* name(Type type);
+};
+
+enum ScalarType {
+    pvBoolean,
+    pvByte, pvShort, pvInt, pvLong,
+    pvUByte, pvUShort, pvUInt, pvULong,
+    pvFloat,pvDouble,
+    pvString;
+};
+
+namespace ScalarTypeFunc {
+public:
+    bool isInteger(ScalarType type);
+    bool isUInteger(ScalarType type);
+    bool isNumeric(ScalarType type);
+    bool isPrimitive(ScalarType type);
+    ScalarType getScalarType(std::string const &value);
+    const char* name(ScalarType);
+    size_t elementSize(ScalarType id);
+};
+std::ostream& operator<<(std::ostream& o, const ScalarType& scalarType);
+
+ +

Type is one of the following:

+
+
scalar
+
A scalar of one of the scalar types.
+
scalarArray
+
An array where every element has the same scalar type.
+
structure
+
A structure where each field has a name and a type. Within a structure + each field name must be unique but the types can be different.
+
structureArray
+
An array where each element is a structure. Each element has the same + structure introspection interface.
+
union_t
+
This is like a structure that has a single subfield. + The type for the subfield can either be any type, which is called a variant union, + of can be one of a specified set of types. + In the data interfaces the type can be changed dynamically. +'
+
unionArray
+
An array where each element is a union. Each element has the same + union introspection interface.
+
+ +

ScalarType is one of the following:

+
+
pvBoolean
+
Has the value false or true.
+
pvByte
+
A signed 8 bit integer.
+
pvShort
+
A signed 16 bit integer.
+
pvInt
+
A signed 32 bit integer.
+
pvLong
+
A signed 64 bit integer.
+
pvUByte
+
An unsigned 8 bit integer.
+
pvUShort
+
An unsigned 16 bit integer.
+
pvUInt
+
An unsigned 32 bit integer.
+
pvULong
+
An unsigned 64 bit integer.
+
pvFloat
+
A IEEE float.
+
pvDouble
+
A IEEE double,
+
pvString
+
An immutable string.
+
+ +

TypeFunction is a set of convenience methods for Type

+
+
name
+
Returns the name of the type.
+
+ +

ScalarTypeFunction is a set of convenience methods for ScalarType

+
+
isInteger
+
Is the scalarType an integer type, i.e. one of pvByte,...pvULong.
+
isUInteger
+
Is the scalarType an unsigned integer type, i.e. one of + pvUByte,...pvULong
+
isNumeric
+
Is the scalarType numeric, i.e. pvByte,...,pvDouble.
+
isPrimitive
+
Is the scalarType primitive, i.e. not pvString
+
name
+
Returns the name of the scalarType.
+
getScalarType
+
Given a string of the form std::string("boolean"),...,std::string("string") + return the scalarType.
+
elementSize
+
Returns the size in bytes of an instance of the scalarType.
+
+ +

Introspection Description

+ +

This section describes the reflection interfaces which provide the +following:

+
+
Field
+
A field: +
    +
  • Has a Type.
  • +
  • Can be converted to a string.
  • +
  • Can be shared. A reference count is kept. When it becomes 0 the + instance is automatically deleted.
  • +
+
+
Scalar
+
A scalar has a scalarType
+
ScalarArray
+
The element type is a scalarType
+
Structure
+
Has fields that can be any of the supported types.
+
StructureArray
+
The field holds an array of structures. Each element has the same + Structure introspection interface. A pvAccess client can only get/put + entire PVStructure elements NOT subfields of array elements.
+
Union
+
+ This has two flavors: a variant union or a union of a fixed set + of types. A PVUnion will have a single subfield. + If the union introspection interface is a variant union then + the single field can be of any type and has the name any. + If the union is not a variant type then the type can be one of + a fixed set of types and a name associated with the type. + The union introspection interface has a field array and a string + array that has the fixed set of types and associated names. +
+
UnionArray
+
+ This is an array of unions. A PVUnionArray is an array + of PVUnions. Each element has the same introspection interface + but the subfield of each element can have a different type. +
+
FieldBuilder
+
This is a convenience interface that makes it easier to create + top introspection interfaces. +
+
FieldCreate
+
This is an interface that provides methods to create introspection + interfaces. A factory is provides to create FieldCreate.
+
getFieldCreate
+
Gets a pointer to the single instance of FieldCreate.
+
+

Field,Scalar,ScalarArray,Structure,StructureArray,Union,UnionArray

+
class Field;
+class Scalar;
+class ScalarArray;
+class Structure;
+class StructureArray;
+class Union;
+class UnionArray;
+
+typedef std::tr1::shared_ptr<const Field> FieldConstPtr;
+typedef std::vector<FieldConstPtr> FieldConstPtrArray;
+typedef std::tr1::shared_ptr<const Scalar> ScalarConstPtr;
+typedef std::tr1::shared_ptr<const ScalarArray> ScalarArrayConstPtr;
+typedef std::tr1::shared_ptr<const Structure> StructureConstPtr;
+typedef std::tr1::shared_ptr<const StructureArray> StructureArrayConstPtr;
+typedef std::tr1::shared_ptr<const Union> UnionConstPtr;
+typedef std::tr1::shared_ptr<const UnionArray> UnionArrayConstPtr;
+
+
+class Field :
+    virtual public Serializable,
+    public std::tr1::enable_shared_from_this<Field>
+{
+public:
+    POINTER_DEFINITIONS(Field);
+    virtual ~Field();
+    Type getType() const{return m_type;}
+    virtual std::string getID() const = 0;
+    virtual std::ostream& dump(std::ostream& o) const = 0;
+ ...
+};
+std::ostream& operator<<(std::ostream& o, const Field& field);
+
+class Scalar : public Field{
+public:
+    POINTER_DEFINITIONS(Scalar);
+    virtual ~Scalar();
+    typedef Scalar& reference;
+    typedef const Scalar& const_reference;
+
+    ScalarType getScalarType() const {return scalarType;}
+    virtual std::string getID() const;
+    virtual std::ostream& dump(std::ostream& o) const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
+ ...
+};
+
+class BoundedString : public Scalar{
+public:
+    POINTER_DEFINITIONS(BoundedString);
+    virtual ~BoundedString();
+    typedef BoundedString& reference;
+    typedef const BoundedString& const_reference;
+
+    std::size_t getMaximumLength() const;
+    virtual std::string getID() const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+...
+};
+
+class epicsShareClass Array : public Field{
+public:
+    POINTER_DEFINITIONS(Array);
+    virtual ~Array();
+    typedef Array& reference;
+    typedef const Array& const_reference;
+    enum ArraySizeType { variable, fixed, bounded };
+
+    virtual ArraySizeType getArraySizeType() const = 0;
+    virtual std::size_t getMaximumCapacity() const = 0;
+ ...
+};
+
+
+class ScalarArray : public Field{
+public:
+    POINTER_DEFINITIONS(ScalarArray);
+    typedef ScalarArray& reference;
+    typedef const ScalarArray& const_reference;
+
+    ScalarArray(ScalarType scalarType);
+    ScalarType  getElementType() const {return elementType;}
+    virtual ArraySizeType getArraySizeType() const;
+    virtual std::size_t getMaximumCapacity() const;
+    virtual std::string getID() const;
+    virtual std::ostream& dump(std::ostream& o) const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+ ...
+};
+
+class epicsShareClass BoundedScalarArray : public ScalarArray{
+public:
+    POINTER_DEFINITIONS(BoundedScalarArray);
+    typedef BoundedScalarArray& reference;
+    typedef const BoundedScalarArray& const_reference;
+
+    BoundedScalarArray(ScalarType scalarType, std::size_t size);
+    virtual ArraySizeType getArraySizeType() const;
+    virtual std::size_t getMaximumCapacity() const;
+    virtual std::string getID() const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+...
+}
+
+class epicsShareClass FixedScalarArray : public ScalarArray{
+public:
+    POINTER_DEFINITIONS(FixedScalarArray);
+    typedef FixedScalarArray& reference;
+    typedef const FixedScalarArray& const_reference;
+
+    FixedScalarArray(ScalarType scalarType, std::size_t size);
+    virtual ArraySizeType getArraySizeType() const {return Array::fixed;}
+    virtual std::size_t getMaximumCapacity() const {return size;}
+    virtual std::string getID() const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+...
+};
+
+
+
+class StructureArray : public Field{
+public:
+    POINTER_DEFINITIONS(StructureArray);
+    typedef StructureArray& reference;
+    typedef const StructureArray& const_reference;
+
+    StructureConstPtr  getStructure() const {return pstructure;}
+    virtual ArraySizeType getArraySizeType() const;
+    virtual std::size_t getMaximumCapacity() const;
+    virtual std::string getID() const;
+    virtual std::ostream& dump(std::ostream& o) const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+ ...
+};
+
+class epicsShareClass UnionArray : public Field{
+public:
+    POINTER_DEFINITIONS(UnionArray);
+    typedef UnionArray& reference;
+    typedef const UnionArray& const_reference;
+    UnionConstPtr  getUnion() const {return punion;}
+    virtual ArraySizeType getArraySizeType() const;
+    virtual std::size_t getMaximumCapacity() const;
+    virtual std::string getID() const;
+    virtual std::ostream& dump(std::ostream& o) const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+};
+
+class Structure : public Field {
+public:
+    POINTER_DEFINITIONS(Structure);
+    typedef Structure& reference;
+    typedef const Structure& const_reference;
+
+    std::size_t getNumberFields() const {return numberFields;}
+    FieldConstPtr getField(std::string const & fieldName) const;
+    FieldConstPtr getField(std::size_t index) const;
+    std::size_t getFieldIndex(std::string const &fieldName) const;
+    FieldConstPtrArray const & getFields() const {return fields;}
+    StringArray const & getFieldNames() const;
+    std::string getFieldName(std::size_t fieldIndex) const;
+    virtual std::string getID() const;
+    virtual std::ostream& dump(std::ostream& o) const;
+    virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
+ ...
+};
+
+class epicsShareClass Union : public Field {
+public:
+    POINTER_DEFINITIONS(Union);
+    static std::string DEFAULT_ID;
+    static std::string ANY_ID;
+    virtual ~Union();
+    typedef Union& reference;
+    typedef const Union& const_reference;
+
+    std::size_t getNumberFields() const;
+    FieldConstPtr getField(std::string const &fieldName) const;
+    FieldConstPtr getField(std::size_t index);
+    std::size_t getFieldIndex(std::string const &fieldName) const;
+    FieldConstPtrArray const & getFields() const;
+    StringArray const & getFieldNames() const;
+    std::string getFieldName(std::size_t fieldIndex) const;
+    bool isVariant() const;
+    virtual std::string getID() const;
+    virtual std::ostream& dump(std::ostream& o) const;
+    virtual void serialize(
+        ByteBuffer *buffer, SerializableControl *control) const;
+    virtual void deserialize(
+        ByteBuffer *buffer, DeserializableControl *control);
+    
+};
+
+
+
Constructors
+
Note that all constructors are protected or private. The only way to + create instances is via fieldBuilder or fieldCreate. The implementation manages all + storage via shared pointers.
+
dump
+
Many classes provide this. This is a stream method that prints using + the metadata syntax described in pvDataJava.html.
+
+ +

Field

+
+
getType
+
Get the field type.
+
getID
+
Get an ID for this introspection interface
+
+ +

Scalar

+
+
getScalarType
+
Get that scalar type.
+
getID
+
For each scalarType there is one instance of Scalar. The ID for each is + the metadata name for the type, i. e. one of "boolean" , ... , "string". +
+
+ +

ScalarArray

+
+
getElementType
+
Get the element type.
+
getID
+
For each elemnetType there is one instance of ScalarArray. The ID for + each is the metadata name for the type, i. e. one of "boolean[]" , ... , + "string[]".
+
+ +

StructureArray

+
+
getStructure
+
Get the introspection interface that each element shares,
+
getID
+
This returns the ID[] where ID is the value returned by + structure->getID().
+
+` +

UnionArray

+
+
getUnion
+
Get the union interface for each element.
+
+ +

Structure

+
+
getNumberFields
+
Get the number of immediate subfields.
+
getField
+
Given a name or an index get the introspection interface for the + field.
+
getFieldIndex
+
Given a name get the index, within the array returned by the next + method, of the field.
+
getFields
+
Get the array of introspection interfaces for the field,
+
getFieldNames
+
Get the array of field names for the subfields.
+
getFieldName
+
Get the field name for the specified index.
+
+

Union

+
+
getNumberFields
+
Get the number of possible field types. + Both getFields and getFieldNames will return an array with getNumberFields elements. + A value of 0 is returned for invariant arrays. +
+
getField
+
Given a name or an index the type is returned. + NULL is returned if not found. +
+
getFieldIndex
+
Get the index for name. -1 is returned if not found.
+
getFields
+
Get the array of types.
+
getFieldNames
+
Get the array of names.
+
getFieldName
+
Get the name for the specified index.
+
isVariant
+
returns true if this is variant array and false otherwise.
+
+

fieldBuilder and createField

+
+class epicsShareClass FieldBuilder :
+    public std::tr1::enable_shared_from_this<FieldBuilder>
+{
+public:
+    FieldBuilderPtr setId(std::string const & id);
+    FieldBuilderPtr add(std::string const & name, ScalarType scalarType);
+    FieldBuilderPtr addBoundedString(std::string const & name, std::size_t maxLength);
+    FieldBuilderPtr add(std::string const & name, FieldConstPtr const & field);
+    FieldBuilderPtr addArray(std::string const & name, ScalarType scalarType);
+    FieldBuilderPtr addFixedArray(
+         std::string const & name,
+         ScalarType scalarType,
+         std::size_t size);
+    FieldBuilderPtr addBoundedArray(std::string const &
+         name,ScalarType scalarType,
+         std::size_t bound);
+    FieldBuilderPtr addArray(std::string const & name, FieldConstPtr const & element);
+    StructureConstPtr createStructure();
+    UnionConstPtr createUnion();
+    FieldBuilderPtr addNestedStructure(std::string const & name); 
+    FieldBuilderPtr addNestedUnion(std::string const & name);
+    FieldBuilderPtr addNestedStructureArray(std::string const & name); 
+    FieldBuilderPtr addNestedUnionArray(std::string const & name);
+    FieldBuilderPtr endNested();
+};
+
+class epicsShareClass FieldCreate {
+public:
+    static FieldCreatePtr getFieldCreate();
+    FieldBuilderPtr createFieldBuilder() const;
+    ScalarConstPtr createScalar(ScalarType scalarType) const;
+    BoundedStringConstPtr createBoundedString(std::size_t maxLength) const;
+    ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
+    ScalarArrayConstPtr createFixedScalarArray(
+        ScalarType elementType, std::size_t size) const
+    ScalarArrayConstPtr createBoundedScalarArray(
+        ScalarType elementType, std::size_t bound) const;
+    StructureArrayConstPtr createStructureArray(
+        StructureConstPtr const & structure) const;
+    StructureConstPtr createStructure () const;
+    StructureConstPtr createStructure (
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    StructureConstPtr createStructure (
+    	std::string const & id,
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    UnionConstPtr createUnion (
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    UnionConstPtr createUnion (
+    	std::string const & id,
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    UnionConstPtr createVariantUnion() const;
+    UnionArrayConstPtr createVariantUnionArray() const;
+    UnionArrayConstPtr createUnionArray(UnionConstPtr const & punion) const;
+    StructureConstPtr appendField(
+        StructureConstPtr const & structure,
+        std::string const & fieldName, FieldConstPtr const & field) const;
+    StructureConstPtr appendFields(
+        StructureConstPtr const & structure,
+        StringArray const & fieldNames,
+        FieldConstPtrArray const & fields) const;
+    FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
+        
+};
+
+epicsShareExtern FieldCreatePtr getFieldCreate();
+
+ +

FieldBuilder

+

This is a class that makes it easier to create introspection interfaces. +It is meant to be used via stream input syntax. See the examples that follow the +description of the methods. +

+
+
setID
+
This sets an ID for the field, which is the name for the field when it is a subfield. +
+
add
+
+ Add a scalar field. +
+
addBoundedString
+
+ Add a scalar field that is a string that has a maximum size. +
+
addArray
+
+ Add an array field. There are two methods: one to create a scalaArray + and one to create scalarArray, unionArray, or structureArray. +
+
addFixedArray
+
+ Add a fixed size scalarArray field. +
+
addBoundedArray
+
+ Add a bounded scalarArray field. +
+
createStructure
+
+ Create a structure from the fields that are currently present. +
+
createUnion
+
+ Create a union from the fields that are currently present. +
+
addNestedStructure
+
+ Add a nested structure. This is followed by an arbitrary number of adds + followed by a an endNested. +
+
addNestedUnion
+
+ Add a nested union. This is followed by an arbitrary number of adds + followed by a an endNested. +
+
addNestedStructureArray
+
+ Add a nested structure array. This is followed by an arbitrary number of adds + followed by a an endNested. +
+
addNestedUnionArray
+
+ Add a nested union array. This is followed by an arbitrary number of adds + followed by a an endNested. +
+
endNested
+
+ End current nested structure or union. +
+
+

Examples of using fieldBuilder were given earlier in this manual.

+

FieldCreate

+
+
getFieldCreate
+
Get the single instance of FieldCreate.
+
createFieldBuilder
+
Create an instance of a FieldBuilder.
+
createScalar
+
Create a scalar introspection instance.
+
createBoundedString
+
create a scalar introspection instance for a bounded string.
+
createScalarArray
+
Create a scalar array introspection instance.
+
createFixedScalarArray
+
Create a scalar array introspection instance.
+
createBoundedScalarArray
+
Create a scalar array introspection instance.
+
createStructure
+
Create a structure introspection instance. Three methods are provided. + The first creates an empty structure, i. e. a structure with no fields. + The other two are similar. + The only difference is that one provides an ID and the other does + not. The one without will result in ID structure.
+
createStructureArray
+
Ceate a structure array introspection instance. + All elements will have the same introspection interface. +
+
createUnion
+
Create a union. There are two methods. + Each has arguments for an array of types and an array of names. + One method has an id. The other results in id = union. +
+
createVariantUnion
+
+ Create a variant union. The id will be any. +
+
createUnionArray
+
Create a union array. punion is the introspection interface + for each element.
+
createVariantUnionArray
+
Create a union array where each element is a variant union.
+
createStructureArray
+
Create a structure array introspection instance.
+
appendField
+
Create a new structure that is like an existing structure but has + an extra field appended to it. +
+
appendFields
+
Create a new structure that is like an existing structure but has + extra fields appended to it. +
+
deserialize
+
Deserialize from given byte buffer.
+
+ +

standardField.h

+ +

The file standardField.h has a class description for creating or sharing +Field objects for standard fields. For each type of field a method is provided. +Each creates a structure that has a field named "value" and a set of properyt +fields, The property field is a comma separated string of property names of the +following: alarm, timeStamp, display, control, and valueAlarm. An example is +"alarm,timeStamp,valueAlarm". The method with properties creates a structure +with fields named value and each of the property names. Each property field is +a structure defining the property. The details about each property is given in +the section named "Property". For example the call:

+
+StructureConstPtr example = standardField->scalar(
+    pvDouble,
+    "value,alarm,timeStamp"
+    );
+
+ +

Will result in a Field definition that has the form:

+
structure example
+    double value
+    alarm_t alarm
+        int severity
+        int status
+        string message
+    timeStamp_t timeStamp
+        long secondsPastEpoch
+        int  nanoseconds
+        int userTag
+ +

In addition there are methods that create each of the property structures, +i.e. the methods named: alarm, .... enumeratedAlarm."

+ +

standardField.h contains:

+
class StandardField;
+typedef std::tr1::shared_ptr<StandardField> StandardFieldPtr;
+
+class StandardField {
+public:
+    static StandardFieldPtr getStandardField();
+    ~StandardField();
+    StructureConstPtr scalar(ScalarType type,std::string const &properties);
+    StructureConstPtr regUnion(
+        UnionConstPtr const & punion,
+        std::string const & properties);
+    StructureConstPtr variantUnion(std::string const & properties);
+    StructureConstPtr scalarArray(
+        ScalarType elementType, std::string const &properties);
+    StructureConstPtr structureArray(
+        StructureConstPtr const & structure,std::string const &properties);
+    StructureConstPtr unionArray(UnionConstPtr const & punion,std::string const & properties);
+    StructureConstPtr enumerated();
+    StructureConstPtr enumerated(std::string const &properties);
+    StructureConstPtr alarm();
+    StructureConstPtr timeStamp();
+    StructureConstPtr display();
+    StructureConstPtr control();
+    StructureConstPtr booleanAlarm();
+    StructureConstPtr byteAlarm();
+    StructureConstPtr ubyteAlarm();
+    StructureConstPtr shortAlarm();
+    StructureConstPtr ushortAlarm();
+    StructureConstPtr intAlarm();
+    StructureConstPtr uintAlarm();
+    StructureConstPtr longAlarm();
+    StructureConstPtr ulongAlarm();
+    StructureConstPtr floatAlarm();
+    StructureConstPtr doubleAlarm();
+    StructureConstPtr enumeratedAlarm();
+ ...
+};
+
+
scalar
+
Create a scalar with the specified scalar type and name. A structure + will be created with the first element being a scalar with the specified + scalar type and name value. The other fields in the structure will be the + corresponding property structures.
+
regUnion
+
A structure + will be created with the first element being a union with the specified + scalar type and name value. The other fields in the structure will be the + corresponding property structures.
+
variant`Union
+
Create a variant union. A structure + will be created with the first element being a union with the specified + scalar type and name value. The other fields in the structure will be the + corresponding property structures.
+
scalarArray
+
Create a scalarArray with each element having the specified scalar type + and name. A structure will be created with the first element being a + scalarArray with name value. The other fields in the structure will be + the corresponding property structures.
+
structureArray
+
Create a structureArray with the specified structure interface and + name. A structure will be created with the first element being a + structureArray with the specified structure interface and name value. The + other fields in the structure will be the corresponding property + structures.
+
unionArray
+
Create a unionArray with the specified union interface and + name. A structure will be created with the first element being a + unionArray with the specified structure interface and name value. The + other fields in the structure will be the corresponding property + structures.
+
structure
+
Create a structure with the specified name and fields specified by + numFields and fields. A structure will be created with the first element + being a structure with the name value and fields specified by numFields + and fields. The other fields in the structure will be the corresponding + property structures.
+
enumerated
+
Create a structure with the specified name and fields for an enumerated + structure. If properties are specified then a structure will be created + with the first element being a structure with the name value and fields + for an enumerated structure. The other fields in the structure will be + the corresponding property structures.
+
alarm
+
timeStamp
+
display
+
control
+
booleanAlarm
+
byteAlarm
+
shortAlarm
+
intAlarm
+
longAlarm
+
floatAlarm
+
doubleAlarm
+
enumeratedAlarm
+
The above provide introspection interfaces for standard properties. See + the section on Properties for a description of how these are defined.
+
+

pvData.h

+ +

This section describes pvData.h This file is quite big so rather than +showing the entire file, it will be described in parts.

+ +

typedefs

+ +

These are typedefs for Array and Ptr for the various pvData class +definitions, i.e. typedefs for "std::vector" and "std::tr1::shared_ptr".

+
+class PVField;
+class PVScalar;
+class PVScalarArray;
+class PVStructure;
+class PVStructureArray;
+class PVUnion;
+
+template<typename T> class PVScalarValue;
+template<typename T> class PVValueArray;
+
+typedef PVValueArray<PVUnionPtr> PVUnionArray;
+typedef std::tr1::shared_ptr<PVUnionArray> PVUnionArrayPtr;
+
+
+typedef std::tr1::shared_ptr<PostHandler> PostHandlerPtr;
+
+typedef std::tr1::shared_ptr<PVField> PVFieldPtr;
+typedef std::vector<PVFieldPtr> PVFieldPtrArray;
+typedef std::vector<PVFieldPtr>::iterator PVFieldPtrArray_iterator;
+typedef std::vector<PVFieldPtr>::const_iterator PVFieldPtrArray_const__iterator;
+
+typedef std::tr1::shared_ptr<PVScalar> PVScalarPtr;
+typedef std::tr1::shared_ptr<PVScalarArray> PVScalarArrayPtr;
+
+typedef std::tr1::shared_ptr<PVStructure> PVStructurePtr;
+typedef std::vector<PVStructurePtr> PVStructurePtrArray;
+typedef std::vector<PVStructurePtr>::iterator PVStructurePtrArray_iterator;
+typedef std::vector<PVStructurePtr>::const_iterator PVStructurePtrArray_const__iterator;
+
+typedef PVValueArray<PVStructurePtr> PVStructureArray;
+typedef std::tr1::shared_ptr<PVStructureArray> PVStructureArrayPtr;
+typedef std::vector<PVStructureArrayPtr> PVStructureArrayPtrArray;
+typedef std::tr1::shared_ptr<PVStructureArrayPtrArray> PVStructureArrayPtrArrayPtr;
+
+typedef std::tr1::shared_ptr<PVUnion> PVUnionPtr;
+typedef std::vector<PVUnionPtr> PVUnionPtrArray;
+typedef std::vector<PVUnionPtr>::iterator PVUnionPtrArray_iterator;
+typedef std::vector<PVUnionPtr>::const_iterator PVUnionPtrArray_const__iterator;
+
+typedef PVValueArray<PVUnionPtr> PVUnionArray;
+typedef std::tr1::shared_ptr<PVUnionArray> PVUnionArrayPtr;
+typedef std::vector<PVUnionArrayPtr> PVUnionArrayPtrArray;
+typedef std::tr1::shared_ptr<PVUnionArrayPtrArray> PVUnionArrayPtrArrayPtr;
+
+class PVDataCreate;
+typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;
+
+
+/**
+ * typedefs for the various possible scalar types.
+ */
+typedef PVScalarValue<boolean> PVBoolean;
+typedef PVScalarValue<int8> PVByte;
+typedef PVScalarValue<int16> PVShort;
+typedef PVScalarValue<int32> PVInt;
+typedef PVScalarValue<int64> PVLong;
+typedef PVScalarValue<uint8> PVUByte;
+typedef PVScalarValue<uint16> PVUShort;
+typedef PVScalarValue<uint32> PVUInt;
+typedef PVScalarValue<uint64> PVULong;
+typedef PVScalarValue<float> PVFloat;
+typedef PVScalarValue<double> PVDouble;
+class PVString;
+typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
+typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
+typedef std::tr1::shared_ptr<PVShort> PVShortPtr;
+typedef std::tr1::shared_ptr<PVInt> PVIntPtr;
+typedef std::tr1::shared_ptr<PVLong> PVLongPtr;
+typedef std::tr1::shared_ptr<PVUByte> PVUBytePtr;
+typedef std::tr1::shared_ptr<PVUShort> PVUShortPtr;
+typedef std::tr1::shared_ptr<PVUInt> PVUIntPtr;
+typedef std::tr1::shared_ptr<PVULong> PVULongPtr;
+typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
+typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
+typedef std::tr1::shared_ptr<PVString> PVStringPtr;
+
+/**
+ * Definitions for the various scalarArray types.
+ */
+typedef PVValueArray<boolean> PVBooleanArray;
+typedef PVValueArray<int8> PVByteArray;
+typedef PVValueArray<int16> PVShortArray;
+typedef PVValueArray<int32> PVIntArray;
+typedef PVValueArray<int64> PVLongArray;
+typedef PVValueArray<uint8> PVUByteArray;
+typedef PVValueArray<uint16> PVUShortArray;
+typedef PVValueArray<uint32> PVUIntArray;
+typedef PVValueArray<uint64> PVULongArray;
+typedef PVValueArray<float> PVFloatArray;
+typedef PVValueArray<double> PVDoubleArray;
+typedef PVValueArray<std::string> PVStringArray;
+
+typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
+typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;
+typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;
+typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;
+typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;
+typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;
+typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;
+typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;
+typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;
+typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;
+typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;
+typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
+
+ +

PVField

+ +

PVField is the base interface for accessing data. A data structure consists +of a top level PVStructure. Every field of every structure of every top level +structure has a PVField associated with it.

+
+class PostHandler
+{
+public:
+    POINTER_DEFINITIONS(PostHandler);
+    virtual ~PostHandler(){}
+    virtual void postPut() = 0;
+};
+
+class PVField
+: virtual public Serializable,
+  public std::tr1::enable_shared_from_this<PVField>
+{
+public:
+   POINTER_DEFINITIONS(PVField);
+   virtual ~PVField();
+   std::string getFieldName() const ;
+   std::string getFullName() const;
+   std::size_t getFieldOffset() const;
+   std::size_t getNextFieldOffset() const;
+   std::size_t getNumberFields() const;
+   bool isImmutable() const;
+   virtual void setImmutable();
+   const FieldConstPtr & getField() const ;
+   PVStructure * getParent() const 
+   void postPut();
+   void setPostHandler(PostHandlerPtr const &postHandler);
+   virtual bool equals(PVField &pv);
+   std::ostream& dumpValue(std::ostream& o) const;
+ ...
+}
+std::ostream& operator<<(std::ostream& o, const PVField& f);
+
+ +

The public methods for PVField are:

+
+
~PVField
+
Destructor. Since shared pointers are used it should never be called by + user code.
+
getFieldName
+
Get the field name. If the field is a top level structure the field + name will be an empty string.
+
getFullName
+
Fully expand the name of this field using the + names of its parent fields with a dot '.' separating + each name. +
+
getFieldOffset
+
Get offset of the PVField field within top level structure. Every field + within the PVStructure has a unique offset. The top level structure has + an offset of 0. The first field within the structure has offset equal to + 1. The other offsets are determined by recursively traversing each + structure of the tree.
+
getNextFieldOffset
+
Get the next offset. If the field is a scalar or array field then this + is just offset + 1. If the field is a structure it is the offset of the + next field after this structure. Thus (nextOffset - offset) is always + equal to the total number of fields within the field.
+
getNumberFields
+
Get the total number of fields in this field. This is nextFieldOffset - + fieldOffset.
+
isImmutable
+
Is the field immutable?
+
setImmutable
+
Make the field immutable. Once a field is immutable it can never be + changed since there is no method to again make it mutable. This is an + important design decision since it allows immutable array fields to share + the internal primitive data array.
+
getField
+
Get the reflection interface for the data.
+
getParent
+
Get the interface for the parent or null if this is the top level + PVStructure.
+
postPut
+
If a postHandler is registered it is called otherwise no action is + taken.
+ NOTE: The implementation of the various data interfaces automatically + call postPut when a field is changed. However this is not true + for a subField of a PVUnion, PVUnionArray, or PVStructureArray. + If a subField of any of these is changed then the code that is making + the modification must call postPut for the PVUnion, PVUnionArray, or PVStructureArray + field. Note also that it is not a good idea to modify a subfield of a PVUnionArray + or a PVStructureArray since it violates the idea of Copy On Write for arrays. +
+
setPostHandler
+
Set the postHandler for the record. Only a single handler can be + registered. + PostHandler is a class that must be implemented by any code that calls setPostHandler. + It's single virtual method. postPut is called whenever PVField::postPut is called. +
+
equals
+
Compare this field with another field. The result will be true only if + the fields have exactly the same field types and if the data values are + equal.
+
dumpValue
+
Method for streams I/O.
+
+ +

PVScalar

+ +

This is the base class for all scalar data.

+
class PVScalar : public PVField {
+public:
+    POINTER_DEFINITIONS(PVScalar);
+    virtual ~PVScalar();
+    typedef PVScalar &reference;
+    typedef const PVScalar& const_reference;
+    const ScalarConstPtr getScalar() const ;
+    template<typename T>
+    T getAs() const;
+ ...
+}
+ +

where

+
+
getScalar
+
Get the introspection interface for the PVScalar.
+
getAs
+
Convert and return the scalar value in the requested type. + Result type is determined from the function template argument + which must be one of the ScalarType enums. + For example: +
+uint32 val = pv->getAs<pvInt>();
+
+
+ +
+ +

PVScalarValue

+ +

The interfaces for primitive data types are:

+
template<typename T>
+class PVScalarValue : public PVScalar {
+public:
+    POINTER_DEFINITIONS(PVScalarValue);
+    typedef T value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    static const ScalarType typeCode;
+
+    virtual ~PVScalarValue() {}
+    virtual T get() const = 0;
+    virtual void put(T value) = 0;
+    std::ostream& dumpValue(std::ostream& o) const;
+    void operator>>=(T& value) const;
+    void operator<<=(T value);
+    template<typename T1>
+    T1 getAs() const;
+    template<typename T1>
+    void putFrom(T1 val);
+ ...
+}
+
+typedef PVScalarValue<boolean> PVBoolean;
+typedef PVScalarValue<int8> PVByte;
+typedef PVScalarValue<int16> PVShort;
+typedef PVScalarValue<int32> PVInt;
+typedef PVScalarValue<int64> PVLong;
+typedef PVScalarValue<uint8> PVUByte;
+typedef PVScalarValue<uint16> PVUShort;
+typedef PVScalarValue<uint32> PVUInt;
+typedef PVScalarValue<uint64> PVULong;
+typedef PVScalarValue<float> PVFloat;
+typedef PVScalarValue<double> PVDouble;
+typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
+typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
+typedef std::tr1::shared_ptr<PVShort> PVShortPtr;
+typedef std::tr1::shared_ptr<PVInt> PVIntPtr;
+typedef std::tr1::shared_ptr<PVLong> PVLongPtr;
+typedef std::tr1::shared_ptr<PVUByte> PVUBytePtr;
+typedef std::tr1::shared_ptr<PVUShort> PVUShortPtr;
+typedef std::tr1::shared_ptr<PVUInt> PVUIntPtr;
+typedef std::tr1::shared_ptr<PVULong> PVULongPtr;
+typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
+typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
+
+
+// PVString is special case, since it implements SerializableArray
+class PVString : public PVScalarValue<std::string>, SerializableArray {
+public:
+    virtual ~PVString() {}
+ ...
+};
+
+
+
+ +

where

+
+
get
+
Get the value stored in the object.
+
put
+
Change the value stored in the object.
+
dumpValue
+
ostream method.
+
operator>>=
+
get operator. For example: +
+double value;
+PVDoublePtr pvDouble;
+...
+pvDouble>>=value;
+
+
+
operator<<=
+
put operator. For example: +
+double value;
+PVDoublePtr pvDouble;
+...
+pvDouble<<=value;
+
+
+
getAs
+
Convert and return the scalar value in the requested type. + Result type is determined from the function template argument + which must be one of the ScalarType enums. + For example: +
+int32 val = pv->getAs<pvInt>>();
+
+
+
putFrom
+
Convert the scalar value in the requested type + and put the value into this PVScalarValue. + The source type is determined from the function template argument + which must be one of the ScalarType enums. + For example: +
+int32 val;
+pv->putFrom<pvInt>(val);
+
+ +
+
+

PVUnion

+

A PVUnion has a single subfield. +The Union introspection interface determines the possible +field types for the subfield. +If it is a variant union then any type is allowed and the +subfield name is normally any. +If it is not a variant union that the Union interface determines +the possible field types and names.

+
+class PVUnion : public PVField
+{
+public:
+    POINTER_DEFINITIONS(PVUnion);
+    virtual ~PVUnion();
+    typedef PVUnion & reference;
+    typedef const PVUnion & const_reference;
+
+    UnionConstPtr getUnion() const;
+    PVFieldPtr get() const;
+    
+    template<typename PVT>
+    std::tr1::shared_ptr<PVT> get() const;
+
+   PVFieldPtr select(int32 index);
+
+    template<typename PVT>
+    std::tr1::shared_ptr<PVT> select(int32 index);
+
+    PVFieldPtr select(std::string const & fieldName);
+
+    template<typename PVT>
+    std::tr1::shared_ptr<PVT> select(std::string const & fieldName);
+
+    int32 getSelectedIndex() const;
+    std::string getSelectedFieldName() const;
+    void set(PVFieldPtr const & value);
+    void set(int32 index, PVFieldPtr const & value);
+    void set(std::string const & fieldName, PVFieldPtr const & value);
+    virtual void serialize(
+        ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
+    PVUnion(UnionConstPtr const & punion);
+    virtual std::ostream& dumpValue(std::ostream& o) const;
+};
+
+
+
getUnion
+
Get the introspection interface.
+
get
+
Get the current field. A template version does the conversion. + NULL is returned if no field is selected or if the caller +' asks for the wrong type. +
+
select
+
Select and get the field by index or name. + A templated version does the conversion. + If the index is out of bounds or the name is not valid this methods throws an exception. + The method set should be used for variant unions rather than select. +
+
getSelectedIndex
+
Get the index of the currently selected field.
+
getSelectedFieldName
+
Get the name of the currently selected field.
+
set
+
Set the field to the argument. If invalid type an exception is thrown. + This should always work for a variant union. +
+
+ +

PVArray

+ +

PVArray is the base interface for all the other PV Array interfaces. It +extends PVField and provides the additional methods:

+
+class PVArray : public PVField, public SerializableArray {
+public:
+    POINTER_DEFINITIONS(PVArray);
+    virtual ~PVArray();
+    virtual ArrayConstPtr getArray() const = 0;
+    virtual void setImmutable();
+    std::size_t getLength() const;
+    virtual void setLength(std::size_t length);
+    std::size_t getCapacity() const;
+    bool isCapacityMutable() const;
+    void setCapacityMutable(bool isMutable);
+    virtual void setCapacity(std::size_t capacity) = 0;
+    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
+ ...
+};
+
+
getArray
+
Get the introspection interface.
+
setImmutable
+
Set the data immutable. Note that this is permanent since there is no + methods to make it mutable.
+
getLength
+
Get the current length. This is less than or equal to the capacity.
+
setLength
+
Set the length. If the PVField is not mutable then an exception is + thrown. If this is greater than the capacity setCapacity is called.
+
getCapacity
+
Get the capacity, i.e. this is the size of the underlying data + array.
+
setCapacity
+
Set the capacity. The semantics are implementation dependent but + typical semantics are as follows: If the capacity is not mutable an + exception is thrown. A new data array is created and data is copied from + the old array to the new array.
+
isCapacityMutable
+
Is the capacity mutable
+
setCapacityMutable
+
Specify if the capacity can be changed.
+
setCapacity
+
Set the capacity.
+
dumpValue
+
ostream method
+
+ + +

PVScalarArray

+ +

PVScalarArray is the base class for scalar array data. PVValueArray is a +template for the various scalar array data classes. There is a class for each +possible scalar type, i. e. PVBooleanArray, ..., PVStringArray.

+
+class PVScalarArray : public PVArray {
+public:
+    POINTER_DEFINITIONS(PVScalarArray);
+    virtual ~PVScalarArray();
+    typedef PVScalarArray &reference;
+    typedef const PVScalarArray& const_reference;
+
+    const ScalarArrayConstPtr getScalarArray() const ;
+
+    template<typename T>
+    void getAs(shared_vector<const T>& out) const
+
+    template<typename T>
+    void putFrom(const shared_vector<const T>& inp)
+
+    void assign(PVScalarArray& pv);
+ ...
+}
+
+ +

where

+
+
getScalarArray
+
Get the introspection interface.
+
getAs
+
Fetch the current value and convert to the requested type. + A copy is made if the requested type does not match the element type. + If the types do match then no copy is made. +
+
putFrom
+
Assign the given value after conversion. + A copy and element-wise conversion is performed unless the element type + of the PVScalarArray matches the type of the provided data. + If the types do match then a new reference to the provided data is kept. +
+
assign
+
Assign the given PVScalarArray's value. + A copy and element-wise conversion is performed unless the element type + of the PVScalarArray matches the type of the provided data. + If the types do match then a new reference to the provided data is kept. +
+
+ +

PVStructure

+ +

The interface for a structure is:

+
class PVStructure : public PVField,public BitSetSerializable {
+public:
+    POINTER_DEFINITIONS(PVStructure);
+    virtual ~PVStructure();
+    typedef PVStructure & reference;
+    typedef const PVStructure & const_reference;
+
+    virtual void setImmutable();
+    StructureConstPtr getStructure() const;
+    const PVFieldPtrArray & getPVFields() const;
+    PVFieldPtr getSubField(std::string const &fieldName) const;
+
+    template<typename PVT>
+    std::tr1::shared_ptr<PVT> getSubField(std::string const &fieldName) const
+
+    PVFieldPtr getSubField(std::size_t fieldOffset) const;
+
+    template<typename PVT>
+    std::tr1::shared_ptr<PVT> getSubField(std::size_t fieldOffset) const
+
+    virtual void serialize(
+        ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
+    virtual void deserialize(
+        ByteBuffer *pbuffer,DeserializableControl *pflusher);
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher,BitSet *pbitSet) const;
+    virtual void deserialize(ByteBuffer *pbuffer,
+        DeserializableControl*pflusher,BitSet *pbitSet);
+    PVStructure(StructureConstPtr const & structure);
+    PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);
+    virtual std::ostream& dumpValue(std::ostream& o) const;
+};
+ +

where

+
+
getStructure
+
Get the introspection interface for the structure.
+
getPVFields
+
Returns the array of subfields. The set of subfields must all have + different field names.
+
getSubField(std::string fieldName)
+
+ Get a subField of a field.d + A non-null result is + returned if fieldName is a field of the PVStructure. The fieldName can be + of the form name.name... + If the field does not exist then a Ptr to a NULL value is returned + without any error message being generated. +
+ Note The template version replaces getBooleanField, etc.
+
+
getSubField(int fieldOffset)
+
Get the field located a fieldOffset, where fieldOffset is relative to + the top level structure. This returns null if the specified field is not + located within this PVStructure. +
+ Note The template version replaces getBooleanField, etc.
+
+
dumpValue
+
Method for streams I/O.
+
+ + +

PVValueArray

+ +

This is a template class plus instances for PVBooleanArray, ..., +PVStringArray.

+
template<typename T>
+class PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> 
+{
+public:
+    POINTER_DEFINITIONS(PVValueArray);
+    typedef T  value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef ::epics::pvData::shared_vector<T> svector;
+    typedef ::epics::pvData::shared_vector<const T> const_svector;
+    static const ScalarType typeCode;
+
+    virtual ~PVValueArray() {}
+    virtual ArrayConstPtr getArray() const
+    std::ostream& dumpValue(std::ostream& o) const;
+    std::ostream& dumpValue(std::ostream& o, size_t index) const;
+    // inherited from PVVectorStorage
+    const_svector view();
+    void swap(const_svector& other);
+    void replace(const const_svector& next);
+    svector reuse();
+    ...
+};
+
+ +

where

+
+
getArray
+
Get the introspection interface.
+
dumpValue
+
Method for streams I/O.
+
view
+
Fetch a read-only view of the current array data.
+
swap
+
+ Callers must ensure that postPut() is called after the last swap() operation. + Before you call this directly, consider using the reuse(), or replace() methods. +
+
replace
+
Discard current contents and replaced with the provided.
+
reuse
+
Remove and return the current array data or an unique copy if shared.
+
+

TBD

+
+
Check for completeness
+
Michael should check that PVScalarArray and PVValueArray + have the correct set of methods and that the descriptions are correct.
+
+ +

PVStructureArray

+ +

The interface for an array of structures is:

+
+template<>
+class PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray>
+{
+public:
+    POINTER_DEFINITIONS(PVStructureArray);
+    typedef PVStructurePtr  value_type;
+    typedef PVStructurePtr* pointer;
+    typedef const PVStructurePtr* const_pointer;
+    typedef PVStructureArray &reference;
+    typedef const PVStructureArray& const_reference;
+    typedef ::epics::pvData::shared_vector<PVStructurePtr> svector;
+    typedef ::epics::pvData::shared_vector<const PVStructurePtr> const_svector;
+
+    virtual ~PVStructureArray() {}
+    virtual ArrayConstPtr getArray() const;
+    virtual size_t getLength();
+    virtual size_t getCapacity();
+    virtual void setCapacity(size_t capacity);
+    virtual void setLength(std::size_t length);
+    virtual StructureArrayConstPtr getStructureArray() const ;
+    virtual std::size_t append(std::size_t number);
+    virtual bool remove(std::size_t offset,std::size_t number);
+    virtual void compress();
+    virtual const_svector view() const;
+    virtual void swap(const_svector &other);
+    virtual void replace(const const_svector &other);
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher) const;
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
+    virtual void deserialize(ByteBuffer *buffer,
+        DeserializableControl *pflusher);
+    virtual std::ostream& dumpValue(std::ostream& o) const;
+    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
+ ...
+}
+

where

+
+
getStructureArray
+
Get the introspection interface shared by each element.
+
compress
+
This moves all null elements and then changes the array capacity. When + done there are no null elements.
+
+ +

The other methods are similar to the methods for other array types. + See PVArray above for details.

+ +

PVUnionArray

+

The interface for an array of unions is:

+
+template<>
+class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
+{
+    typedef detail::PVVectorStorage<PVUnionPtr,PVArray> base_t;
+public:
+    POINTER_DEFINITIONS(PVUnionArray);
+    typedef PVUnionPtr  value_type;
+    typedef PVUnionPtr* pointer;
+    typedef const PVUnionPtr* const_pointer;
+    typedef PVUnionArray &reference;
+    typedef const PVUnionArray& const_reference;
+
+    //TODO: full namespace can be removed along with local typedef 'shared_vector'
+    typedef ::epics::pvData::shared_vector<PVUnionPtr> svector;
+    typedef ::epics::pvData::shared_vector<const PVUnionPtr> const_svector;
+    
+    virtual ~PVValueArray() {}
+    virtual ArrayConstPtr getArray() const;
+    virtual size_t getLength() const;
+    virtual size_t getCapacity() const;
+    virtual void setCapacity(size_t capacity);
+    virtual void setLength(std::size_t length);
+    UnionArrayConstPtr getUnionArray() const;
+    virtual std::size_t append(std::size_t number);
+    virtual bool remove(std::size_t offset,std::size_t number);
+    virtual void compress();
+    virtual const_svector view() const;
+    virtual void swap(const_svector &other);
+    virtual void replace(const const_svector &other);
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher) const;
+    virtual void deserialize(ByteBuffer *buffer,
+        DeserializableControl *pflusher);
+    virtual void serialize(ByteBuffer *pbuffer,
+        SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
+    virtual std::ostream& dumpValue(std::ostream& o) const;
+    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
+};
+
+

where

+
+
getUnionArray
+
Get the introspection interface shared by each element.
+
compress
+
This moves all null elements and then changes the array capacity. When + done there are no null elements.
+
+ +

The other methods are similar to the methods for other array types. + See PVArray above for details.

+ +

PVDataCreate

+ +

PVDataCreate is an interface that provides methods that create PVField +interfaces. A factory is provided that creates PVDataCreate.

+
class PVDataCreate {
+public:
+    static PVDataCreatePtr getPVDataCreate();
+
+    PVFieldPtr createPVField(FieldConstPtr const & field);
+    PVFieldPtr createPVField(PVFieldPtr const & fieldToClone);
+
+    PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
+    PVScalarPtr createPVScalar(ScalarType scalarType);
+    PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
+    template<typename PVT>
+    std::tr1::shared_ptr<PVT> createPVScalar();
+
+    PVStructurePtr createPVStructure(
+        StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
+    PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
+    PVStructurePtr createPVStructure(StructureConstPtr const & structure);
+
+    PVUnionPtr createPVUnion(UnionConstPtr const & punion);
+    PVUnionPtr createPVUnion(PVUnionPtr const & unionToClone);
+    PVUnionPtr createPVVariantUnion();
+
+    PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
+    PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
+    PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const  & scalarArrayToClone);
+    template<typename PVAT>
+    std::tr1::shared_ptr<PVAT> createPVScalarArray();
+
+    PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
+    PVStructureArrayPtr createPVStructureArray(StructureConstPtr const & structure);
+
+    PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
+    PVUnionArrayPtr createPVUnionArray(UnionConstPtr const & punion);
+    PVUnionArrayPtr createPVVariantUnionArray();
+ ...
+};
+
+extern PVDataCreatePtr getPVDataCreate();
+ +

where

+
+
getPVDataCreate
+
The returns the PVDataCreate implementation, which is a singleton.
+
createPVField
+
The PVField is created reusing the Field interface. Two methods are + provided. Each calls the corresponding createPVScalar, createPVArray, or + createPVStructure depending in the type of the last argument.
+
createPVScalar
+
Creates an instance of a PVScalar. Four versions are supplied. The + first is passed an introspection interface. + The second provides the scalarType. + The third provides a PVScalar to clone. + The last is a template version. PVAT must be a valid type. + For example: +
+PVDoublePtr pvDouble = getPVDataCreate()->createPVScalar<PVDouble>();
+
+
+
createPVStructure
+
Create an instance of a PVStructure. + Three methods are provided. + The first uses an array of field names and an array of PVFields to initialize the subfields. + The second initializes the subfields by cloning the fields contained in + structToClone. The newly created subfields will have the same values as the original. + If structToClone is null then the new structure is initialized to have 0 subfields. + The third method uses a previously created structure introspection interface. +
+
createPVUnion
+
Create an instance of a PVUnion. Two methods are provided. + The first uses a previously created union introspection interface. + The second clones an existing PVUnion. +
+
createPVVariantUnion
+
Creates an instance of a variant PVUnion. + This is a union which has a single field which can be any pvData supported type, +
+
createPVScalarArray
+
Create an instance of a PVArray. Four versions are supplied. + The first is passed an introspection interface. + The second provides the elementType. + The third provides a PVScalarArray to clone. + The last is a template version. PVAT must be a valid type. + For example: +
+PVDoubleArrayPtr pvDoubleArray = getPVDataCreate()->createPVScalarArray<PVDoubleArray>();
+
+
+
createPVStructureArray
+
Create a PVStructureArray. + Two versions are provided. + The first is passed a StructureArrayConstPtr. + The second is passed a StructureConstPtr which is used to create a StructureArrayConstPtr. + The argument provides the Structure interface for ALL elements of the PVStructureArray. +
+
createPVUnionArray
+
Create a PVUnionArray. + Two versions are provided. + The first is passed a UnionArrayConstPtr. + The second is passed a UnionConstPtr which is used to create a UnionArrayConstPtr. + The argument provides the Union interface for ALL elements of the PVUnionArray. +
+
createPVVariantUnionArray
+
Create a PVUnionArray. + No arguments are needed. +
+
+ +

standardPVField.h

+ +

A class StandardPVField has methods for creating standard data fields. Like +class StandardField it has two forms of the methods which create a field, one +without properties and one with properties. Again the properties is some +combination of alarm, timeStamp, control, display, and valueAlarm. And just +like StandardField there are methods to create the standard properties. The +methods are:

+
class StandardPVField;
+typedef std::tr1::shared_ptr<StandardPVField> StandardPVFieldPtr;
+
+class StandardPVField : private NoDefaultMethods {
+public:
+    static StandardPVFieldPtr getStandardPVField();
+    ~StandardPVField();
+    PVStructurePtr scalar(ScalarType type,std::string const &properties);
+    PVStructurePtr scalarArray(ScalarType elementType, std::string const &properties);
+    PVStructurePtr structureArray(StructureConstPtr const &structure,std::string const &properties);
+    PVStructurePtr unionArray(UnionConstPtr const &punion,std::string const &properties);
+    PVStructurePtr enumerated(StringArray const &choices);
+    PVStructurePtr enumerated(StringArray const &choices, std::string const &properties);
+ ...
+}
+
+extern StandardPVFieldPtr getStandardPVField();
+
+ +

Conversion

+

There are two facilities for converting between two different PVData +objects:

+
+
Convert
+
This preforms all conversions except for coping subarrays.
+
PVSubArray
+
This copies a subarray from one PVArray to another. + The two arrays must have the same element type.
+
+

convert.h

+ +

NOTE about copying immutable array fields. If an entire immutable array +field is copied to another array that has the same elementType, both offsets +are 0, and the length is the length of the source array, then the shareData +method of the target array is called and the target array is set immutable. +Thus the source and target share the same primitive array.

+ +

This section describes the supported conversions between data types.

+
    +
  • All supported types can be converted to a string. If you ask for a 100 + megabyte array to be converted to a string expect a lot of output.
  • +
  • Conversion from a string to a scalar type.
  • +
  • Conversion from an array of strings to an array of scalar types.
  • +
  • Copy between the following types of scalar PVs +
      +
    • Numeric type to another numeric type
    • +
    • Both have the same type.
    • +
    • Either is a string
    • +
    +
  • +
  • Copy between PVArrays that satisfy one of the following. +
      +
    • Both have the same type.
    • +
    • Either is a string.
    • +
    +
  • +
  • Conversions between numeric scalar types.
  • +
  • Conversion between compatible structures.
  • +
  • A utility method the returns the full field name of a field
  • +
+
+bool operator==(PVField&, PVField&);
+
+static bool operator!=(PVField& a, PVField& b);
+
+bool operator==(const Field&, const Field&);
+bool operator==(const Scalar&, const Scalar&);
+bool operator==(const ScalarArray&, const ScalarArray&);
+bool operator==(const Structure&, const Structure&);
+bool operator==(const StructureArray&, const StructureArray&);
+bool operator==(const Union&, const Union&);
+bool operator==(const UnionArray&, const UnionArray&);
+
+static inline bool operator!=(const Field& a, const Field& b);
+static inline bool operator!=(const Scalar& a, const Scalar& b);
+static inline bool operator!=(const ScalarArray& a, const ScalarArray& b);
+static inline bool operator!=(const Structure& a, const Structure& b);
+static inline bool operator!=(const StructureArray& a, const StructureArray& b);
+static inline bool operator!=(const Union& a, const Union& b);
+static inline bool operator!=(const UnionArray& a, const UnionArray& b);
+
+class Convert;
+typedef std::tr1::shared_ptr<Convert> ConvertPtr;
+
+class Convert {
+public:
+    static ConvertPtr getConvert();
+    ~Convert();
+    void getFullName(std::string * buf,PVFieldPtr const & pvField);
+    bool equals(PVFieldPtr const &a,PVFieldPtr const &b);
+    bool equals(PVField &a,PVField &b);
+    void getString(std::string * buf,PVFieldPtr const & pvField,int indentLevel);
+    void getString(std::string * buf,PVFieldPtr const & pvField);
+    void getString(std::string * buf,PVField const * pvField,int indentLevel);
+    void getString(std::string * buf,PVField const * pvField);
+    std::size_t fromString(
+        PVStructurePtr const &pv,
+        StringArray const & from,
+        std::size_t fromStartIndex = 0);
+    void fromString(PVScalarPtr const & pv, std::string const & from);
+    std::size_t fromString(PVScalarArrayPtr const & pv, std::string const &from);
+    std::size_t fromStringArray(
+        PVScalarArrayPtr const & pv,
+        std::size_t offset, std::size_t length,
+        StringArray const & from,
+        std::size_t fromOffset);
+    std::size_t toStringArray(PVScalarArrayPtr const & pv,
+        std::size_t offset,
+        std::size_t length,
+        StringArray & to,
+        std::size_t toOffset);
+    bool isCopyCompatible(FieldConstPtr const & from, FieldConstPtr const & to);
+    void copy(PVFieldPtr const & from, PVFieldPtr const & to);
+    bool isCopyScalarCompatible(
+        ScalarConstPtr const & from,
+        ScalarConstPtr const & to);
+    void copyScalar(PVScalarPtr const & from, PVScalarPtr const & to);
+    bool isCopyScalarArrayCompatible(
+        ScalarArrayConstPtr const & from,
+        ScalarArrayConstPtr const & to);
+    bool isCopyStructureCompatible(
+        StructureConstPtr const & from, StructureConstPtr const & to);
+    void copyStructure(PVStructurePtr const & from, PVStructurePtr const & to);
+    bool isCopyStructureArrayCompatible(
+        StructureArrayConstPtr const & from, StructureArrayConstPtr const & to);
+    void copyStructureArray(
+        PVStructureArrayPtr const & from, PVStructureArrayPtr const & to);
+    bool isCopyUnionCompatible(
+        UnionConstPtr const & from, UnionConstPtr const & to);
+    void copyUnion(
+        PVUnionPtr const & from, PVUnionPtr const & to);
+    bool isCopyUnionArrayCompatible(
+        UnionArrayConstPtr const & from, UnionArrayConstPtr const & to);
+    void copyUnionArray(
+        PVUnionArrayPtr const & from, PVUnionArrayPtr const & to);
+    int8 toByte(PVScalarPtr const & pv);
+    int16 toShort(PVScalarPtr const & pv);
+    int32 toInt(PVScalarPtr const & pv);
+    int64 toLong(PVScalarPtr const & pv);
+    uint8 toUByte(PVScalarPtr const & pv);
+    uint16 toUShort(PVScalarPtr const & pv);
+    uint32 toUInt(PVScalarPtr const & pv);
+    uint64 toULong(PVScalarPtr const & pv);
+    float toFloat(PVScalarPtr const & pv);
+    double toDouble(PVScalarPtr const & pv);
+    std::string toString(PVScalarPtr const & pv);
+    void fromByte(PVScalarPtr const & pv,int8 from);
+    void fromShort(PVScalarPtr const & pv,int16 from);
+    void fromInt(PVScalarPtr const & pv, int32 from);
+    void fromLong(PVScalarPtr const & pv, int64 from);
+    void fromUByte(PVScalarPtr const & pv,uint8 from);
+    void fromUShort(PVScalarPtr const & pv,uint16 from);
+    void fromUInt(PVScalarPtr const & pv, uint32 from);
+    void fromULong(PVScalarPtr const & pv, uint64 from);
+    void fromFloat(PVScalarPtr const & pv, float from);
+    void fromDouble(PVScalarPtr const & pv, double from);
+    void newLine(std::string * buf, int indentLevel);
+ ...
+}
+
+extern ConvertPtr getConvert();
+
+

newLine is a convenience method for code that implements toString It +generates a newline and inserts blanks at the beginning of the newline.

+ +

pvSubArrayCopy.h

+
+template<typename T>
+void copy(
+    PVValueArray<T> & pvFrom,
+    size_t fromOffset,
+    size_t fromStride,
+    PVValueArray<T> & pvTo,
+    size_t toOffset,
+    size_t toStride,
+    size_t count);
+
+void copy(
+    PVScalarArray & from,
+    size_t fromOffset,
+    size_t fromStride,
+    PVScalarArray & to,
+    size_t toOffset,
+    size_t toStride,
+    size_t count);
+
+void copy(
+    PVStructureArray & from,
+    size_t fromOffset,
+    size_t fromStride,
+    PVStructureArray & to,
+    size_t toOffset,
+    size_t toStride,
+    size_t count);
+
+void copy(
+    PVArray & from,
+    size_t fromOffset,
+    size_t fromStride,
+    PVArray & to,
+    size_t toOffset,
+    size_t toStride,
+    size_t count);
+
+

The last copy is the only one most client need to call. +It either throws an error if the element types do not match or calls the +other copy functions. The arguments are:

+
+
from
+
The source array.
+
fromOffset
+
The offset into the source array.
+
fromStride
+
The interval between source elements.
+
to
+
The destination array. The element type must be the same + as for the source array. If the element type is structure then + the introspection interface for the element types must be the same. +
+
toOffset
+
The offset into the destination array.
+
toStride
+
The interval between destination elements.
+
count
+
The number of elements to copy.
+
+

An exception is thrown if:

+
+
type mismatch
+
The element types for the source and destination differ.
+
immutable
+
The destination array is immutable.
+
capacity immutable
+
The destination array needs to have it's capacity extended + but the capacity is immutable.
+
+ +

src/property

+ +

Definition of Property

+ +

+Often a field named "value" has properties. A record can have multiple value +fields, which can appear in the top level structure of a record or in a +substructure. All other fields in the structure containing a value field are +considered properties of the value field. The fieldname is also the property +name. The value field can have any type, i.e. scalar, scalarArray, or +structure. Typical property fields are timeStamp, alarm, display, control, and +history. The timeStamp is a special case. If it appears anywhere in the +structure hierarchy above a value field it is a property of the value field.

+ +

For example the following top level structure has a single value field. The +value field has properties alarm, timeStamp, and display.

+
structure counterOutput
+    double value
+    alarm_t
+        int severity 0
+        int status 0
+        string message
+    timeStamp_t
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+    display_t
+        double limitLow 0.0
+        double limitHigh 10.0
+        string description "Sample Description"
+        string format "%f"
+        string units volts
+ +

The following example has three value fields each with properties alarm and +timeStamp. Voltage, Current, and Power each have a different alarms but all +share the timeStamp.

+
structure powerSupplyValue
+    double value
+    alarm_t
+        int severity 0
+        int status 0
+        string message
+
+structure powerSupplySimple
+    alarm_t
+        int severity 0
+        int status 0
+        string message
+    timeStamp_t
+        long secondsPastEpoch
+        int nanoseconds
+        int userTag
+    powerSupplyValue_t voltage
+        double value
+        alarm_t
+            int severity 0
+            int status 0
+            string message
+    powerSupplyValue_t power
+        double value
+        alarm_t
+            int severity 0
+            int status 0
+            string message
+    powerSupplyValue_t current
+        double value
+        alarm_t
+            int severity 0
+            int status 0
+            string message
+ +

Standard Properties

+ +

The following field names have special meaning, i.e. support properties for +general purpose clients.

+
+
value
+
This is normally defined since most general purpose clients access this + field. All other fields in the structure support or describe the value + field. The type can any supported type but is usually one of the + following: +
+
scalar
+
Any of the scalar types.
+
scalarArray
+
An array with the elementType being a scalar type
+
enumerated structure
+
A structure that includes fields named index and choices. index + is an int that selects a choice. choices is an array of strings + that defines the complete set of choices.
+
other
+
Other structure or array types can also be defined if clients and + support code agree on the meaning. Some examples are: 1) A + structure defining a 2D matrix, 2) A structure defining an image, + 3) A structure that simulates a remote method, ...
+
+
+
timeStamp
+
The timeStamp. The type MUST be a timeStamp structure. Also if the + PVData structure does not have a timeStamp then a search up the parent + tree is made to find a timeStamp.
+
alarm
+
The alarm. The type MUST be an alarm structure.
+
display
+
A display structure as described below. It provides display + characteristics for the value field.
+
control
+
A control structure as described below. It provides control + characteristics for the value field.
+
history
+
Provides a history buffer for the value field. Note that currently + PVData does not define history support.
+
other
+
Other standard properties can be defined.
+
+ +

In addition a structure can have additional fields that support the value +field but are not recognized by most general purpose client tools. Typical +examples are:

+
+
input
+
A field with support that changes the value field. This can be + anything. It can be a channel access link. It can obtain a value from + hardware. Etc.
+
valueAlarm
+
A field with support that looks for alarm conditions based on the + value.
+
output
+
A field with support that reads the current value and sends it + somewhere else. This can be anything. It can be a channel access link. It + can write a value to hardware. Etc.
+
+ +

The model allows for device records. A device record has structure fields +that that support the PVData data model. For example a powerSupport record can +have fields power, voltage, current that each support the PVData data model. +

+ +

Overview of Property Support

+ +

Except for enumerated, each property has two files: a property.h and a +pvProperty.h . For example: timeStamp.h and pvTimeStamp.h In each case the +property.h file defined methods for manipulating the property data and the +pvProperty.h provides methods to transfer the property data to/from a pvData +structure.

+ +

All methods copy data via copy by value semantics, i.e. not by pointer or by +reference. No property class calls new or delete and all allow the compiler to +generate default methods. All allow a class instance to be generated on the +stack. For example the following is permitted:

+
void example(PVFieldPtr const &pvField) {
+    Alarm alarm;
+    PVAlarm pvAlarm;
+    bool result;
+    result = pvAlarm.attach(pvField);
+    assert(result);
+    Alarm al;
+    al.setMessage(std::string("testMessage"));
+    al.setSeverity(majorAlarm);
+    result = pvAlarm.set(al);
+    assert(result);
+    alarm = pvAlarm.get();
+     ...
+}
+ +

timeStamp

+ +

A timeStamp is represented by the following structure

+
structure timeStamp
+    long secondsPastEpoch
+    int nanoseconds
+    int userTag
+ +

The Epoch is the posix epoch, i.e. Jan 1, 1970 00:00:00 UTC. Both the +seconds and nanoseconds are signed integers and thus can be negative. Since the +seconds is kept as a 64 bit integer, it allows for a time much greater than the +present age of the universe. Since the nanoseconds portion is kept as a 32 bit +integer it is subject to overflow if a value that corresponds to a value that +is greater than a little more than 2 seconds of less that about -2 seconds. The +support code always adjust seconds so that the nanoseconds part is normalized, +i. e. it has is 0<=nanoseconds<nanoSecPerSec..

+ +

Two header files are provided for manipulating time stamps:

+
+
timeStamp.h
+
Defines a time stamp independent of pvData, i.e. it is a generally + useful class for manipulating timeStamps.
+
pvTimeStamp.h
+
A class that can be attached to a time stamp pvData structure. It + provides get and set methods to get/set a TimeStamp as defined by + timeStamp.h
+
+ +

timeStamp.h

+ +

This provides

+
extern int32 milliSecPerSec;
+extern int32 microSecPerSec;
+extern int32 nanoSecPerSec;
+extern int64 posixEpochAtEpicsEpoch;
+
+class TimeStamp {
+public:
+    TimeStamp()
+    :secondsPastEpoch(0), nanoseconds(0), userTag(0) {}
+    TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0,int32 userTag = 0);
+    //default constructors and destructor are OK
+    //This class should not be extended
+    void normalize();
+    void fromTime_t(const time_t &);
+    void toTime_t(time_t &) const;
+    int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
+    int64 getEpicsSecondsPastEpoch() const {
+        return secondsPastEpoch - posixEpochAtEpicsEpoch;
+    }
+    int32 getNanoseconds() const  {return nanoseconds;}
+    int32 getUserTag() const {return userTag;}
+    void setUserTag(int userTag) {this->userTag = userTag;}
+    void put(int64 secondsPastEpoch,int32 nanoseconds = 0) {
+        this->secondsPastEpoch = secondsPastEpoch;
+        this->nanoseconds = nanoseconds;
+        normalize();
+    }
+    void put(int64 milliseconds);
+    void getCurrent();
+    double toSeconds() const ;
+    bool operator==(TimeStamp const &) const;
+    bool operator!=(TimeStamp const &) const;
+    bool operator<=(TimeStamp const &) const;
+    bool operator< (TimeStamp const &) const;
+    bool operator>=(TimeStamp const &) const;
+    bool operator> (TimeStamp const &) const;
+    static double diff(TimeStamp const & a,TimeStamp const & b);
+    TimeStamp & operator+=(int64 seconds);
+    TimeStamp & operator-=(int64 seconds);
+    TimeStamp & operator+=(double seconds);
+    TimeStamp & operator-=(double seconds);
+    int64 getMilliseconds(); // milliseconds since epoch
+ ...
+}
+ +

where

+
+
TimeStamp()
+
The default constructor. Both seconds and nanoseconds are set to 0.
+
TimeStamp(int64 secondsPastEpoch,int32 nanoseconds = 0)
+
A constructor that gives initial values to seconds and nanoseconds.
+
normalize
+
Adjust seconds and nanoseconds so that + 0<=nanoseconds<nanoSecPerSec.
+
fromTime_t
+
Set time from standard C time.
+
toTime_t
+
Convert timeStamp to standard C time.
+
getSecondsPastEpoch
+
Get the number of seconds since the epoch.
+
getEpicsSecondsPastEpoch
+
Get the number of EPICS seconds since the epoch. EPICS uses Jan 1, 1990 + 00:00:00 UTC as the epoch.
+
getNanoseconds
+
Get the number of nanoseconds. This is always normalized.
+
getUserTag
+
Get the userTag.
+
setUserTag
+
Set the userTag.
+
put(int64 secondsPastEpoch,int32 nanoseconds = 0)
+
Set the timeStamp value. If necessary it will be normalized.
+
put(int64 milliseconds)
+
Set the timeStamp with a value the is the number of milliSeconds since + the epoch.
+
getCurrent()
+
Set the timeStamp to the current time.
+
toSeconds()
+
Convert the timeStamp to a value that is the number of seconds since + the epocj
+
operator =
+
operator!=
+
operator<=
+
operator<
+
operator>=
+
operator>
+
Standard C++ operators.
+
diff
+
diff = a - b
+
getMilliseconds
+
Get the number of milliseconds since the epoch.
+
+ +

The TimeStamp class provides arithmetic operations on time stamps. The +result is always kept in normalized form, which means that the nano second +portion is 0≤=nano<nanoSecPerSec. Note that it is OK to have timeStamps +for times previous to the epoch.

+ +

TimeStamp acts like a primitive. It can be allocated on the stack and the +compiler is free to generate default methods, i.e. copy constructor, assignment +constructor, and destructor.

+ +

One use for TimeStamp is to time how long a section of code takes to +execute. This is done as follows:

+
    TimeStamp startTime;
+    TimeStamp endTime;
+    ...
+    startTime.getCurrent();
+    // code to be measured for elapsed time
+    endTime.getCurrent();
+    double time = TimeStamp::diff(endTime,startTime);
+ +

pvTimeStamp.h

+
class PVTimeStamp {
+public:
+    PVTimeStamp();
+    //default constructors and destructor are OK
+    //This class should not be extended
+    //returns (false,true) if pvField(isNot, is valid timeStamp structure
+    bool attach(PVFieldPtr const &pvField);
+    void detach();
+    bool isAttached();
+    // following throw logic_error if not attached to PVField
+    // a set returns false if field is immutable
+    void get(TimeStamp &) const;
+    bool set(TimeStamp const & timeStamp);
+};
+ +

where

+
+
PVTimeStamp
+
The default constructor. Attach must be called before get or set can be + called.
+
attach
+
Attempts to attach to pvField It returns (false,true) if a timeStamp + structure is found. It looks first at pvField itself and if is not an + appropriate pvData structure but the field name is value it looks up the + parent structure tree.
+
detach
+
Detach from the pvData structure.
+
isAttached
+
Is there an attachment to a timeStamp structure?
+
get
+
Copies data from the pvData structure to a TimeStamp. An exception is + thrown if not attached to a pvData structure.
+
set
+
Copies data from TimeStamp to the pvData structure. An exception is + thrown if not attached to a pvData structure.
+
+ +

alarm

+ +

An alarm structure is defined as follows:

+
structure alarm
+    int severity
+    int status
+    string message
+ +

Note that neither severity or status is defined as an enumerated structure. +The reason is performance, i. e. prevent passing the array of choice strings +everywhere. The file alarm.h provides the choice strings. Thus all code that +needs to know about alarms share the exact same choice strings.

+ +

Two header files are provided for manipulating alarms:

+
+
alarm.h
+
Defines an alarm independent of pvData, i.e. it is a generally useful + class for manipulating alarms.
+
pvAlarm.h
+
A class that can be attached to an alarm pvData structure. It provides + get and set methods to get/set alarm data as defined by alarm.h
+
+ +

alarm.h

+
enum AlarmSeverity {
+ noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
+};
+
+enum AlarmStatus {
+    noStatus,deviceStatus,driverStatus,recordStatus,
+    dbStatus,confStatus,undefinedStatus,clientStatus
+};
+
+
+class AlarmSeverityFunc {
+public:
+    static AlarmSeverity getSeverity(int value);
+    static StringArrayPtr getSeverityNames();
+};
+
+class AlarmStatusFunc {
+public:
+    static AlarmStatus getStatus(int value);
+    static StringArrayPtr getStatusNames();
+};
+
+class Alarm {
+public:
+    Alarm();
+    //default constructors and destructor are OK
+    std::string getMessage();
+    void setMessage(std::string const &value);
+    AlarmSeverity getSeverity() const;
+    void setSeverity(AlarmSeverity value);
+    AlarmStatus getStatus() const;
+    void setStatus(AlarmStatus value);
+};
+ +

Alarm Severity defines the possible alarm severities:

+
+
getSeverity
+
Get the alarm severity corresponding to the integer value.
+
getSeverityNames
+
Get the array of severity choices.
+
+ +

Alarm Status defines the possible choices for alarm status:

+
+
getStatus
+
Get the alarm status corresponding to the integer value.
+
getStatusNames
+
Get the array of status choices.
+
+ +

Alarm has the methods:

+
+
Alarm
+
The constructor. It sets the severity to no alarm and the message to + "".
+
getMessage
+
Get the message.
+
setMessage
+
Set the message.
+
getSeverity
+
Get the severity.
+
setSeverity
+
Set the severity.
+
getStatus
+
Get the status.
+
setStatus
+
Set the status.
+
+ +

pvAlarm.h

+
class PVAlarm {
+public:
+    PVAlarm() : pvSeverity(0),pvMessage(0) {}
+    //default constructors and destructor are OK
+    //returns (false,true) if pvField(isNot, is valid enumerated structure
+    //An automatic detach is issued if already attached.
+    bool attach(PVFieldPtr const &pvField);
+    void detach();
+    bool isAttached();
+    // each of the following throws logic_error is not attached to PVField
+    // set returns false if field is immutable
+    void get(Alarm & alarm) const;
+    bool set(Alarm const & alarm); 
+};
+ +

where

+
+
PVAlarm
+
The default constructor. Attach must be called before get or set can be + called.
+
attach
+
Attempts to attach to pvField It returns (false,true) if it found an + appropriate pvData structure. It looks first a pvField itself and if is + not an appropriate pvData structure but the field name is value it looks + to see if the parent structure has an appropriate sub structure.
+
detach
+
Just detaches from the pvData structure.
+
isAttached
+
Is there an attachment to an alarm structure?
+
get
+
Copies data from the pvData structure to an Alarm. An exception is + thrown if not attached to a pvData structure.
+
set
+
Copies data from Alarm to the pvData structure. An exception is thrown + if not attached to a pvData structure.
+
+ +

control

+ +

Control information is represented by the following structure

+
structure control
+    double limitLow
+    double limitHigh
+    double minStep
+ +

Two header files are provided for manipulating control:

+
+
control.h
+
Defines control independent of pvData, i.e. it is a generally useful + class for manipulating control.
+
pvControl.h
+
A class that can be attached to an control pvData structure. It + provides get and set methods to get/set control data as defined by + control.h
+
+ +

control.h

+
class Control {
+public:
+    Control();
+    //default constructors and destructor are OK
+    double getLow() const;
+    double getHigh() const;
+    double getMinStep() const;
+    void setLow(double value);
+    void setHigh(double value);
+    void setMinStep(double value);
+};
+ +

where

+
+
Control
+
The default constructor.
+
getLow
+
Get the low limit.
+
getHigh
+
Get the high limit.
+
setLow
+
Set the low limit.
+
setHigh
+
Set the high limit.
+
setMinStep
+
Set the minimum step size.
+
getMinStep
+
Get he minimum step size.
+
+ +

pvControl.h

+
class PVControl {
+public:
+    PVControl();
+    //default constructors and destructor are OK
+    //returns (false,true) if pvField(isNot, is valid enumerated structure
+    //An automatic detach is issued if already attached.
+    bool attach(PVFieldPtr const &pvField);
+    void detach();
+    bool isAttached();
+    // each of the following throws logic_error is not attached to PVField
+    // set returns false if field is immutable
+    void get(Control &) const;
+    bool set(Control const & control);
+};
+ +

where

+
+
PVControl
+
The default constructor. Attach must be called before get or set can be + called.
+
attach
+
Attempts to attach to pvField It returns (false,true) if it found an + appropriate pvData structure. It looks first a pvField itself and if is + not an appropriate pvData structure but the field name is value it looks + to see if the parent structure has an appropriate sub structure.
+
detach
+
Just detaches from the pvData structure.
+
isAttached
+
Is there an attachment to a control structure?
+
get
+
Copies data from the pvData structure to a Control. An exception is + thrown if not attached to a pvData structure.
+
set
+
Copies data from Control to the pvData structure. An exception is + thrown if not attached to a pvData structure.
+
+ +

display

+ +

Display information is represented by the following structure

+
structure display
+    double limitLow
+    double limitHigh
+    string description
+    string format
+    string units
+ +

Two header files are provided for manipulating display:

+
+
display.h
+
Defines display independent of pvData, i.e. it is a generally useful + class for manipulating display.
+
pvDisplay.h
+
A class that can be attached to an display pvData structure. It + provides get and set methods to get/set display data as defined by + display.h
+
+ +

display.h

+
class Display {
+public:
+    Display();
+    //default constructors and destructor are OK
+    double getLow() const;
+    double getHigh() const;
+    void setLow(double value);
+    void setHigh(double value);
+    std::string getDescription() const;
+    void setDescription(std::string const &value);
+    std::string getFormat() const;
+    void setFormat(std::string const &value);
+    std::string getUnits() const;
+    void setUnits(std::string const &value);
+};
+ +

where

+
+
Control
+
The default constructor.
+
getLow
+
Get the low limit.
+
getHigh
+
Get the high limit.
+
setLow
+
Set the low limit.
+
setHigh
+
Set the high limit.
+
getDescription
+
Get the description.
+
setDescription
+
Set the description.
+
getFormat
+
Get the format.
+
setFormat
+
Set the format.
+
getUnits
+
Get the units.
+
setUnits
+
Set the units.
+
+ +

pvDisplay.h

+
class PVDisplay {
+public:
+    PVDisplay()
+    : pvDescription(0),pvFormat(),pvUnits(),pvLow(),pvHigh() {}
+    //default constructors and destructor are OK
+    //An automatic detach is issued if already attached.
+    bool attach(PVFieldPtr const&pvField); 
+    void detach();
+    bool isAttached();
+    // each of the following throws logic_error is not attached to PVField
+    // a set returns false if field is immutable
+    void get(Display &) const;
+    bool set(Display const & display);
+};
+ +

where

+
+
PVDisplay
+
The default constructor. Attach must be called before get or set can be + called.
+
attach
+
Attempts to attach to pvField It returns (false,true) if it found an + appropriate pvData structure. It looks first a pvField itself and if is + not an appropriate pvData structure but the field name is value it looks + to see if the parent structure has an appropriate sub structure.
+
detach
+
Just detaches from the pvData structure.
+
isAttached
+
Is there an attachment to a display structure?
+
get
+
Copies data from the pvData structure to a Display. An exception is + thrown if not attached to a pvData structure.
+
set
+
Copies data from Display to the pvData structure. An exception is + thrown if not attached to a pvData structure.
+
+ +

pvEnumerated.h

+ +

An enumerated structure is a structure that has fields:

+
structure
+    int index
+    string[] choices
+ +

For enumerated structures a single header file pvEnumerted.h is available

+
class PVEnumerated {
+public:
+    PVEnumerated();
+    //default constructors and destructor are OK
+    //This class should not be extended
+    //returns (false,true) if pvField(isNot, is valid enumerated structure
+    //An automatic detach is issued if already attached.
+    bool attach(PVFieldPtr const &pvField);
+    void detach();
+    bool isAttached();
+    // each of the following throws logic_error is not attached to PVField
+    // a set returns false if field is immutable
+    bool setIndex(int32 index);
+    int32 getIndex();
+    std::string getChoice();
+    bool choicesMutable();
+    StringArrayPtr const & getChoices();
+    int32 getNumberChoices();
+    bool setChoices(StringArray &choices);
+};
+ +

where

+
+
PVEnumerated
+
The default constructor. Attach must be called before any get or set + method can be called.
+
attach
+
Attempts to attach to pvField It returns (false,true) if pvField (is + not, is) an enumerated structure.
+
detach
+
Just detaches from the pvData structure.
+
isAttached
+
Is there an attachment to an enumerated structure?
+
setIndex
+
Set the index field in the pvData structure. An exception is thrown if + not attached to a pvData structure.
+
getIndex
+
Get the index field in the pvData structure.
+
getChoice
+
Get the std::string value corresponding to the current index field in the + pvData structure. An exception is thrown if not attached to a pvData + structure.
+
choicesMutable
+
Can the choices be changed? Note that this is often true. An exception + is thrown if not attached to a pvData structure.
+
getChoices
+
Get the array of choices. An exception is thrown if not attached to a + pvData structure.
+
getNumberChoices
+
Get the number of choices. An exception is thrown if not attached to a + pvData structure.
+
setChoices
+
Change the choices. An exception is thrown if not attached to a pvData + structure.
+
+ + +

src/factory

+ +

Directory factory has code that implements everything described by the files +in directory pv

+ +

TypeFunc.cpp implements the functions for the enums defined in +pvIntrospecct.h

+ +

FieldCreateFactory.cpp automatically creates a single instance of +FieldCreate and implements getFieldCreate.

+ +

PVDataCreateFactory.cpp automatically creates a single instance of +PVDataCreate and implements getPVDataCreate.

+ + +

Convert.cpp automatically creates a single instance of Convert and +implements getConvert.

+ +

Other files implement PVData base classes

+ +

src/misc

+ +

Overview

+ +

This package provides utility code:

+
+
bitSet.h
+
An implementation of BitSet that can be serialized.
+
byteBuffer.h
+
Used to serialize objects.
+
destroyable.h
+
Provides method destroy.
+
epicsException.h
+
Exception with stack trace.
+
event.h
+
Signal and wait for an event.
+
executor.h
+
Provides a thread for executing commands.
+
localStaticLock.h
+
TBD Matej can You explain what this does?
+
lock.h
+
Support for locking and unlocking.
+
messageQueue.h
+
Support for queuing messages to give to requesters.
+
noDefaultMethods.h
+
When privately extended prevents compiler from implementing default + methods.
+
queue.h
+
A queue implementation that allows the latest queue element to continue + to be used when no free element is available.
+
requester.h
+
Allows messages to be sent to a requester.
+
serialize.h
+
Support for serializing objects.
+
serializeHelper.h
+
More support for serializing objects.
+
sharedPtr.h
+
Defines POINTER_DEFINITIONS.
+
sharedVector.h
+
Like std::vector except that std::shared_ptr is used for + the data array.
+
status.h
+
A way to pass status information to a client.
+
templateMeta.h
+
TBD Michael can You provide an explanation?
+
thread.h
+
Provides thread support.
+
timeFunction.h
+
Time how long a function call requires.
+
timer.h
+
An implementation of Timer that does not require an object to be + created for each timer request.
+
typeCast.h
+
TBD Michael can You provide an explanation?
+
+ +

Note that directory testApp/misc has test code for all the classes in misc. +The test code also can be used as examples.

+ +

bitSet.h

+ +

This is adapted from the java.util.BitSet. bitSet.h is:

+
+class BitSet;
+typedef std::tr1::shared_ptr<BitSet> BitSetPtr;
+
+class BitSet : public Serializable {
+public:
+    static BitSetPtr create(uint32 nbits);
+    BitSet();
+    BitSet(uint32 nbits);
+    virtual ~BitSet();
+    void flip(uint32 bitIndex);
+    void set(uint32 bitIndex);
+    void clear(uint32 bitIndex);
+    void set(uint32 bitIndex, bool value);
+    bool get(uint32 bitIndex) const;
+    void clear();
+    int32 nextSetBit(uint32 fromIndex) const;
+    int32 nextClearBit(uint32 fromIndex) const;
+    bool isEmpty() const;
+    uint32 cardinality() const;
+    uint32 size() const;
+    BitSet& operator&=(const BitSet& set);
+    BitSet& operator|=(const BitSet& set);
+    BitSet& operator^=(const BitSet& set);
+    BitSet& operator=(const BitSet &set);
+    void or_and(const BitSet& set1, const BitSet& set2);
+    bool operator==(const BitSet &set) const;
+    bool operator!=(const BitSet &set) const;
+    virtual void serialize(
+        ByteBuffer *buffer,SerializableControl *flusher) const;
+    virtual void deserialize(
+        ByteBuffer *buffer,DeserializableControl *flusher);
+private:
+};
+
+std::ostream& operator<<(std::ostream& o, const BitSet& b);
+
+ +

where

+
+
BitSet()
+
Creates a bitSet of initial size 64 bits. All bits initially false.
+
BitSet(uint32 nbits)
+
Creates a bitSet with the initial of the specified number of bits. All + bits initially false.
+
~BitSet()
+
Destructor.
+
flip(uint32 bitIndex)
+
Flip the specified bit.
+
set(uint32 bitIndex)
+
Set the specified bit true.
+
clear(uint32 bitIndex)
+
Set the specified bit false.
+
set(uint32 bitIndex, bool value)
+
Set the specified bit to value.
+
get(uint32 bitIndex)
+
Return the state of the specified bit.
+
clear()
+
Set all bits to false.
+
nextSetBit(uint32 fromIndex)
+
Get the index of the next true bit beginning with the specified + bit.
+
nextClearBit(uint32 fromIndex)
+
Get the index of the next false bit beginning with the specified + bit.
+
isEmpty()
+
Return (false,true) if (at least one bit true, all bits are false)
+
cardinality()
+
Return the number of true bits.
+
size()
+
Returns the number of bits of space actually in use.
+
operator&=(const BitSet& set)
+
Performs a logical and of this target bit set with the argument bit + set. This bit set is modified so that each bit in it has the value true + if and only if it both initially had the value true and the corresponding + bit in the bit set argument also had the value.
+
operator|=(const BitSet& set)
+
Performs a logical or of this target bit set with the argument bit + set.
+
operator^=(const BitSet& set)
+
Performs a logical exclusive or of this target bit set with the + argument bit set.
+
operator=(const BitSet &set)
+
Assignment operator.
+
or_and(const BitSet& set1, const BitSet& set2)
+
Perform AND operation on set1 and set2, and then OR this bitSet with + the result.
+
operator==(const BitSet &set)
+
Does this bitSet have the same values as the argument.
+
operator!=(const BitSet &set)
+
Is this bitSet different than the argument.
+
virtual void serialize(ByteBuffer *buffer,SerializableControl *flusher) + const;
+
Serialize the bitSet
+
virtual void deserialize(ByteBuffer *buffer,DeserializableControl + *flusher);
+
Deserialize the bitSet.
+
+ +

byteBuffer.h

+ +

A ByteBuffer is used to serialize and deserialize primitive data. File +byteBuffer.h is:

+
class ByteBuffer {
+public:
+    ByteBuffer(std::size_t size, int byteOrder = EPICS_BYTE_ORDER)
+    ~ByteBuffer();
+    void setEndianess(int byteOrder);
+    const char* getBuffer();
+    void clear();
+    void flip();
+    void rewind();
+    std::size_t getPosition();
+    void setPosition(std::size_t pos);
+    std::size_t getLimit();
+    void setLimit(std::size_t limit);
+    std::size_t getRemaining();
+    std::size_t getSize();
+    template<typename T>
+    void put(T value)
+    template<typename T>
+    void put(std::size_t index, T value);
+    template<typename T>
+    T get()
+    template<typename T>
+    T get(std::size_t index)
+    void put(const char* src, std::size_t src_offset, std::size_t count);
+    void get(char* dest, std::size_t dest_offset, std::size_t count);
+    template<typename T>
+    inline void putArray(T* values, std::size_t count)
+    template<typename T>
+    inline void getArray(T* values, std::size_t count)
+    template<typename T>
+    inline bool reverse();
+    inline void align(std::size_t size)
+    void putBoolean(  bool value);
+    void putByte   (  int8 value);
+    void putShort  ( int16 value);
+    void putInt    ( int32 value);
+    void putLong   ( int64 value);
+    void putFloat  ( float value);
+    void putDouble (double value);
+    void putBoolean(std::size_t  index,  bool value);
+    void putByte   (std::size_t  index,  int8 value);
+    void putShort  (std::size_t  index, int16 value);
+    void putInt    (std::size_t  index, int32 value);
+    void putFloat  (std::size_t  index, float value);
+    void putDouble (std::size_t  index, double value);
+    bool getBoolean();
+    int8 getByte   ();
+    int16 getShort  ();
+    int32 getInt    ();
+    int64 getLong   ();
+    float getFloat  ();
+    double getDouble ();
+    bool getBoolean(std::size_t  index);
+    int8 getByte   (std::size_t  index);
+    int16 getShort  (std::size_t  index);
+    int32 getInt    (std::size_t  index);
+    int64 getLong   (std::size_t  index);
+    float getFloat  (std::size_t  index);
+    double getDouble (std::size_t  index);
+    const char* getArray();
+ ...
+};
+ +

destroyable.h

+
class Destroyable  {
+public:
+    POINTER_DEFINITIONS(Destroyable);
+    virtual void destroy() = 0;
+    virtual ~Destroyable() {};
+};
+ +

epicsException.h

+
/*
+ * Throwing exceptions w/ file+line# and, when possibly, a stack trace
+ *
+ * THROW_EXCEPTION1( std::bad_alloc );
+ *
+ * THROW_EXCEPTION2( std::logic_error, "my message" );
+ *
+ * THROW_EXCEPTION( mySpecialException("my message", 42, "hello", ...) );
+ *
+ * Catching exceptions
+ *
+ * catch(std::logic_error& e) {
+ *   fprintf(stderr, "%s happened\n", e.what());
+ *   PRINT_EXCEPTION2(e, stderr);
+ *   cout<<SHOW_EXCEPTION(e);
+ * }
+ *
+ * If the exception was not thrown with the above THROW_EXCEPTION*
+ * the nothing will be printed.
+ */
+ +

event.h

+ +

This class provides coordinates activity between threads. One thread can +wait for the event and the other signals the event.

+
class Event;
+typedef std::tr1::shared_ptr<Event> EventPtr;
+ 
+class Event {
+public:
+    POINTER_DEFINITIONS(Event);
+    explicit Event(bool = false);
+    ~Event();
+    void signal();
+    bool wait (); /* blocks until full */
+    bool wait ( double timeOut ); /* false if empty at time out */
+    bool tryWait (); /* false if empty */
+...
+}; 
+ +

where

+
+
Event
+
The constructor. The initial value can be full or empty. The normal + first state is empty.
+
signal
+
The event becomes full. The current or next wait will complete.
+
wait
+
Wait until event is full or until timeout. The return value is + (false,true) if the wait completed because event (was not, was) full. A + false value normally means that that a timeout occurred. It is also + returned if an error occurs or because the event is being deleted.
+
tryWait
+
returns (false,true) if the event is (empty,full)
+
+ +

executor.h

+ +

An Executor is a thread that can execute commands. The user can request that +a single command be executed.

+
+class Command;
+class Executor;
+typedef std::tr1::shared_ptr<Command> CommandPtr;
+typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
+    
+class Command {
+public:
+    POINTER_DEFINITIONS(Command);
+    virtual ~Command(){}
+    virtual void command() = 0;
+private: 
+    CommandPtr next;
+    friend class Executor;
+}; 
+ 
+class Executor :  public Runnable{
+public: 
+    POINTER_DEFINITIONS(Executor);
+    Executor(std::string threadName,ThreadPriority priority);
+    ~Executor();
+    void execute(CommandPtr const &node);
+    virtual void run();
+ ...
+};
+ +

Command is a class that must be implemented by the code that calls execute. +It contains the single virtual method command, which is the command to +execute.

+ +

Executor has the methods:

+
+
Executor
+
The constructor. A thread name and priority must be specified.
+
~Executor
+
The destructor. If any commands remain in the execute list they are not + called. All ExecutorNodes that have been created are deleted.
+
execute
+
Request that command be executed. If it is already on the run list + nothing is done.
+
+ +

localStaticLock.h

+
+extern epics::pvData::Mutex& getLocalStaticInitMutex();
+
+static class MutexInitializer {
+  public:
+    MutexInitializer ();
+    ~MutexInitializer ();
+} localStaticMutexInitializer; // Note object here in the header.
+
+

TBD Matej will explain.

+ +

lock.h

+
+typedef epicsMutex Mutex;
+
+class Lock : private NoDefaultMethods {
+public:
+    explicit Lock(Mutex &pm);
+    ~Lock();
+    void lock();
+    void unlock();
+    bool tryLock();
+    bool ownsLock() ;
+ ...
+};
+ +

Lock is as easy to use as Java synchronize. To protect some object just +create a Mutex for the object and then in any method to be synchronized just +have code like:

+
class SomeClass {
+private
+    Mutex mutex;
+ ...
+public
+    SomeClass() : mutex(Mutex()) {}
+ ...
+    void method()
+    {
+        Lock xx(mutex);
+        ...
+    }
+
+ +

The method will take the lock when xx is created and release the lock when +the current code block completes.

+ +

Another example of Lock is initialization code that must initialize only +once. This can be implemented as follows:

+
    static void init(void) {
+        static Mutex mutex;
+        Lock guard(mutex);
+        if(alreadyInitialized) return;
+        // initialization
+    }
+

Lock has a private variable:

+
+bool locked;
+
+and improves efficiency by checking the local variable before calling the +mutex methods. This is not thread safe if any methods are called by a thread other than +the thread that created the Lock. +

It is thread safe if used as follows:

+
+{
+    Lock guard(mutex);
+    ...
+    /* the following can optionally be called
+    guard.unlock();
+    guard.lock();
+    */
+}
+
+

It is not thread safe if used as follows:

+
+class SomeClass
+{
+private:
+    Mutex mutex;
+    Lock lock;
+public:
+    SomeClass: lock(mutex) {}
+    ...
+    void someMethod() {
+        lock.unlock();
+        ...
+    }
+    ...
+};
+
+

It is only safe if all methods of Lock, including ~Lock(), +are called by the same thread. +

+ +

messageQueue.h

+ +

Definitions

+ +

A messageQueue is for use by code that wants to handle messages without +blocking higher priority threads.

+
class MessageNode;
+class MessageQueue;
+typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
+typedef std::vector<MessageNodePtr> MessageNodePtrArray;
+typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
+
+class MessageNode {
+public:
+    std::string getMessage() const;
+    MessageType getMessageType() const;
+    void setMessageNull();
+};
+
+class MessageQueue : public Queue<MessageNode> {
+public:
+    POINTER_DEFINITIONS(MessageQueue);
+    static MessageQueuePtr create(int size);
+    MessageQueue(MessageNodePtrArray &nodeArray);
+    virtual ~MessageQueue();
+    MessageNodePtr &get();
+    // must call release before next get
+    void release();
+    // return (false,true) if message (was not, was) put into queue
+    bool put(std::string message,MessageType messageType,bool replaceLast);
+    bool isEmpty() ;
+    bool isFull() ;
+    int getClearOverrun();
+ ...
+};
+ +

A messageNode is a class with two public data members:

+
+
getMessage
+
The message.
+
getMessageType
+
The message type.
+
setMessageNull
+
Set the message to be a null string.
+
+ +

A messageQueue is an interface with public methods:

+
+
MessageQueue
+
The constructor. The queue size must be specified.
+
~MessageQueue
+
The destructor.
+
put
+
Put a new message into the queue. False is returned if the queue was + full and true otherwise. If replaceLast is true then the last message is + replaced with this message.
+
get
+
Get the oldest queue element. If the queue is empty null is returned. + Before the next get can be issued release must be called.
+
release
+
Release the queue element returned by the last get.
+
isEmpty
+
Is the queue empty?
+
isFull
+
Is the queue full?
+
getClearOverrun
+
Get the number of times put has been called but no free element is + available.
+
+ +

Look at miscTest/testMessageQueue.cpp for an example.

+ +

noDefaultMethods.h

+ +

If a class privately extends this class then the compiler can not create any +of the following: default constructor, default copy constructor, or default +assignment constructor.

+
/* This is based on Item 6 of
+ * Effective C++, Third Edition, Scott Meyers
+ */
+    class NoDefaultMethods {
+    protected:
+    // allow by derived objects
+    NoDefaultMethods(){};
+    ~NoDefaultMethods(){}
+    private:
+    // do not implement
+    NoDefaultMethods(const NoDefaultMethods&);
+    NoDefaultMethods & operator=(const NoDefaultMethods &);
+    };
+ +

queue.h

+ +

This provides a bounded queue. When the queue is +full the user code is expected to keep using the current element until a new +free element becomes available.

+
+template <typename T>
+class Queue
+{   
+public:
+    POINTER_DEFINITIONS(Queue);
+    typedef std::tr1::shared_ptr<T> queueElementPtr;
+    typedef std::vector<queueElementPtr> queueElementPtrArray;
+    Queue(queueElementPtrArray &);
+    virtual ~Queue();
+    void clear();
+    int capacity();
+    int getNumberFree();
+    int getNumberUsed();
+    queueElementPtr & getFree();
+    void setUsed(queueElementPtr const &element);
+    queueElementPtr & getUsed();
+    void releaseUsed(queueElementPtr const &element);
+ ...
+};
+ +

testApp/misc/testQueue.cpp provides an example of how to define a queue.

+ +

The queue methods are:

+
+
clear
+
Make the queue empty.
+
getNumberFree
+
Get the number of free elements in the queue.
+
capacity
+
Get the capacity, i.e. the maximum number of elements the queue can + hold.
+
getNumberFree
+
Get the number of free elements.
+
getNumberUsed
+
Get the number of elements used.
+
getFree
+
Get the next free element. Null is returned if no free elements are + available. If a non null value is returned then the element belongs to + the caller until setUsed is called.
+
setUsed
+
Set a queue element used. This must be the element returned by the last + call to getFree.
+
getUsed
+
Get the next used element of null if no more used elements are + available.
+
releaseUsed
+
Set a queue element free. This must be the element returned by the last + call to getUsed.
+
+ +

A queue is created as follows:

+
   class MyClass;
+   typedef MyQueueElement<MyClass> MyElement;
+   typedef MyQueue<MyClass> MyQueue;
+   int numElement = 5;
+   ...
+   MyClass *array[numElements];
+   for(int i=0; i<numElements; i++) {
+        array[i] = new MyClass();
+   }
+   MyQueue *queue = new MyQueue(array,numElements);
+ +

A producer calls getFree and setUsed via code like the following:

+
   MyClass *getFree() {
+       MyElement *element = queue->getFree();
+       if(element==0) return 0;
+       return element->getObject();
+  }
+ +

A consumer calls getUsed and releaseUsed via code like the following:

+
     while(true) {
+         MyElement *element = queue->getUsed();
+         if(element==0) break;
+         MyClass *myClass = element->getObject();
+         // do something with myClass
+         queue->releaseUsed(element);
+     }
+ +

requester.h

+ +

Requester is present so that when +errors are found there is someplace to send a message. +At one time PVField extended Requester but it no longer does. +Requester is, however, used by pvAccess. +

+
+class Requester;
+typedef std::tr1::shared_ptr<Requester> RequesterPtr;
+
+enum MessageType {
+   infoMessage,warningMessage,errorMessage,fatalErrorMessage
+};
+
+extern std::string getMessageTypeName(MessageType messageType);
+extern const size_t messageTypeCount;
+class Requester {
+public:
+    POINTER_DEFINITIONS(Requester);
+    virtual ~Requester(){}
+    virtual std::string getRequesterName() = 0;
+    virtual void message(std::string const & message,MessageType messageType) = 0;
+};
+ +

where

+
+
+
MessageType
+
Type of message.
+
messageTypeName
+
An array of strings of the message type names, i.e. + std::string("info"),std::string("warning"),std::string("error"),std::string("fatalError").
+
getRequesterName
+
Returns the requester name.
+
message
+
Gives a message to the requester.
+
+ +

serialize.h

+
+    class SerializableControl;
+    class DeserializableControl;
+    class Serializable;
+    class BitSetSerializable;
+    class SerializableArray;
+    class BitSet;
+    class Field;
+
+    class SerializableControl {
+    public:
+        virtual ~SerializableControl(){}
+        virtual void flushSerializeBuffer() =0;
+        virtual void ensureBuffer(std::size_t size) =0;
+        virtual void alignBuffer(std::size_t alignment) =0;
+        virtual void cachedSerialize(
+            std::tr1::shared_ptr<const Field> const & field,
+            ByteBuffer* buffer) = 0;
+    };
+
+    class DeserializableControl {
+    public:
+        virtual ~DeserializableControl(){}
+        virtual void ensureData(std::size_t size) =0;
+        virtual void alignData(std::size_t alignment) =0;
+        virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
+            ByteBuffer* buffer) = 0;
+    };
+
+    class Serializable {
+    public:
+        virtual ~Serializable(){}
+        virtual void serialize(ByteBuffer *buffer,
+            SerializableControl *flusher) const = 0;
+        virtual void deserialize(ByteBuffer *buffer,
+            DeserializableControl *flusher) = 0;
+    };
+
+    class BitSetSerializable {
+    public:
+        virtual ~BitSetSerializable(){}
+        virtual void serialize(ByteBuffer *buffer,
+            SerializableControl *flusher,BitSet *bitSet) const = 0;
+        virtual void deserialize(ByteBuffer *buffer,
+            DeserializableControl *flusher,BitSet *bitSet) = 0;
+    };
+
+
+    class SerializableArray : virtual public Serializable {
+    public:
+        virtual ~SerializableArray(){}
+        virtual void serialize(ByteBuffer *buffer,
+            SerializableControl *flusher, std::size_t offset,
+            std::size_t count) const = 0;
+    };
+ +

serializeHelper.h

+ +

This is a helper class for serialization, which is required for sending and +receiving pvData over the network.

+
class SerializeHelper : public NoDefaultMethods {
+public:
+    static void writeSize(int s, ByteBuffer* buffer,
+        SerializableControl* flusher);
+    static int readSize(ByteBuffer* buffer,
+        DeserializableControl* control);
+    static void serializeString(const std::string& value,
+        ByteBuffer* buffer,SerializableControl* flusher);
+    static void serializeSubstring(const std::string& value, int offset,
+        int count, ByteBuffer* buffer,
+        SerializableControl* flusher);
+    static std::string deserializeString(ByteBuffer* buffer,
+        DeserializableControl* control);
+ ...
+};
+ +

where

+
+
writeSize
+
Serialize the size.
+
readSize
+
Deserialize the size.
+
serializeString
+
Serialize a std::string.
+
serializeSubstring
+
Serialize a substring.
+
deserializeString
+
Deserialize a string.
+
+ +

sharedPtr.h

+
+#define POINTER_DEFINITIONS(clazz) \
+    typedef std::tr1::shared_ptr<clazz> shared_pointer; \
+    typedef std::tr1::shared_ptr<const clazz> const_shared_pointer; \
+    typedef std::tr1::weak_ptr<clazz> weak_pointer; \
+    typedef std::tr1::weak_ptr<const clazz> const_weak_pointer;
+ +

sharedVector.h

+

+shared_vector is a holder for a contiguous piece of memory. +Data is shared, but offset and length are not. +This allows one vector to have access to only a subset of a piece of memory. +

+

+shared_vector differs from std::vector as follows:

+
+
Differences in behavior
+
+ shared_vector models const-ness like shared_ptr. + An equivalent of 'const std::vector<E>' is + 'const shared_vector<const E>'. + However, it is also possible to have 'const shared_vector<E>' + analogous to 'E* const' and 'shared_vector<const E>>' + which is analogous to 'const E*'.i +
+ Copying a shared_vector, by construction or assignment, does not copy + its contents. + Modifications to one such "copy" effect all + associated shared_vector instances. +
+ std::vector::reserve(N) has no effect if N<=std::vector::capacity(). + However, like resize(), shared_vector<E>::reserve() has the side effect + of always calling make_unique(). +
+
Parts of std::vector interface not implemented
+
+ Mutating methods insert(), erase(), shrink_to_fit(), emplace(), and emplace_back() are not implemented. +
+ shared_vector does not model an allocator which is bound to the object. Therefore the get_allocator() method and the allocator_type typedef are not provided. +
+ The assign() method and the related constructor are not implemented at this time. +
+ The comparison operators are not implemented at this time. +
+
Parts not found in std::vector
+
+ shared_vector has additional constructors from raw pointers and shared_ptr s. + The copy constructor and assignment operator allow implicit castings + from type 'shared_vector<T>' to 'shared_vector<const T>>'. + To facilitate safe modification the methods unique() and make_unique() are provided + The slice() method selects a sub-set of the shared_vector. + The low level accessors dataPtr(), dataOffset(), dataCount(), and dataTotal(). +
+
+ + +
+template<typename E, class Enable = void& class shared_vector;
+
+template<typename E, class Enable&
+class shared_vector : public detail::shared_vector_base<E&
+{
+    typedef detail::shared_vector_base<E& base_t;
+    typedef typename detail::call_with<E&::type param_type;
+    typedef typename meta::strip_const<E&::type _E_non_const;
+public:
+    typedef E value_type;
+    typedef E& reference;
+    typedef typename meta::decorate_const<E&::type& const_reference;
+    typedef E* pointer;
+    typedef typename meta::decorate_const<E&::type* const_pointer;
+    typedef E* iterator;
+    typedef std::reverse_iterator<iterator& reverse_iterator;
+    typedef typename meta::decorate_const<E&::type* const_iterator;
+    typedef std::reverse_iterator<const_iterator& const_reverse_iterator;
+    typedef ptrdiff_t difference_type;
+    typedef size_t size_type;
+
+    typedef E element_type;
+    typedef std::tr1::shared_ptr<E& shared_pointer_type;
+
+    // allow specialization for all E to be friends
+    template<typename E1, class Enable1& friend class shared_vector;
+
+    shared_vector() :base_t();
+    explicit shared_vector(size_t c)
+        :base_t(new _E_non_const[c], 0, c);
+    shared_vector(size_t c, param_type e);
+    template<typename A&
+    shared_vector(A v, size_t o, size_t c) :base_t(v,o,c);
+    template<typename E1&
+    shared_vector(const std::tr1::shared_ptr<E1&& d, size_t o, size_t c);
+    template<typename A, typename B&
+    shared_vector(A d, B b, size_t o, size_t c);
+    shared_vector(const shared_vector& o) :base_t(o);
+    
+    size_t max_size() const;
+    size_t capacity() const;
+    void reserve(size_t i);
+    void resize(size_t i);
+    void resize(size_t i, param_type v);
+    void make_unique();
+    
+    iterator begin() const;
+    iterator end() const;
+    reverse_iterator rbegin() const;
+    reverse_iterator rend() const;
+    reference front() const;
+    reference back() const;
+
+    void push_back(param_type v);
+    void pop_back();
+    pointer data() const;
+    reference operator[](size_t i) const;
+    reference at(size_t i) const;
+    // inherited from detail
+    shared_vector_base& operator=(const shared_vector_base& o);
+    void swap(shared_vector_base& o);
+    void clear();
+    bool unique() const;
+    size_t size() const;
+    bool empty() const;
+    void slice(size_t offset, size_t length=(size_t)-1);
+    const std::tr1::shared_ptr<E&& dataPtr();
+    size_t dataOffset() const;
+    size_t dataCount() const;
+    size_t dataTotal() const;
+
+where +
+
shared_vector
+
Several flavors of constructor are provided. The most commonly used is: +
+shared_vector(size_t c);
+       
+ This creates a shared_vector of the specified size/ +
+
max_size
+
The maximum size the C++ implementation allows, i.e., + the maximum possible capacity. + Note that units are number of elements not number of bytes. +
+
capacity
+
The current capacity.
+
reserve
+
Set array capacity.
+
resize
+
Grow or shrink array. + It the second argument is given it is the value to assign to + and new elements. +
+
make_unique
+
Ensure (by copying) that this shared_vector + is the sole owner of the data array. +
+
begin,...,rend
+
Standard iterators.
+
front
+
Return a reference to the first element.
+
back
+
Return a reference to the last element.
+
push_back
+
Add an element to the end of the array.
+
pop_back
+
Remove an element from the end of the array.
+
data
+
Return a pointer to the raw array.
+
operator[](size_t i)
+
Return a reference to the specified element.
+
at
+
Like the previous except that it throws a range-error if + the specified element is out of range.
+
operator=
+
Copy an existing shared_vector.
+
swap
+
Swap the contents of this vector with another.
+
clear
+
Clear contents.
+
unique
+
returns (true,false) if data (is not, is) shared.
+
size
+
Number of elements visible through this vector.
+
empty
+
Is the number of elements zero?
+
slice
+
Reduce the view of this shared_vector.
+
dataPtr
+
A read-only shared_ptr to the array.
+
dataOffset
+
Offset in the data array of first visible element.
+
dataCount
+
Number of visible elements between dataOffset and end of data.
+
dataTotal
+
The total number of elements between dataOffset and the end of data
+
+

TBD +Michael should decide if this is the correct set of methods to describe. +Also he should check for correct descriptions. +

+ + +

status.h

+ +

Status provides a way to pass status back to client code:

+
class Status : public epics::pvData::Serializable {
+    public:
+   enum StatusType { 
+         /** Operation completed successfully. */
+         STATUSTYPE_OK,
+         /** Operation completed successfully, but there is a warning message. */
+         STATUSTYPE_WARNING,
+         /** Operation failed due to an error. */
+         STATUSTYPE_ERROR,
+         /** Operation failed due to an unexpected error. */
+         STATUSTYPE_FATAL
+    }; 
+    static const char* StatusTypeName[];
+    static Status Ok;
+    Status();
+    Status(StatusType type, std::string const & message);
+    Status(StatusType type, std::string const & message, std::string stackDump);
+    ~Status()
+    StatusType getType() const;
+    std::string getMessage() const;
+    std::string getStackDump() const;
+    bool isOK() const;
+    bool isSuccess() const;
+    void serialize(ByteBuffer *buffer, SerializableControl *flusher) const;
+    void deserialize(ByteBuffer *buffer, DeserializableControl *flusher);
+    void dump(std::ostream& o) const;
+};
+ +

The Status methods are:

+
+
StatusType
+
An enum for the status type.
+
getType
+
Get the statusType.
+
getMessage
+
Get a message explaining the error.
+
getStackDump
+
Get a stack dump.
+
+ +

The StatusCreate methods are:

+
+
getStatusOK
+
Get a singleton that returns StatusType.OK and a null message and + stackDump.
+
createStatus
+
Create a new Status.
+
deserializeStatus
+
Use this method instead of Status.deserialize(), since this allows OK + status optimization.
+
+

templateMeta.h

+

TBD Michael will explain.

+ +

thread.h

+ +

ThreadPriority

+
enum ThreadPriority {
+    lowestPriority,
+    lowerPriority,
+    lowPriority,
+    middlePriority,
+    highPriority,
+    higherPriority,
+    highestPriority
+};
+ +

Thread

+
+class Thread;
+typedef std::tr1::shared_ptr<Thread> ThreadPtr;
+typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
+
+class Runnable {
+public:
+    virtual void run() = 0;
+};
+
+class Thread;
+
+class Thread : public epicsThread, private NoDefaultMethods {
+public:
+    Thread(
+        std::string name,
+        ThreadPriority priority,
+        Runnable *runnableReady,
+        epicsThreadStackSizeClass stkcls=epicsThreadStackSmall);
+    ~Thread();
+ ...
+};
+ +

Runnable must be implement by code that wants to be run via a thread. It has +one virtual method: run. Run is the code that is run as a thread. When run +completes it can not be restarted. If code wants to delete a thread then it +MUST arrange that the run returns before the thread can be deleted. An +exception is thrown if run remains active when delete is called.

+ +

Thread has the methods:

+
+
Thread
+
The constructor. A thread name and priority must be specified. The run + methods of runnable is executed. When the run methods returns the thread + will no longer be active but the client code must still delete the + thread.
+
~Thread
+
The destructor. This is called as the result of: +
    delete pthread;
+
+
+ +

timeFunction.h

+ +

TimeFunction is a facility that measures the average number of seconds a +function call requires. When timeCall is called, it calls function in a loop. +It starts with a loop of one iteration. If the total elapsed time is less then +.1 seconds it increases the number of iterations by a factor of 10. It keeps +repeating until the elapsed time is greater than .1 seconds. It returns the +average number of seconds per call.

+
class TimeFunctionRequester;
+class TimeFunction;
+typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
+typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
+        
+class TimeFunctionRequester {
+public:              
+    POINTER_DEFINITIONS(TimeFunctionRequester);
+    virtual ~TimeFunctionRequester(){}
+    virtual void function() = 0;
+};  
+
+    
+class TimeFunction {
+public:    
+    POINTER_DEFINITIONS(TimeFunction);
+    TimeFunction(TimeFunctionRequesterPtr const & requester);
+    ~TimeFunction(); 
+    double timeCall();
+ ...
+};      
+ +

TimeFunctionRequester must be implemented by code that wants to time how +long a function takes. It has the single method:

+
+
function
+
This is the function.
+
+ +

TimeFunction has the methods:

+
+
TimeFunction
+
Constructor.
+
~TimeFunction
+
Destructor.
+
timeCall
+
Time how long it takes to execute the function. It starts by calling + the function one time. If it takes < 1 seconds to doubles the number + of times to call the function. It repeats this until it takes at least + one second to call it ntimes.
+
+ +

timer.h

+ +

This provides a general purpose timer. It allows a user callback to be +called after a delay or periodically.

+
class TimerCallback;
+class Timer;
+typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
+typedef std::tr1::shared_ptr<Timer> TimerPtr;
+
+
+class TimerCallback {
+public:
+    POINTER_DEFINITIONS(TimerCallback);
+    TimerCallback();
+    virtual ~TimerCallback(){}
+    virtual void callback() = 0;
+    virtual void timerStopped() = 0;
+};
+
+class Timer : private Runnable {
+public:
+    POINTER_DEFINITIONS(Timer);
+    Timer(std::string threadName, ThreadPriority priority);
+    virtual ~Timer();
+    virtual void run();
+    void scheduleAfterDelay(
+        TimerCallbackPtr const &timerCallback,
+        double delay);
+    void schedulePeriodic(
+        TimerCallbackPtr const &timerCallback,
+        double delay,
+        double period));
+    void cancel(TimerCallbackPtr const &timerCallback);
+    bool isScheduled(TimerCallbackPtr const &timerCallback);
+    void dump(std::ostream& o);
+ ...
+};
+ +

TimerCallback must be implemented by the user. It has the following methods: +

+
+
callback
+
This is called when a timer expires. This is called with no locks held. + When called a delay timer is no longer on the queue but a periodic timer + is on a queue. Thus the callback for a delay timer can issue a new + schedule request but a periodic timer must not. Note the explanation of + TimerNode.cancel below.
+
timerStopped
+
Timer.stop was called when a timer request was queued. or if the timer + is stopped and a schedule request is made.
+
+ +

In order to schedule a callback client code must allocate a TimerNode It can +be used to schedule multiple callbacks. It has the methods:

+
+
TimerNode
+
The constructor. User code must create a TimeNode in order to call a + schedule method.
+
~TimerNode
+
The destructor. This is called as a result of the client calling: +
    delete timerNode;
+
+
cancel
+
This is called to cancel a timer request. If a callback has been + dequeued but the callback not called when cancel is called then a + callback may still happen. New schedule requests can be made after a + cancel request has been made.
+
isScheduled
+
Is the timerNode scheduled to be called.
+
+ +

Timer has the methods:

+
+
Timer
+
The constructor.
+
~Timer
+
The destructor. The queue is emptied and TimerCallback.timerStopped is + called for each element of the queue.
+
scheduleAfterDelay
+
A request to schedule a callback after a delay specified in + seconds.
+
schedulePeriodic
+
Schedule a periodic callback.
+
+

typeCast.h

+

TBD Michael will explain.

+ +

src/pvMisc

+ +

bitSetUtil.h

+ +

The following is also provided:

+
class BitSetUtil : private NoDefaultMethods {
+public:
+    static bool compress(BitSet const &bitSet,PVStructure const &pvStructure);
+};
+ +

This provides functions that operate on a BitSet for a PVStructure. It +currently has only one method:

+
+
compress
+
Compress the bits in a BitSet related to a structure.
+ For each structure: +
    +
  1. If the bit for the structure is set then the bit for all subfields + of the structure are cleared.
  2. +
  3. If the bit for the structure is not set but all immediate subfields + have their bit set then the bit for the structure is set and the bits + for all subfields are cleared.
  4. +
+ Note that this is a recursive algorithm. That is if every immediate + subfield has it's offset bit set then the bits for ALL fields that reside + in the structure will be cleared.
+
Channel Access can call this before sending data. It can then pass + entire structures if the structure offset bit is set.
+
+ +

src/copy and src/monitor

+

copy and monitor are not used in this project. +They are intended for use by pvAccess and by pvAccess servers. +They are provided with this project because the code depends only on +pvData itself. +

+

This document describes C++ specific code. + +pvRequest.html +provides a language independent overview of copy and monitor. +

+

+NOTE:pvRequest.html must be updated since it is based on an earlier version of pvCopy that +had knowledge of PVRecord. The C++ version was implemented in pvDatabaseCPP +and the Java version on pvIOCJava. +At present only the C++ version of the new API for pvCopy is implemented. +

+

Copy provides:

+
+
createRequest
+
+ The Channel create methods in pvAccess all have an argument + PVStructure pvRequest.
+ Given an ascii string createRequest creates a PVStructure that provides + a pvData representation of the information from the ascii string. + It is this structure that can be passed to the channel create methods.
+ The information in a pvRequest selects an arbitrary subset of the + fields in a top level structure that resides in the server. + In addition options can be specified. Both global and field specific + options can be specified. +
+
pvCopy
+
This is a facility used by channel providers. + It provides client specific code that manages a copy of an arbitrary + subset of the fields in a top level structure that resides in the + provider. It also allows provider access to options specified + by the client. +
+
+Monitor provides: +
+
monitor
+
This is support code for channel providers that implement channel + monitor. It, together with the queue facility, provides support for + monitor queues. +
+
monitorPlugin
+
This is support for implementing monitor plugins. + A monitor plugin can be developed that has no knowledge + of pvAccess but only pvData. +
+
+

src/copy

+

copy provides the ability to create a structure that has +a copy of an arbitrary subset of the fields in an existing top level +structure. In addition it allows global options and field specific options. +It has two main components: createRequest and pvCopy. +Given a string createRequest creates a pvRequest, which is a PVStructure +that has the format expected by pvCopy. +

+ +

createRequest

+

This is mainly used by pvAccess clients. Given a request string it creates +a pvRequest structure that can be passed to the pvAccess create methods. +In turn pvAccess passes the pvRequest to a local channel provider which +then passes it to pvCopy. +

+

The definition of the public members is:

+
+class CreateRequest {
+...
+     static CreateRequestPtr create();
+     virtual PVStructurePtr createRequest(std::string const &request);
+     std::string getMessage();
+};
+
+

An example of how it is used is:

+
+CreateRequestPtr createRequest = CreateRequest::create();
+PVStructurePtr pvRequest = createRequest->createRequest(request);
+if(pvRequest==NULL) {
+    std::string error = createRequest->getMessage();
+    // take some action
+} else {
+    //success do something
+}
+
+

pvCopy

+

The definition of the public members is:

+
+class epicsShareClass PVCopyTraverseMasterCallback
+{
+...
+    virtual void nextMasterPVField(PVFieldPtr const &pvField);
+};
+
+class class epicsShareClass PVCopy
+{
+...
+    static PVCopyPtr create(
+        PVStructurePtr const &pvMaster,
+        PVStructurePtr const &pvRequest,
+        std::string const & structureName);
+    virtual void destroy();
+    PVStructurePtr getPVMaster();
+    void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback);
+    StructureConstPtr getStructure();
+    PVStructurePtr createPVStructure();
+    size_t getCopyOffset(PVFieldPtr const  &masterPVField);
+    size_t getCopyOffset(
+        PVStructurePtr const  &masterPVStructure,
+        PVFieldPtr const  &masterPVField);
+     PVFieldPtr getMasterPVField(std::size_t structureOffset);
+     void initCopy(
+        PVStructurePtr const  &copyPVStructure,
+        BitSetPtr const  &bitSet);
+     void updateCopySetBitSet(
+        PVStructurePtr const  &copyPVStructure,
+        BitSetPtr const  &bitSet);
+    void updateCopyFromBitSet(
+        PVStructurePtr const  &copyPVStructure,
+        BitSetPtr const  &bitSet);
+    void updateMaster(
+        PVStructurePtr const  &copyPVStructure,
+        BitSetPtr const  &bitSet);
+    PVStructurePtr getOptions(std::size_t fieldOffset);
+    std::string dump();
+...
+};
+
+where +
+
PVCopyTraverseMasterCallback::nextMasterPVField
+
+ PVCopyTraverseMasterCallback is a callback which must + be implemented by the code that uses pvCopy, normally + the channel provider. It has the single method nextMasterPVField +
+ nextMasterPVField is called for each field in the master + as a result of a call to traverseMaster. +
+
create
+
+ This is the method for creating a PVCopy instance.
+
+
pvMaster
+
the top level structure managed by the server.
+
pvRequest
+
selects the set of subfields desired + and options for each field.
+
structureName
+
the name for the top level of any PVStructure created. +
+
+
+
getPVMaster
+
+ Gets the top level structure from pvMaster. +
+
traverseMaster
+
+ Traverse all fields of the top level structure of pvMaster. + For each field the callback is called. +
+
getStructure
+
+ Get the introspection interface for a PVStructure for e copy. +
+
createPVStructure
+
Create a copy instance. + Monitors keep a queue of monitor elements. + Since each element needs a PVStructure, multiple top level structures + will be created. +
+
getCopyOffset
+
Given a field in pvMaster. + return the offset in copy for the same field. + A value of std::string::npos means that the copy does not have this field. + Two overloaded methods are provided. The first is called if + the field of master is not a structure. The second is for + subfields of a structure. +
+
getMasterPVField
+
+ Given a offset in the copy get the corresponding field in pvMaster. +
+
initCopy
+
+ Initialize the fields in copyPVStructure + by giving each field the value from the corresponding field in pvMaster. + bitSet will be set to show that all fields are changed. + This means that bit set will have the value {0}. +
+
updateCopySetBitSet
+
+ Set all fields in copyPVStructure to the value of the corresponding field + in pvMaster. Each field that is changed has it's corresponding + bit set in bitSet. +
+
updateCopyFromBitSet
+
+ For each set bit in bitSet set the field in copyPVStructure to the value + of the corresponding field in pvMaster. +
+
updateMaster
+
+ For each set bit in bitSet set the field in pvMaster to the value + of the corresponding field in copyPVStructure. + +
+
getOptions
+
+ Get the options for the field at the specified offset. + A NULL is returned if no options were specified for the field. + If options were specified,PVStructurePtr is + a structure with a set of PVString subfields that specify name,value + pairs. name is the subField name and value is the subField value. +
+
+ + + + +

src/monitor

+

This consists of two components:

+
+
monitor
+
Used by code that implements pvAccess monitors.
+
monitorPlugin
+
Code that provides special semantics for monitors.
+
+

monitor

+
+class MonitorElement {
+    MonitorElement(PVStructurePtr const & pvStructurePtr);
+    PVStructurePtr pvStructurePtr;
+    BitSetPtr changedBitSet;
+    BitSetPtr overrunBitSet;
+};
+
+class Monitor {
+    virtual Status start() = 0;
+    virtual Status stop() = 0;
+    virtual MonitorElementPtr poll() = 0;
+    virtual void release(MonitorElementPtr const & monitorElement) = 0;
+};
+
+class MonitorRequester : public virtual Requester {
+    virtual void monitorConnect(Status const & status,
+        MonitorPtr const & monitor, StructureConstPtr const & structure) = 0;
+    virtual void monitorEvent(MonitorPtr const & monitor) = 0;
+    virtual void unlisten(MonitorPtr const & monitor) = 0;
+};
+
+

monitorElement

+

MonitorElement holds the data for one element of a monitor queue. +It has the fields: +

+
+
pvStructurePtr
+
A top level structure with data values at the time the monitors occurs.
+
changedBitSet
+
Shows which fields have changed since the previous monitor.
+
overrunBitSet
+
Shows which fields have changed more than once since the previous monitor.
+
+

monitorElement queue

+

+A queue of monitor elements must be implemented by any channel provider that implements +Channel::createMonitor. +For an example implementation look at pvDatabaseCPP. +It has the following: +

+
+typedef Queue<MonitorElement> MonitorElementQueue;
+typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
+
+class MultipleElementQueue :
+    public ElementQueue
+{
+public:
+    POINTER_DEFINITIONS(MultipleElementQueue);
+    virtual ~MultipleElementQueue(){}
+    MultipleElementQueue(
+        MonitorLocalPtr const &monitorLocal,
+        MonitorElementQueuePtr const &queue,
+        size_t nfields);
+    virtual void destroy(){}
+    virtual Status start();
+    virtual Status stop();
+    virtual bool dataChanged();
+    virtual MonitorElementPtr poll();
+    virtual void release(MonitorElementPtr const &monitorElement);
+...
+};
+
+

Monitor

+

Monitor must be implemented by any channel provider that implements +Channel::createMonitor. +Remote PVAccess also implements Monitor on the client side. +Note that each client has it's own queue that is not shared with other client. +

+

Monitor has the following methods:

+
+
start
+
+ Start monitoring. + This will result in a an initial monitor that has the current value + of all fields. +
+
stop
+
+ Stop monitoring. +
+
poll
+
+ Called to get a monitor element. + If no new elements are available then a null pointer is returned. +
+
release
+
+ Release the monitor element. + The caller owns the monitor element between the calls to poll and release. +
+
+

MonitorRequester

+

This must be implemented by a pvAccess client. +It has the methods:

+
+
monitorConnect
+
+ A monitor has either connected of disconnected. +
+
monitorEvent
+
+ A new monitor element is available. +
+
unlisten
+
+ The channel is going away. The client cam no longer access the monitor. +
+
+ +

monitorPlugin

+
+class MonitorPlugin
+{
+    virtual std::string const & getName() = 0;
+    virtual bool causeMonitor(
+        PVFieldPtr const &pvField,
+        PVStructurePtr const &pvTop,
+        MonitorElementPtr const &monitorElement) = 0;
+    virtual void monitorDone(
+        MonitorElementPtr const &monitorElement);
+    virtual void startMonitoring();
+    virtual void stopMonitoring();
+    virtual void beginGroupPut();
+    virtual void endGroupPut();
+};
+
+class MonitorPluginCreator
+{
+    virtual MonitorPluginPtr create(
+        FieldConstPtr const &field,
+        StructureConstPtr const &top,
+        PVStructurePtr const &pvFieldOptions) = 0;
+     virtual std::string const & getName() = 0;
+}
+
+class MonitorPluginManager
+{
+    static MonitorPluginManagerPtr get();
+    bool addPlugin(
+         std::string const &pluginName,
+         MonitorPluginCreatorPtr const &creator);
+    MonitorPluginCreatorPtr findPlugin(std::string const &pluginName);
+    void showNames();
+};
+
+
+

MonitorPlugin

+

MonitorPlugin must be implemented by the plugin implementation. +It has methods:

+
+
getName
+
Get the name of the plugin.
+
causeMonitor
+
+ Should the value of pvField cause a monitor to be raised. + pvField and pvTop are fields in the top level structure + being monitored. monitorElement has the top level structure + for the copy
. + The implementation should not modify the fields in the structure + being monitored. + Called with pvTop locked. +
+
monitorDone
+
+ Called just before monitorElement will be given to client. + The plugin can change the data values and bitSets in monitorElement. + Called with pvTop unlocked. +
+
startMonitoring
+
+ Monitoring is starting. +
+
stopMonitoring
+
+ Monitoring is being stopped. +
+
beginGroupPut
+
+ A set of puts is starting. + Called with pvTop locked. +
+
endGroupPut
+
+ The set of puts is complete. + Called with pvTop locked. +
+
+

MonitorPluginCreator

+

MonitorPluginCreator must also be implemented by the plugin implementation. +It is called for each field instance that has options of the from +[plugin=name...] where name is the name of the plugin. +Note that a plugin instance will belong to a single client. +It has methods:

+
+
getName
+
Get the name of the plugin.
+
create
+
+ Create a new plugin instance. + If the arguments are not compatible with the plugin a NULL shared pointer is + returned.
+ pvFieldOptions is + a structure with a set of PVString subfields that specify name,value + pairs. name is the subField name and value is the subField value.
+ Note that a plugin will below to a single client. +
+
+

MonitorPluginManager

+

MonitorPluginManager has the methods:

+
+
get
+
+ MonitorPluginManager is a singleton. + The first call to get will create the single instance. + Further calls will return the single instance. +
+
addPlugin
+
+ Add a new plugin. +
+
findPlugin
+
+ Find a plugin. A NULL shared pointer is returned if it has not been added. +
+
showNames
+
+ Show the names of all plugins that have been added. +
+
+

NOTE: +Should the method causeMonitor +have arguments pvField and pvTop +be defined so that they can not be modified. +This would be possible if the following was defined: +

+
+typedef std::tr1::shared_ptr<const PVField> PVFieldConstPtr;
+typedef std::tr1::shared_ptr<const PVStructure> PVStructureConstPtr;
+
+then the definition for causeMonitor could be: +
+virtual bool causeMonitor(
+        PVFieldConstPtr const &pvField,
+        PVStructureConstPtr const &pvTop,
+        MonitorElementPtr const &monitorElement) = 0;
+
+But just adding these definitions is not sufficient. +In addition all methods defined in pvDataCPP must be checked. +In particular many of the methods in Convert must have +their arguments modified. +Big job. +

monitorPlugin example

+

Example Plugin Overview

+

This section describes an example plugin that:

+
    +
  • Only raises monitors when a field changes value.
    + If no plugin is provided + the default is to raise a monitor when a put is issued to a field.
  • +
  • Optionally a change will not raise a monitor.
    + The change will, however, + appear if a put to another field raise a monitor.
  • +
+

As an example assume that a channel provided by pvAccess has a top level structure +that represents a power supply.

+
+structure powerSupply
+    structure alarm
+    structure timeStamp
+    structure power
+       double value
+       structure alarm
+       structure display
+    structure voltage
+       double value
+       structure alarm
+       structure display
+    structure current
+       double value
+       structure alarm
+       structure display
+
+

A pvAccess client wants to create a monitor on the powerSupply as follows: +The client wants a top level structure that looks like: +

+
+structure powerSupply
+    structure alarm
+    structure timeStamp
+    structure power
+       double value
+    structure voltage
+       double value
+    structure current
+       double value
+
+In addition the client wants monitors to occur only when one of the monitored +fields changes value but not just because a put occurred. +Also if only the timeStamp changes value then that should not cause a monitor. +

The example monitor plugin implements the semantics the +client wants. It can be attached to any field via the following options: +

+
+[plugin=onChange,raiseMonitor=value]
+
+This plugin will trigger a monitor for the field only if the field changes +value. In addition value equals false means do not raise a monitor +for changes to this field. +But if a change to another field does cause a monitor the change to this field +will be passed to the client. +

+Assume that the client has already connected to the channel. +The client can then issue the commands:

+
+std::string request("field(alarm[plugin=onChange]");
+request += ",timeStamp[plugin=onChange,raiseMonitor=false]";
+request += ",power.value[plugin=onChange";
+request += ",voltage.value[plugin=onChange";
+request += ",current.value[plugin=onChange";
+
+PVStructurePtr pvRequest = createRequest->createRequest(request);
+
+MonitorPtr monitor = channel->createMonitor(monitorRequester,pvRequest);
+
+

Example Plugin Code

+

The header file to create the example has the definition:

+
+class ExampleMonitorPlugin{
+public:
+    static void create();
+};
+
+

The implementation is:

+
+class OnChangePlugin : public MonitorPlugin
+{
+public:
+    virtual ~OnChangePlugin(){}
+    OnChangePlugin() {}
+    bool init(
+        FieldConstPtr const &field,
+        StructureConstPtr const &top,
+        PVStructurePtr const &pvFieldOptions)
+   {
+        pvField = getPVDataCreate()->createPVField(field);
+        raiseMonitor = true;
+        if(pvFieldOptions!=NULL) {
+            PVStringPtr pvString =
+                pvFieldOptions->getSubField<PVString>("raiseMonitor");
+                if(pvString!=NULL) {
+                    std::string value = pvString->get();
+                    if(value.compare("false")==0) raiseMonitor = false;
+                }
+        }
+        return true;
+   }
+   virtual std::string &getName(){return pluginName;}
+   virtual bool causeMonitor(
+        PVFieldPtr const &pvNew,
+        PVStructurePtr const &pvTop,
+        MonitorElementPtr const &monitorElement)
+   {
+       bool isSame = convert->equals(pvNew,pvField);
+       if(isSame) return false;
+       convert->copy(pvNew,pvField);
+       return raiseMonitor;
+   }
+private:
+   PVFieldPtr pvField;
+   bool raiseMonitor;
+};
+class OnChangePluginCreator : public MonitorPluginCreator
+{
+public:
+    virtual std::string &getName(){return pluginName;}
+    virtual MonitorPluginPtr create(
+        FieldConstPtr const &field,
+        StructureConstPtr const &top,
+        PVStructurePtr const &pvFieldOptions)
+   {
+       OnChangePluginPtr plugin(new OnChangePlugin());
+       bool result = plugin->init(field,top,pvFieldOptions);
+       if(!result) return MonitorPluginPtr();
+       return plugin;
+   }
+
+};
+
+void ExampleMonitorPlugin::create()
+{
+    static OnChangePluginCreatorPtr plugin;
+    static Mutex mutex;
+    Lock xx(mutex);
+    if(plugin==NULL) {
+        plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
+        MonitorPluginManager::get()->addPlugin(pluginName,plugin);
+    }
+}
+
+ + +
+ +