update doc

This commit is contained in:
Michael Davidsaver
2017-07-14 18:59:02 +02:00
parent 95a750c4f9
commit a3350a4f38
11 changed files with 342 additions and 1682 deletions

View File

@ -1,38 +0,0 @@
Release 5.x.x
==========
* Add new library pvAccessIOC for use with PVAClientRegister.dbd and PVAServerRegister.dbd.
Necessary to avoid having pvAccess library depend on all IOC core libraries.
Release 5.0.0
==========
* Remote channel destroy support
* Multiple network inteface support
* Local multicast (repetitor) reimplemented
* Monitor reconnect when channel type changes fix
* C++11 compilation fixes
* Added version to pvaTools
* Memory management improved
* pipeline: ackAny argument percentage support
* Monitor overrun memory issues fixed
* CA provider destruction fixed
* Replaced LGPL wildcard matcher with simplistic EPICS version
Release 4.1.2
==========
* Improved Jenkins build support
* Removed QtCreated IDE configuration files
* Use of getSubField<> instead of e.g. getDoubleField()
* CA support for pvget, pvput and pvinfo.
* vxWorks/RTEMS compiler warnings resolved.
* Transport shutdown improved.
* CA DBR status fix.
* Monitor queue handling improved.
* Fixed bad performance on 10Gbit or faster networks.
* Async RPC service.
Release 4.0.5
==========
(Starting point for release notes.)

View File

@ -321,7 +321,7 @@ AUTOLINK_SUPPORT = YES
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
@ -766,9 +766,9 @@ WARN_LOGFILE =
# Note: If this tag is empty the current directory is searched.
INPUT = ../src/client/pv \
../src/client/pva \
../src/utils/pv \
../src/pva/pv \
../src/testing/pv \
.
# This tag can be used to specify the character encoding of the source files
@ -2068,7 +2068,8 @@ SKIP_FUNCTION_MACROS = NO
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES = ../../pvData/documentation/pvdata.tag
TAGFILES = "../../pvData/documentation/pvdata.tag=http://mdavidsaver.github.io/pvDataCPP/" \
"libstdc++.tag = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen"
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
@ -2087,14 +2088,14 @@ ALLEXTERNALS = NO
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
EXTERNAL_GROUPS = NO
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
EXTERNAL_PAGES = NO
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of 'which perl').

View File

@ -1,5 +1,14 @@
/**
@page examples_miniget Simple Client Get Example
The shortest possible PVA get() example.
@include miniget.cpp
*/
/**
@page examples_getme Client Get Example
This example demonstrates a client which issues a Get operation on startup,

View File

@ -3,34 +3,22 @@
/**
@mainpage pvAccess C++ docs
The epics::pvAccess namespace.
See pv/pvAccess.h header.
- [Download](https://sourceforge.net/projects/epics-pvdata/files/)
- @htmlonly <a href="modules.html">API components</a> @endhtmlonly
- @ref pvarelease_notes
- API documentation
- @ref pvac page
- @ref providers page
- @ref pvtools
@code
#include <pv/configuration.h>
#include <pv/pvAccess.h>
#include <pv/clientFactory.h>
@endcode
@section main_examples API usage Examples
See the @ref providers page.
@section main_interesting Interesting
- Clients providers
- PVA Client
- CA Client (wraps libca)
- RPC Client helper
- PVA Server epics::pvAccess::ServerContext
- Server providers
- RPC
- Pipeline (monitor w/ flow control)
@section main_examples Examples
- @ref examples_getme
- @ref examples_putme
- @ref examples_monitorme
- Simplest (shortest) possible
- @ref examples_miniget
- More complete
- @ref examples_getme
- @ref examples_putme
- @ref examples_monitorme
*/

View File

@ -6,6 +6,15 @@
@tableofcontents
The epics::pvAccess namespace.
See pv/pvAccess.h header.
@code
#include <pv/configuration.h>
#include <pv/pvAccess.h>
#include <pv/clientFactory.h>
@endcode
@section providers_roles Roles
The Client and Server APIs revolve around the epics::pvAccess::ChannelProvider class.

File diff suppressed because it is too large Load Diff

5
documentation/pvtools.h Normal file
View File

@ -0,0 +1,5 @@
/** @page pvtools Command Line Utilities
*/

3
documentation/readme Normal file
View File

@ -0,0 +1,3 @@
get libstdc++ tag file from
https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag

View File

@ -0,0 +1,138 @@
/** @page pvarelease_notes Release Notes
Release 6.x.x
=============
- Incompatible changes
- Major changes to shared_ptr ownership rules for epics::pvAccess::ChannelProvider and
associated classes. See
- @ref providers
- @ref providers_changes
- Add new library pvAccessIOC for use with PVAClientRegister.dbd and PVAServerRegister.dbd.
Necessary to avoid having pvAccess library depend on all IOC core libraries.
- Simplifications
- use of the epics::pvAccess::ChannelRequester interface is optional
and may be omitted when calling createChannel().
Channel state change notifications are deliviered
to individual operations via epics::pvAccess::ChannelBaseRequester::channelDisconnect()
Release 5.0.0 (July 2016)
=========================
- Remote channel destroy support
- Multiple network inteface support
- Local multicast (repetitor) reimplemented
- Monitor reconnect when channel type changes fix
- C++11 compilation fixes
- Added version to pvaTools
- Memory management improved
- pipeline: ackAny argument percentage support
- Monitor overrun memory issues fixed
- CA provider destruction fixed
- Replaced LGPL wildcard matcher with simplistic EPICS version
Release 4.1.2 (Oct 2015)
========================
- Improved Jenkins build support
- Removed QtCreated IDE configuration files
- Use of getSubField<> instead of e.g. getDoubleField()
- CA support for pvget, pvput and pvinfo.
- vxWorks/RTEMS compiler warnings resolved.
- Transport shutdown improved.
- CA DBR status fix.
- Monitor queue handling improved.
- Fixed bad performance on 10Gbit or faster networks.
- Async RPC service.
Release 4.0.5 (Dec 2014)
=========================
(Starting point for release notes.)
*/
/** @page providers_changes Changes to ChannelProvider ownership rules
@tableofcontents
Major series 6.x includes changes to the rules for when user code may
store strong and/or weak references to epics::pvAccess::ChannelProvider
and related classes. These rules exist to prevent strong reference loops from forming.
@section providers_changes_requester Operation <-> Requester
One change is the reversal of the allowed relationship between
an Operation and its associated Requester (see @ref provider_roles_requester for definitions).
Prior to 6.0.0 an Operation was required to hold a strong reference to its Requester.
This prevented the Requester from holding a strong ref to the Operation.
This was found to be inconvienent and frequently violated.
Beginning with 6.0.0 an Operation is prohibited from holding a strong reference to its Requester.
@subsection providers_changes_requester_port Porting
Legecy code does not store a strong reference to Requesters will see that they are immediately destory.
An example where the Operation is a ChannelGet and the Requester is ChannelGetRequester.
@code
// Bad example!
epics::pvAccess::Channel::shared_pointer chan = ...;
epics::pvAccess::ChannelGet::shared_pointer get;
{
epics::pvAccess::ChannelGetRequester::shared_pointer req(new MyRequester(...));
get = chan->createChannelGet(req, epics::pvData::createRequest("field()"));
// 'req' is only strong ref.
// MyRequester::~MyRequester() called here
// MyRequester::getDone() never called!
}
@endcode
It is necessary to maintain a strong reference to the ChannelRequester as long as callbacks are desired.
@note Legacy code could be modified to strong each Requester alongside the associated Operation.
New code may utilize the new ownership rules and store the Operation in a custom Requester.
@code
struct MyRequester : public epics::pvAccess::ChannelGetRequester {
epics::pvAccess::ChannelGet::shared_pointer get;
...
};
epics::pvAccess::ChannelGetRequester::shared_pointer req(new MyRequester(...));
epics::pvAccess::Channel::shared_pointer chan = ...;
req->get = chan->createChannelGet(req, epics::pvData::createRequest("field()"));
@endcode
@section providers_changes_store Must store Operation reference
Beginning with 6.0.0, all create methods of
epics::pvAccess::ChannelProvider and
epics::pvAccess::Channel
are required to return shared_ptr which are uniquely ownered by the caller
and are not stored internally.
Thus the caller of a create method must keep a reference to each Operation
or the Operation will be destoryed.
Prior to 6.0.0 some providers, notibly the "pva" provider, did not do this.
It was thus (sometimes) necessary to explicitly call a destory() method
to fully dispose of an Operation.
Failure to do this resulted in a slow resource leak.
Beginning with 6.0.0 an Operation may not rely on user code to call a destory() method.
@subsection providers_changes_store_port Porting
Legecy code may be relying on these internal references to keep an Operation alive.
Beginning with 6.0.0 the shared_ptr returned by any create method must be stored or the Operation will
be immediately destroy'd.
@note Beginning with 6.0.0 use of the epics::pvAccess::ChannelRequester interface is optional
and may be omitted when calling createChannel().
*/

92
notes.md.txt Normal file
View File

@ -0,0 +1,92 @@
changes
must keep ChannelProvider refs
Channel doesn't have strong ref to provider.
All channels closed when provider destory'd
default ChannelProviderFactory uses weak_ptr for sharedInstance()
copy+paste from eget.cpp very inefficient...
TODO
ca provider changes
channel has weak_ref to provider
create operations on disconnected channel
monitor queue
untangle responseHandlers.cpp
ref. loops galore
destroy which queued to send???
maps which grow w/o bound
named lock pattern
m_beaconHandlers
locking
no internal locks held when calling *Requester methods, including dtor
any external locks may be held when channel/operation methods called
provider->createChannel()
* returns unique() reference.
* Provider must maintain a cache of existing Channels are prefer this to creating new Channels
calls to channel->createChannel*
* returns unique() reference
* Channel retains internal references to Operation until destroy() is called (or all external references released)
* request on dis-connected channel queues until connected
Add channelStateChanged() to all operation Requesters
* called only with DISCONNECTED (channel connected -> disconnected) or DESTROYED (channel->destroy() called).
* Any in-progress action is implicitly cancel()'d
After some considerable thought, I like to re-define some of the semantics of ChannelProvider, Channel, and operations (eg. ChannelGet).
1. User/caller code takes ownership of returned Channel or operation.
For a Channel to remain open, or an operation to remain active, the caller must hold a reference. This will prevent accumulation of channels and operations which user code isn't accounting for.
The suggested way to accomplish this is for a ChannelProvider to return a shared_ptr<> with a custom cleanup function which calls destroy().
1.1 returned shared_ptr<Channel> must not include an internal references. That is, the first time a Channel is returned it is unique(). Subsequent calls to createChannel() with the same arguments may return unique()==false provided that this count includes only external references.
1.2 returned operation shared_ptr<> must be unique().
2. User/caller code need not cache Channel instances.
Every non-trivial client worries about minimizing the number of Channels.
2.1 ChannelProvider is required to maintain a cache of in-use Channels and prefer to return a cached entry before creating a new Channel.
3 Notify operations about Channel state changes
channelStateChanged() by itself isn't so useful. Clients always proxy this through to some action of each in-progress operation. So have the Channel do this.
3.1 Add a new method channelStateChanged() to all operation Requester classes. Default implementation is a no-op. Only DISCONNECTED and DESTROYED shall be used (CONNECT is delivered as a separate callback *Connect() ).
3.2 When DISCONNECTED is delivered the operation remains "valid" and its *Connect() will be called (again) if/when the Channel again becomes connected
3.3 When DESTROYED is delivered, the underlying Channel has been forcibly closed.
3.3 Delivery of DISCONNECTED or DESTROYED implicitly cancels any in-progress action.
4 Operation life-time
4.1 Channel must support starting operations while in disconnected state
4.2 Operations persist when a Channel becomes DISCONNECTED. On re-connect, the operation *Connect() method is called again, potentially with new Structure definition.

View File

@ -22,8 +22,21 @@ class Configuration;
//! See @ref pvac API
namespace pvac {
/** @defgroup pvac PVAccess Client
/** @defgroup pvac Client API
*
* PVAccess network client (or other epics::pvAccess::ChannelProvider)
*
* Usage:
*
* 1. Construct a ClientProvider
* 2. Use the ClientProvider to obtain a ClientChannel
* 3. Use the ClientChannel to begin an get, put, rpc, or monitor operation
*
* Code examples
*
* - @ref examples_getme
* - @ref examples_putme
* - @ref examples_monitorme
* @{
*/
@ -110,12 +123,13 @@ struct epicsShareClass MonitorEvent
void *priv;
};
//! informaiton on connect/disconnect
//! information on connect/disconnect
struct epicsShareClass ConnectEvent
{
bool connected;
};
//! Thrown by blocking methods of ClientChannel on operation timeout
struct epicsShareClass Timeout : public std::runtime_error
{
Timeout();
@ -130,6 +144,7 @@ class epicsShareClass ClientChannel
ClientChannel(const std::tr1::shared_ptr<Impl>& i) :impl(i) {}
public:
//! Channel creation options
struct epicsShareClass Options {
short priority;
std::string address;
@ -137,26 +152,38 @@ public:
bool operator<(const Options&) const;
};
//! Construct a null channel. All methods throw. May later be assigned from a valid ClientChannel
ClientChannel() {}
/** Construct a ClientChannel using epics::pvAccess::ChannelProvider::createChannel()
*
* Does not block.
* @throw std::logic_error if the provider is NULL or name is an empty string
* @throw std::runtime_error if the ChannelProvider can't provide
*/
ClientChannel(const std::tr1::shared_ptr<epics::pvAccess::ChannelProvider>& provider,
const std::string& name,
const Options& opt = Options());
~ClientChannel();
//! Channel name or an empty string
std::string name() const;
//! callback for get() and rpc()
struct epicsShareClass GetCallback {
virtual ~GetCallback() {}
//! get or rpc operation is complete
virtual void getDone(const GetEvent& evt)=0;
};
//! Issue request to retrieve current PV value
//! @param cb Completion notification callback. Must outlive Operation (call Operation::cancel() to force release)
//! @param pvRequest if NULL defaults to "field()".
Operation get(GetCallback* cb,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
//! Block and retrieve current PV value
//! @param timeout in seconds
//! @param pvRequest if NULL defaults to "field()".
//! @throws Timeout or std::runtime_error
epics::pvData::PVStructure::const_shared_pointer
get(double timeout = 3.0,
@ -165,10 +192,16 @@ public:
//! Start an RPC call
//! @param cb Completion notification callback. Must outlive Operation (call Operation::cancel() to force release)
//! @param arguments encoded call arguments
//! @param pvRequest if NULL defaults to "field()".
Operation rpc(GetCallback* cb,
const epics::pvData::PVStructure::const_shared_pointer& arguments,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
//! Block and execute remote call
//! @param timeout in seconds
//! @param arguments encoded call arguments
//! @param pvRequest if NULL defaults to "field()".
epics::pvData::PVStructure::const_shared_pointer
rpc(double timeout,
const epics::pvData::PVStructure::const_shared_pointer& arguments,
@ -182,8 +215,15 @@ public:
epics::pvData::PVStructure::const_shared_pointer root;
epics::pvData::BitSet& tosend;
};
//! Called to build the value to be sent once the type info is known
/** Server provides expected structure.
*
* Implementation must instanciate (or re-use) a PVStructure into args.root,
* then initialize any necessary fields and set bits in args.tosend as approprate.
*
* If this method throws, then putDone() is called with PutEvent::Fail
*/
virtual void putBuild(const epics::pvData::StructureConstPtr& build, Args& args) =0;
//! Put operation is complete
virtual void putDone(const PutEvent& evt)=0;
};
@ -193,8 +233,16 @@ public:
Operation put(PutCallback* cb,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
//! Monitor event notification
struct epicsShareClass MonitorCallback {
virtual ~MonitorCallback() {}
/** New monitor event
*
* - MonitorEvent::Fail - An Error occurred. Check evt.message
* - MonitorEvent::Cancel - Monitor::cancel() called
* - MonitorEvent::Disconnect - Underlying ClientChannel becomes disconnected
* - MonitorEvent::Data - FIFO becomes not empty.Call Monitor::poll()
*/
virtual void monitorEvent(const MonitorEvent& evt)=0;
};
@ -225,16 +273,25 @@ class epicsShareClass ClientProvider
std::tr1::shared_ptr<Impl> impl;
public:
/** Use named provider.
*
* @param providerName ChannelProvider name, may be prefixed with "clients:" or "servers:" to query
* epics::pvAccess::ChannelProviderRegistry::clients() or
* epics::pvAccess::ChannelProviderRegistry::servers().
* No prefix implies "clients:".
*/
ClientProvider(const std::string& providerName,
const std::tr1::shared_ptr<epics::pvAccess::Configuration>& conf = std::tr1::shared_ptr<epics::pvAccess::Configuration>());
const std::tr1::shared_ptr<epics::pvAccess::Configuration>& conf = std::tr1::shared_ptr<epics::pvAccess::Configuration>());
~ClientProvider();
//! Get a new Channel
//! Does not block.
//! Never returns NULL.
//! Uses internal Channel cache.
/** Get a new Channel
*
* Does not block.
* Never returns NULL.
* Uses internal Channel cache.
*/
ClientChannel connect(const std::string& name,
const ClientChannel::Options& conf = ClientChannel::Options());
const ClientChannel::Options& conf = ClientChannel::Options());
//! Remove from channel cache
bool disconnect(const std::string& name,