Files
cdev-1.7.2n/doc/html/cdevIntroduction.html
2022-12-13 12:44:04 +01:00

1969 lines
72 KiB
HTML
Executable File

<! This document generated using mif2html Version 1.0 - Walt Akers - 1996 !>
<head>
<title>CDEV Documentation</title>
</head>
<body bgcolor="#E0E0FF">
<body>
<! ************************ FILE : cdevIntroductionTITLE.mif *****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start ADDRESS ***!><font size=+12 color=Black><strong><em>
Introduction to CDEV
<!*** Finish ADDRESS ***!></p></strong></em></font>
<!*** Start ADDRESS-SUBHEAD ***!><font size=+2 color=Black><strong>
Overview of the Control Device Interface
</p>
<!*** Finish ADDRESS-SUBHEAD ***!></p></strong></font>
<!*** Start ADDRESS-VERSION ***!><font size=+2 color=Black>
Chip Watson, Jie Chen, Danjin Wu, Walt Akers
</p>
</p>
Version 1.5 December 9, 1996
</p>
</p>
TJNAF - Thomas Jefferson National Accelerator Facility
</p>
<!*** Finish ADDRESS-VERSION ***!></p></font>
</td></tr>
</table>
<! *************************** TABLE OF CONTENTS ****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top align=center>
<!*** Start CLASS-TOC-TITLE ***!><font size=+3><strong>
Table of Contents
<!*** Finish CLASS-TOC-TITLE ***!></p></strong></font>
</td></tr>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<table>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
1.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF1">Introduction</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF2">What is CDEV</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF3">Layering and Abstraction</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF4">Information Hiding</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF5">Device Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF6">Standard Messages</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF7">Data Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
2.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF8">Basic Operations on Devices and Data</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
3.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF9">Asychronous Operations</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF10">Callback Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF11">System Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF12">Group Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF13">Request Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF14">File Descriptors and &quot;select&quot;</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
4.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF15">Error Handling</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
5.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF16">Name Resolution</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF17">cdevDirectory Object</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF18">Service Definition</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF19">Device Class Definition</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF20">Instance Definition</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<!*** Finish UHEADING2TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start UHEADING2TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF21">Aliases</a>
<!*** Finish UHEADING2TOC ***!><br></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
6.
<!*** Finish HEADING1TOC ***!><br></font>
</td>
<td valign=top>
<!*** Start HEADING1TOC ***!><font size=+1 color=Black>
<a href="cdevIntroduction.html#TOCREF22">Channel Access Service</a>
<!*** Finish HEADING1TOC ***!><br></font>
</td></tr>
</table>
</td></tr>
</table>
<! **************************** LIST OF FIGURES *****************************!>
<br><hr><br>
<table width=100%>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top align=center>
<!*** Start CLASS-LOF-TITLE ***!><font size=+3><strong>
List of Figures
<!*** Finish CLASS-LOF-TITLE ***!></p></strong></font>
</td></tr>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 1:
<a href="cdevIntroduction.html#LOFREF1">Sample usage of the send method of a cdevDevice</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 2:
<a href="cdevIntroduction.html#LOFREF2">Overview of cdevData operations</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 3:
<a href="cdevIntroduction.html#LOFREF3">Three forms of the send command</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 4:
<a href="cdevIntroduction.html#LOFREF4">Overview of the cdevCallback object and the cdevCallbackFunction</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 5:
<a href="cdevIntroduction.html#LOFREF5">Structure of the cdevCallback object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 6:
<a href="cdevIntroduction.html#LOFREF6">Usage of the pend method in the cdevSystem object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 7:
<a href="cdevIntroduction.html#LOFREF7">Synchronization methods in the cdevSystem object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 8:
<a href="cdevIntroduction.html#LOFREF8">Sample usage of the cdevGroup object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 9:
<a href="cdevIntroduction.html#LOFREF9">Sample usage of the cdevRequestObject object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 10:
<a href="cdevIntroduction.html#LOFREF10">Structure of the cdevRequestObject object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 11:
<a href="cdevIntroduction.html#LOFREF11">File descriptor routines of the cdevSystem object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 12:
<a href="cdevIntroduction.html#LOFREF12">Using CDEV file descriptors with the UNIX select function</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 13:
<a href="cdevIntroduction.html#LOFREF13">Error handling mechanisms provided by the cdevSystem object</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 14:
<a href="cdevIntroduction.html#LOFREF14">Enumerated severity codes generated by CDEV</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 15:
<a href="cdevIntroduction.html#LOFREF15">Enumerated error codes generated by CDEV</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 16:
<a href="cdevIntroduction.html#LOFREF16">Obtaining a reference to the cdevDirectory device</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 17:
<a href="cdevIntroduction.html#LOFREF17">Virtual form of the data in a cdevDirectory</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 18:
<a href="cdevIntroduction.html#LOFREF18">Syntax of the #include directive</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 19:
<a href="cdevIntroduction.html#LOFREF19">Sample service definition</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 20:
<a href="cdevIntroduction.html#LOFREF20">Sample service definition</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 21:
<a href="cdevIntroduction.html#LOFREF21">Sample inherited class definition </a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 22:
<a href="cdevIntroduction.html#LOFREF22">Multiple instances of the magnet class</a>
<!*** Finish FIGURELOF ***!><br></font>
<!*** Start FIGURELOF ***!><font size=+1 color=Black>
Figure 23:
<a href="cdevIntroduction.html#LOFREF23">Alias device name</a>
<!*** Finish FIGURELOF ***!><br></font>
</td></tr>
</table>
<! ************************ FILE : ./cdevIntroduction.mif *****************************!>
<br><hr><br>
<table width=100%>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
1.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF1">
Introduction
</a> <!*** Finish HEADING1 ***!></p></strong></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF2">
What is CDEV
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The CDEV (common device) C++ class library is an object-oriented framework that
provides a standard interface between an application and one or more underlying
control packages or systems. Each underlying package (called a service) is
dynamically loaded at run-time, allowing an application to access a new service by
name without re-compilation or re-linking. A major feature of CDEV is its ability to hide
the implementation details of a particular device from the high level application
developer. This allows server implementation choices to be changed without breaking
high level client applications. Additionally, because the application is unaware of the
underlying service's specific implementation, CDEV is a powerful vehicle for
developing portable applications.
</p>
The basic CDEV interface can be described through a <em>device</em>/<em>message</em> paradigm. The
<em>device</em> is not necessarily a physical object, rather, it is a cdevDevice object that
provides a standard interface to CDEV. The application uses this interface to send
messages to the device. When the cdevDevice receives this message it will
dynamically load the appropriate service (as defined in the CDEV device definition
file), and forward the message to it. The service may then perform any action
necessary to satisfy the application's request.
</p>
The CDEV API is optimized for repetitive operations, in particular for monitoring value
changes within a server. Asychronous operations with callbacks are supported,
including asychronous error notification. Specifically, CDEV supports most features of
channel access (the EPICS communications protocol).
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF3">
Layering and
Abstraction
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The CDEV library provides a standard interface to one or more underlying control
packages or systems. Currently CDEV provides support for EPICS channel access,
tcl scripts, the ACE communications package (a C++ class library over TCP/IP). The
ACE package is used to communicate with an on-line accelerator modeling package
and with CODA, the CEBAF On-line Data Acquisition system. Access to the EPICS
archive data will be added in a later release. All data will be available through a single
API (application programming interface).
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF4">
Information Hiding
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The ability to hide the implementation details of a particular device (such as the choice
of records in EPICS) from the high level application developer, allows server
implementation choices to be changed without breaking all high level client
applications. For example, several records may be merged into a new custom record
without changing applications which access those records through the CDEV API.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF5">
Device Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The basic idea behind CDEV is that all I/O is performed by sending messages to
devices. A device is a named entity in the control system which can respond to a set
of messages such as <em>on</em> or <em>off</em> or <em>get current</em>. Further, a device is a virtual entity
potentially spanning multiple servers and services such as channel access, an
archiver, and a static database.
</p>
Each device and message pair is mapped to a unique service (such as channel
access) and service dependent data (such as the process variable name in EPICS).
This mapping is kept in a name service, and is ultimately initialized from an ASCII file.
The designer/maintainer of the server would typically be the person responsible for
keeping the mapping current.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF6">
Standard
Messages
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Most devices will implement a number of attributes which may be read or written. In
order to facilitate developing generic applications, the following standard messages
are recommended for devices, where <em>attrib</em> is some attribute of the device:
<!*** Finish BODY ***!></p></font>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
set <em>attrib</em> =&gt; Set the value of the attribute
get <em>attrib</em> =&gt; Get the value of the attribute
monitorOn <em>attrib</em> =&gt; Start monitoring the value of the attribute
monitorOff <em>attrib</em> =&gt; Stop monitoring the value of the attribute
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF7">
Data Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The message sent to the device may have an associated data object. For example,
the message <em>set current</em> will have an associated <em>value</em> for the new current setting. This
value is passed as an additional argument on the send call.
</p>
Data returned from the server to the client may contain multiple tagged values,
including <em>value</em>, <em>status</em>, and<em> timestamp</em>. Each of these items is extracted from the
returned data object by specifying a name or an integer tag. Any data object may
contain an arbitrary number of tagged entries, allowing considerable flexibility in
defining future clients and servers.
</p>
Acknowledgment: This work derives some of its ideas about devices and messages
from work done at Argonne by Claude Saunders on a device oriented layer above
channel access. Much additional analysis &amp; design work has been done by members
of the EPICS collaboration.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
2.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF8">
Basic Operations on Devices and Data
</a> <!*** Finish HEADING1 ***!></p></strong></font>
<!*** Start BODY ***!><font size=+1 color=Black>
The basic user deals only with the device and data objects. The device is created by
name, and I/O consists of sending messages to this device. The device object is the
simplest I/O object to use: a single device (magnet, viewer, etc.) may be completely
controlled from a single device object, with data being passed by 2 data objects (one
for output, another for returned results; dataless commands would not require either).
The following sample code reads the magnet current from one magnet, and sets the
magnet current for a second magnet to that value:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 1:
<a name="LOFREF1">
Sample usage of the send method of a cdevDevice
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
void main ()
{
// *************************************************************
// * Get references to the 2 devices
// *************************************************************
cdevDevice&amp; mag1 = cdevDevice::attachRef (&quot;Magnet1&quot;);
cdevDevice&amp; mag2 = cdevDevice::attachRef (&quot;Magnet2&quot;);
cdevData result;
// *************************************************************
// * Get the current from the first magnet and use it to set
// * the current on the second.
// *************************************************************
mag1.send(&quot;get current&quot;, NULL, result);
mag2.send(&quot;set current&quot;, result, NULL);
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 1>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
The send call, which is synchronous, takes 3 arguments, and returns an integer
status:
<!*** Finish BODY ***!></p></font>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
int send(char* msg, cdevData&amp; out, cdevData&amp; result);
<!*** Finish PROGRAM ***!></font></pre>
<!*** Start BODY ***!><font size=+1 color=Black>
Like all CDEV calls, a return code of 0 means success (error handling is described in
a later section). The first argument to <em>send</em> is a character string message. The device
name and this string uniquely determine the underlying service to use, and whatever
addressing data that service needs to locate the server. The first <em>send</em> operation
automatically connects to the requested service, initializing any underlying packages
as needed.
</p>
The second and third arguments are outbound and result data of type cdevData. This
is a composite data object which may contain an arbitrary number of data values
tagged with an integer tag. The data is self-describing to the extent that cdevData
keeps track of the data type, and can automatically convert between data types
through C++ function overloading or by explicit direction from the caller. The integer
tags are not known to the user at compile time (i.e., no header files required), and can
be referred to by character string equivalents. The cdevData class keeps track of all
integer tags and their character string equivalents. Character string tags may be
converted to integer tags at run time to improve performance. The following code
demonstrates how to insert values into and extract values from a cdevData object:
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 2:
<a name="LOFREF2">
Overview of cdevData operations
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
cdevData d1, d2;
int valtag;
float x, x2;
int status;
...
d1.tagC2I(&quot;value&quot;,&amp;valtag); // get the integer tag for &quot;value&quot;
...
d1.insert(&quot;value&quot;,37.9); // insert using a character tag
device.send(&quot;message&quot;,d1,d2); // send d1, get back d2
d2.get(valtag,&amp;x); // get &quot;value&quot; from d2 into x
d2.get(&quot;status&quot;,&amp;status); // extract the &quot;status&quot;
x2 = d2; // get &quot;value&quot; into x2 (= overload)
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 3>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
The last line above demonstrates using operator overloading to extract the &quot;value&quot;
item from the data object; i.e., the character tag &quot;value&quot; is the default tag to use in
extracting a data item for the &quot;=&quot; function overload. This form is available for all scalar
types supported by cdevData.
</p>
Most I/O operations use the &quot;value&quot; tag to transmit a single value (scalar or array).
Other commonly used tags are &quot;status&quot; and &quot;time&quot; (a POSIX time struct). These
tagged data items are optionally returned by some servers under the control of the I/O
context (see below for changing the default context).
</p>
In this release, cdevData supports the following data types: <em>unsigned char, short,
unsigned short, int, unsigned int, long, unsigned long, float, double</em>, <em>character strings</em>
and <em>time stamp. </em>All data types may be either scalar or multi-dimensional arrays.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
3.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF9">
Asychronous Operations
</a> <!*** Finish HEADING1 ***!></p></strong></font>
<!*** Start BODY ***!><font size=+1 color=Black>
In addition to the synchronous send, there are 2 asynchronous forms for sending
messages. The class definition for all three forms is given below.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 3:
<a name="LOFREF3">
Three forms of the send command
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
class cdevDevice:
{
public:
int send (char* msg, cdevData&amp; out, cdevData&amp; result);
int sendNoBlock (char* msg, cdevData&amp; out, cdevData&amp; result);
int sendCallback (char* msg, cdevData&amp; out, cdevCallback cb);
};
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 5>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
The second form, sendNoBlock, takes the same arguments as send but completes
asynchronously. That is, the result will be invalid until some synchronizing action is
taken (discussed below). The third form returns the result to a callback function
specified as part of the callback argument. For each of these asychronous calls, the
message may be buffered by the underlying service, so that upon return from the call
there is no guarantee that the message has even been sent yet. Transmission may be
forced with a flush call using the cdevSystem object described below. A flush is
automatically performed if pend is called.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF10">
Callback Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The callback object is a simple object containing 2 items: a function pointer, and an
arbitrary user argument. As an example, the following code fragment demonstrates
monitoring the magnet current asynchronously (the third argument to the callback
function is discussed later):
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 4:
<a name="LOFREF4">
Overview of the cdevCallback object and the cdevCallbackFunction
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
// declare the callback func
cdevCallbackFunction gotit;
// create callback object
cdevCallback callbk(gotit, myarg);
...
mag1.sendCallback(&quot;monitorOn current&quot;,NULL,callbk);
...
void gotit(int status, void* userarg, cdevRequestObject&amp; reqobj,
cdevData&amp; result)
{
float f = result;
printf(&quot;new value is %f\\n&quot;,f);
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 7>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
The following code defines the callback (the cdevRequestObject is described below):
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 5:
<a name="LOFREF5">
Structure of the cdevCallback object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
typedef void (*cdevCallbackFunction)(int status, void* userarg,
cdevRequestObject&amp; reqobj,
cdevData&amp; result);
class cdevCallback
{
public:
cdevCallback (cdevCallbackFunction func, void* userarg);
cdevCallbackFunction function;
void* userarg;
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 9>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF11">
System Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Waiting for completion of asychronous operations may be accomplished in one of two
ways: (1) using groups, and (2) using the system object. The system object keeps
track of all devices, and contains methods for flushing, polling, and pending for
asychronous operations.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 6:
<a name="LOFREF6">
Usage of the pend method in the cdevSystem object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
// get default system
cdevSystem&amp; sys = cdevSystem::defaultSystem();
...
mag1.sendNoBlock(&quot;on&quot;,...); // async op(s)
mag2.sendNoBlock(&quot;on&quot;,...); // async op(s)
...
sys.pend(); // wait for all I/O to complete
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 13>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
The following class interface shows the forms for each synchronization method:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 7:
<a name="LOFREF7">
Synchronization methods in the cdevSystem object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
class cdevSystem
{
public:
intflush();
int poll();
intpend();
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 15>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
<em>flush</em>: Flush all pending output to the network for those services that perform send
buffering.
</p>
<em>poll:</em> Flush all pending output, and process all received replies (including dispatching
callbacks, if any). Any received monitor callbacks will be delivered as well.
</p>
<em>pend</em>: Flush all pending output, and process all replies for the specified number of
seconds. If the time argument is omitted, wait until all replies have been received. If a
monitor operation was started, this waits for the connection (first callback) only.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF12">
Group Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
An alternative mechanism for waiting for asychronous calls is through the use of
groups. A group keeps track off all I/O operations started from the time the group is
started until the group is ended. Groups may be nested or overlapped, and support
the same flush/poll/pend operations as the system object. For example:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 8:
<a name="LOFREF8">
Sample usage of the cdevGroup object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
cdevGroup g1, g2;
...
g1.start();
mag1.sendCallback(...);
mag2.sendCallback(...);
g2.start();
bpm1.sendNoBlock(...);
bpm2.sendNoBlock(...);
g1.end();
mag3.sendCallback(...);
bpm3.sendNoBlock(...);
g2.end();
g1.pend(4.0);
// at this point operations on mag1, mag2, bpm1, &amp; bpm2 are done
// or have timed out (error handling discussed later).
...
// mag3 and bpm3 may not be finished yet, pend on the second
// group to wait for their completion
g2.pend();
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 17>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
Note: Allowing nested or overlapped groups allows library calls to start or stop groups
without needing to know if another group is already active.
</p>
Groups may be operated in one of two modes. Immediate mode (default) causes
grouped operations to be immediately executed, and the group is just used for
completion synchronization. Deferred mode causes messages to be held back until
the group is ended and the operations are flushed. After the operations are complete,
he group of operations may be flushed again (without re-posting), allowing the group
to function as a list manager/executor.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF13">
Request Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Occasionally, an I/O operation may need to be repeated may times. In this case, it is
not efficient to parse the message each time to determine which server to use. It is
possible to bypass this parsing by creating a request object. The request object is like
the device object, except that the message string is specified at creation time, and the
request object is therefore specific to the particular underlying service to which that
message must be directed.
</p>
In the case of EPICS channel access, the request object opens and maintains the
channel to the EPICS process variable. The request object is NOT the same as an
EPICS channel, in that the request object binds a device and a message, and the
message implies a direction. If the message is considered to be of the form <em>verb</em> +
<em>attribute </em>then the EPICS channel essentially binds device and attribute but not verb. In
some future release of CDEV, a more channel like object may be included if there is a
demand for it. If two cdevRequestObjects reference the same EPICS channel, only a
single channel access connection is established.
</p>
The following code demonstrates sending a set of data values to a single magnet
using a request object. Note that the send call omits the message argument:
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 9:
<a name="LOFREF9">
Sample usage of the cdevRequestObject object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
cdevRequestObject&amp; mag1BDL =
cdevRequestObject::attachRef(&quot;mag1&quot;,&quot;set BDL&quot;);
cdevData mydata;
...
{
mydata = i*10; // 10 amp steps
mag1BDL.send(mydata,NULL); // ignore errors for now
sleep(1);
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 19>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
In most cases, the device object will create the request object to perform a requested
I/O operation. All 3 forms of send are supported by the request object, with a calling
syntax identical to the device calls without the message argument. The interface to the
request object is given below:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 10:
<a name="LOFREF10">
Structure of the cdevRequestObject object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
class cdevRequestObject
{
public:
char* message(); // returns the message string
cdevDevice&amp; device(); // returns the device object
int state(); // connected/disconnected/
int access(); // read/write/none
int send(cdevData&amp; out, cdevData&amp; result);
int sendNoBlock(cdevData&amp; out, cdevData&amp; result);
int sendCallback(cdevData&amp; out, cdevCallback callback);
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 21>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
When an asynchronous operation completes, the relevant request object is passed to
the user's callback routine. This allows the user to extract the message string and
device name from the request object if necessary or desired.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF14">
File Descriptors
and &quot;select&quot;
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
An alternative mechanism for dealing with asynchronous operations is to directly test
the file descriptors being used. This interface is currently implemented in the
cdevSystem class. The pertinent methods have the following form:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 11:
<a name="LOFREF11">
File descriptor routines of the cdevSystem object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
typedef void (*cdevFdChangedCallback)(int fd, int opened,
void* userarg)
class cdevSystem
{
public:
...
int getFd(int fd[], int &amp;numFD);
int addFdChangedCallback(cdevFdChangedCallback cbk, void* arg);
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 23>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
The getFd method will populate a user allocated array of integers (fd) with the file
descriptors currently in use by the cdevSystem object. The number of file descriptors
that were allocated by the user is specified in the numFD variable. Upon completion,
the numFD variable will be set to the number of file descriptors actually copied into the
fd array. An error is returned if the buffer is not sufficient to store the complete set of
file descriptors.
</p>
The addFdChangedCallback method allows the user to specify a function to be called
each time a file descriptor is added (opened=1) or closed (opened=0).
</p>
The following code illustrates the usage of the UNIX select call:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 12:
<a name="LOFREF12">
Using CDEV file descriptors with the UNIX select function
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
int myFD[5];
void mySelectLoop ( cdevSystem &amp; system )
{
int fd[20];
int numFD = 15, nfds;
fd_set rfds; // Ready file descriptors
fd_set afds; // Active file descriptors
// Copy the file descriptors I am already using to the list
memcpy(fd, myFD, sizeof(myFD));
// Get the file descriptors in use by the cdevSystem object
system.getFd(&amp;fd[5], numFD);
// Add in the 5 previously defined file descriptors
numFD += 5;
// Zero the active file descriptors
FD_ZERO(&amp;afds);
// Setup the active file descriptors
// Get the maximum number of file descriptors
nfds = FD_SETSIZE;
while(1) {
// Copy the active descriptors to the ready descriptors
memcpy((void *)&amp;rfds, (void *)&amp;afds, sizeof(rfds));
// Use select to detect activity on the file descriptors
// Iterate through the list of file descriptors
{
if (FD_ISSET(fd[i], &amp;rfds)
{
// Respond to active file descriptor here
}
}
}
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 25>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
4.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF15">
Error Handling
</a> <!*** Finish HEADING1 ***!></p></strong></font>
<!*** Start BODY ***!><font size=+1 color=Black>
Most CDEV routines return an integer status, with 0=success. Errors may also be
automatically printed or routed to a user supplied error handler. Control over this
behavior is through the system object:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 13:
<a name="LOFREF13">
Error handling mechanisms provided by the cdevSystem object
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
typedef void (*cdevErrorHandler)(int severity, char* text,
cdevRequestObject&amp; request);
class cdevSystem
{
public:
...
int autoErrorOn();
int autoErrorOff();
cdevErrorHandler setErrorHandler(cdevErrorHandler handler = 0);
int reportError(int severity, char *name,
cdevRequestObject* request, char* format, ...);
void setThreshold ( int errorThreshold );
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 27>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
<em></em>
</p>
<em>The </em><em>severity </em><em>parameter indicates the </em>level of the error. Severity levels are informative,
warning, error, and severe error. The following values are defined in cdevErrCode.h to
describe the severity of an error message:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 14:
<a name="LOFREF14">
Enumerated severity codes generated by CDEV
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
CDEV_SEVERITY_INFO Informative message
CDEV_SEVERITY_WARN Warning message - operation encountered a
problem during processing.
CDEV_SEVERITY_ERROR Error message - operation cannot be completed
CDEV_SEVERITY_SEVERE Severe/Fatal Error - cdev cannot continue
execution
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 29>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
<em>autoErrorOn</em> Turn on default error handling, which prints error to stdout.
</p>
<em>autoErrorOff</em> Turn off default error handling.
</p>
<em>setErrorHandler</em> Set a new function to be the system error handler. Return the old
function pointer. Omitting the argument resets the handler to the default handler which
simply prints error messages to stderr.
</p>
<em>reportError</em> Routine which behaves like printf with 3 additional arguments (severity,
caller's name, and request object if available).
</p>
Note: For simplicity of use, a very compact set of error codes is implemented in CDEV.
The following error codes are defined in the header file cdevErrCode.h.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 15:
<a name="LOFREF15">
Enumerated error codes generated by CDEV
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
CDEV_WARNING = -2 Failure of function is non-consequential
CDEV_ERROR = -1 Errors that are not in any categories
CDEV_SUCCESS = 0 Success
CDEV_INVALIDOBJ = 1 Invalid cdev objects
CDEV_INVALIDARG = 2 Invalid argument passed to cdev calls
CDEV_INVALIDSVC = 3 Wrong service during dynamic loading
CDEV_INVALIDOP = 4 Operation is unsupported (collection)
CDEV_NOTCONNECTED = 5 Not connected to low network service
CDEV_IOFAILED = 6 Low level network service IO failed
CDEV_CONFLICT = 7 Conflicts of data types or tags
CDEV_NOTFOUND = 8 Cannot find user request (cdevData)
CDEV_TIMEOUT = 9 Time out
CDEV_CONVERT = 10 cdevData Conversion error
CDEV_OUTOFRANGE = 11 Value out of range for device attribute
CDEV_NOACCESS = 12 Insufficient access to perform request
CDEV_ACCESSCHANGED = 13 Change in access permission of device
CDEV_DISCONNECTED = 60 Application has lost server connection
CDEV_RECONNECTED = 61 Application has regained server connection
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 31>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
5.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF16">
Name Resolution
</a> <!*** Finish HEADING1 ***!></p></strong></font>
<!*** Start BODY ***!><font size=+1 color=Black>
Some type of name resolution system is needed to (1) locate which package (called a
service) underneath CDEV will support the specified message for the specified device
and (2) provide parameters needed by the service to contact the server and perform
the desired operation. For example, the message &quot;get current&quot; sent to a magnet
&quot;mag1&quot; might use the service &quot;ca&quot; (channel access), with parameter &quot;mag1cur.val&quot;
(record and field). This parameter is referred to as service data, i.e. data used by the
service to perform the operation. The user is typically unaware of this data, which
should be supplied by the device implementer.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF17">
cdevDirectory
Object
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Name resolution in CDEV is implemented by the <em>cdevDirectory</em> device. The
cdevDirectory device supports a <em>query</em> message allowing the user to search the
Device Directory List (DDL) for devices which are (1) members of a user specified
class or (2) match a user specified regular expression.
</p>
As with any cdevDevice object, the user instantiates a cdevDirectory device by using
the <em>cdevDevice::attachPtr() </em>or <em>cdevDevice::attachRef()</em> method. The following code
fragment illustrates the correct method for attaching to a cdevDirectory device.
<!*** Finish BODY ***!></p></font>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
<!*** Finish PROGRAM ***!></font></pre>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 16:
<a name="LOFREF16">
Obtaining a reference to the cdevDirectory device
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
cdevDevice &amp; device = cdevDevice::attachRef(&quot;cdevDirectory&quot;);
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 11>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
Like all other devices, the cdevDirectory response to messages. The following
messages may be submitted to this device:
<!*** Finish BODY ***!></p></font>
<table>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
query: Identify the devices that match the selection criteria.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
queryClass: Identify the DDL class from which a device is instantiated.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
queryAttributes: Identify all attributes supported by a device or a DDL class.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
queryMessages: Identify all messages supported by a device or DDL class.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
queryVerbs: Identify all verbs supported by a device or DDL class.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
service: Identify the service that is used by a device/message pair.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
serviceData: Identify service data specified for a device/message pair.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
update: Add information to the cdevDirectory data structure.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
validate: Verify that a device or DDL class contains certain definitions.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
</table>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
By default, there is a single directory device. To allow for arbitrary expansion CDEV
will allow each service to register additional directory devices with the system object.
A search list of directories may be specified to the system directory device (planned
feature).
</p>
Each directory acts as if it has a table of information in the following form:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 17:
<a name="LOFREF17">
Virtual form of the data in a cdevDirectory
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
dev-class dev-namemessageserviceservice-data
magnet mag1 on ca {pv=M1CSR.VAL default=1}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 33>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
This table is loaded from a device definition file which describes the mapping from
(device,message) to (service,serviceData), where &quot;service&quot; is one of the dynamically
loaded CDEV services, and &quot;serviceData&quot; is whatever information that service needs
to send the message to the device. In this example the service data contains an
EPICS process variable name and a default value to write to that channel.
</p>
It is NOT the purpose of the device definition file to completely specify the datatypes of
all data passed between device and user. CDEV does considerable data type
conversion as needed, and services do reasonable run-time validation. The goal is to
make the file as small as is reasonably possible and still maintain readability.
</p>
General:
<!*** Finish BODY ***!></p></font>
<table>
<tr><td width=5% valign=top>
</td>
<td valign=top>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
leading whitespace is not significant
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
any amount of whitespace may separate language elements, including
space, tab, and newline, with the exception that at least one whitespace
character is needed before the colon separating a class name and its
inherited classes.
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
keywords are case sensitive
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start BODY ***!><font size=+1 color=Black>
NOTE: This specification is preliminary, and will be expanded to support additional
features as time allows.
</p>
The interface definition consists of three parts: service definitions, device class
definitions, and device instantiation (in that order). Standard definitions may be
specified via include files using a cpp syntax:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 18:
<a name="LOFREF18">
Syntax of the #include directive
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
#include &quot;filename&quot;
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 35>
</a> <!*** Finish FIGURE ***!></p></em></font>
</td></tr>
</table>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF18">
Service Definition
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
The service definition declares a service name, and lists all tags which the service will
accept for its &quot;serviceData&quot;. The following 3 lines define a service named &quot;myservice&quot;
which supports serviceData that specifies values for any of the tags &quot;abc&quot;, &quot;def&quot;, and
&quot;ghi&quot;:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 19:
<a name="LOFREF19">
Sample service definition
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
service myservice
{
tags {abc, def, ghi}
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 37>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
As a more concrete example, the following is the specification for thechannel access
service:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 20:
<a name="LOFREF20">
Sample service definition
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
service ca
{
tags {pv, default}
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 39>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
The &quot;pv&quot; tag is used to specify the process variable name, and the &quot;default&quot; tag is used
to specify a default value for a &quot;set&quot; operation (examples are below).
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF19">
Device Class
Definition
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Device classes are used to define a collection of similar devices; that is, devices which
will respond to the same set of messages. In order to simplify class definition, the
following design choices are made:
<!*** Finish BODY ***!></p></font>
<table>
<tr><td width=5% valign=top>
</td>
<td valign=top>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
multiple inheritance is supported, and
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
messages may be defined as verb + attribute, where the list of verbs is
defined separately from the list of attributes.
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start BODY ***!><font size=+1 color=Black>
The second item reduces the amount of text needed to define a device, since all
operations on a single attribute (get, set, monitor, etc.) may be defined in a single line
as long as they all use the same serviceData.
</p>
For this initial specification, the class definition contains 4 parts:
<!*** Finish BODY ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
inheritance specification
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
verbs
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
attributes
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
messages
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start BODY ***!><font size=+1 color=Black>
For each attribute or message there are 3 parts:
<!*** Finish BODY ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
attribute or message text
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
service name
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start LISTBULLET2 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
service data
<!*** Finish LISTBULLET2 ***!></p></font>
<!*** Start BODY ***!><font size=+1 color=Black>
Service data is zero or more (name=value) pairs, where the allowed set of names are
defined by the &quot;tags&quot; clause in the service specification. The value may contain a pair
of angle brackets &quot;&lt;&gt;&quot; into which the device name will be substituted.
</p>
Example: Suppose there are a set of magnets for which it is possible to read and write
bdl (integral field), and current (amps). That is, the messages &quot;get bdl&quot;, &quot;get current&quot;,
&quot;set bdl&quot;, etc. are valid. Also, each magnet responds to the commands &quot;on&quot; and &quot;off&quot;.
Further suppose that the beamline position and length of the magnet are available in a
static database (assume read/write).
</p>
Here is a complete class definition:
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 21:
<a name="LOFREF21">
Sample inherited class definition
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
class stdio
{
verbs {get, set, monitorOn, monitorOff}
}
class magnet : stdio
{
attributes
{
bdl ca {pv=&lt;&gt;.bdl};
current ca {pv=&lt;&gt;.val};
zpos os {path=&lt;&gt;/phy/z};
length os {path=&lt;&gt;/phy/len}
}
messages
{
on ca {pv=&lt;&gt;CSR.val, default=1};
off ca {pv=&lt;&gt;CSR.val, default=0};
}
}
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 41>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
Note the semicolon at the end of each line of attributes or messages (except for the
last line). Note also that the process variable name has a place holder into which the
device name will be substituted. More sophisticated name mangling is envisaged, but
not for this release. Syntax is still open to revision.
<!*** Finish BODY ***!></p></font>
</td></tr>
</table>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF20">
Instance Definition
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Instances of a class are given by following the class name with a list of instance
names. Device names may be separated by whitespace characters (including
newline) or by commas.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 22:
<a name="LOFREF22">
Multiple instances of the magnet class
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
magnet : m1 m2 m3;
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 43>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
Combined with the previous definition, the message &quot;on&quot; sent to magnet m2 would
select the process variable &quot;m2CSR.val&quot; with &quot;1&quot; as the value to write.
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start UHEADING2 ***!><font size=+1 color=Black><strong>
<a name="TOCREF21">
Aliases
</a> <!*** Finish UHEADING2 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start BODY ***!><font size=+1 color=Black>
Sometimes it is convenient to refer to a device by more than one name. The DDL
syntax supports simple aliases, one per line.
</p>
<!*** Finish BODY ***!></p></font>
<!*** Start FIGURE ***!><font size=+0 color=Black><em>
Figure 23:
<a name="LOFREF23">
Alias device name
<table border=1><tr><td>
<table>
<tr><td>
<! ***** Empty Column ***** !>
</td>
<td valign=top>
<!*** Start PROGRAM ***!><pre><font size=+0 color=Black>
alias myname m1
<!*** Finish PROGRAM ***!></font></pre>
</td></tr>
</table>
</tr></td></table>
<AFrame 45>
</a> <!*** Finish FIGURE ***!></p></em></font>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
<!*** Finish BODY ***!></p></font>
</td></tr>
<tr><td valign=top align=right>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
6.
<!*** Finish HEADING1 ***!></p></strong></font>
</td>
<td valign=top>
<!*** Start HEADING1 ***!><font size=+3 color=Black><strong>
<a name="TOCREF22">
Channel Access Service
</a> <!*** Finish HEADING1 ***!></p></strong></font>
<!*** Start BODY ***!><font size=+1 color=Black>
EPICS / Channel Access version 3.12 is recommended.
</p>
Features:
<!*** Finish BODY ***!></p></font>
<table>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Supports synchronous and asynchronous send's.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Tracks file descriptor registration.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Fetches data in native type (type conversion done on client and not server).
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Provides a default name service so that if a device is not defined, then an
EPICS channel access connection is attempted with the record name set equal
to the device name, and the field name set equal to the attribute name.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
</table>
<!*** Start BODY ***!><font size=+1 color=Black>
Restrictions:
<!*** Finish BODY ***!></p></font>
<table>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Only supports set/get/monitorOn/monitorOff verbs and the pv and readonly
tags. Support for arbitrary messages with default data will be in the next release.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Discards all exception callbacks from channel access in this version.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
Channel access security is not supported in this release.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
</table>
<!*** Start BODY ***!><font size=+1 color=Black>
Compilation options:
<!*** Finish BODY ***!></p></font>
<table>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
_CA_SYNC_CONN = perform connections synchronously, waiting up to 4
seconds.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
_CDEV_DEBUG = print verbose messages
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
<tr><td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
<img src="bullet.jpg">
<!*** Finish LISTBULLET1 ***!></p></font>
</td>
<td valign=top>
<!*** Start LISTBULLET1 ***!><font size=+1 color=Black>
_EPICS_3_12 = if not defined, use 3.11 calls instead.
<!*** Finish LISTBULLET1 ***!></p></font>
</td></tr>
</table>
<!*** Start BODY ***!><font size=+1 color=Black>
</p>
<!*** Finish BODY ***!></p></font>
</td></tr>
</table>
</body>