3 Commits

Author SHA1 Message Date
Dave Hickin 1ba091524a Add release notes for 4.1.2 2016-01-28 18:38:39 +00:00
Dave Hickin d2d390a852 Correct comment in RELEASE 2016-01-28 18:00:15 +00:00
Dave Hickin 63ee062e9c Add libraries needed for static builds
(cherry picked from commit 7f972fc877)
2016-01-28 17:51:40 +00:00
58 changed files with 3581 additions and 2917 deletions
-1
View File
@@ -10,4 +10,3 @@ envPaths
configure/*.local configure/*.local
!configure/ExampleRELEASE.local !configure/ExampleRELEASE.local
**/O.* **/O.*
QtC-*
+149 -238
View File
@@ -1,4 +1,4 @@
# Doxyfile 1.8.10 # Doxyfile 1.8.6
# This file describes the settings to be used by the documentation system # This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project. # doxygen (www.doxygen.org) for a project.
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places. # title of most generated pages and in a few other places.
# The default value is: My Project. # The default value is: My Project.
PROJECT_NAME = pvaClientCPP PROJECT_NAME = easyPVACPP
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
@@ -46,10 +46,10 @@ PROJECT_NUMBER =
PROJECT_BRIEF = PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included # With the PROJECT_LOGO tag one can specify an logo or icon that is included in
# in the documentation. The maximum height of the logo should not exceed 55 # the documentation. The maximum height of the logo should not exceed 55 pixels
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
# the logo to the output directory. # to the output directory.
PROJECT_LOGO = PROJECT_LOGO =
@@ -60,7 +60,7 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and # directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this # will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where # option can be useful when feeding doxygen a huge amount of source files, where
@@ -70,14 +70,6 @@ OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all # The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this # documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language. # information to generate all constant output in the proper language.
@@ -93,14 +85,14 @@ ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
# descriptions after the members that are listed in the file and class # descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this. # documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES. # The default value is: YES.
BRIEF_MEMBER_DESC = YES BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
# description of a member or function before the detailed description # description of a member or function before the detailed description
# #
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@@ -135,7 +127,7 @@ ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = YES INLINE_INHERITED_MEMB = YES
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the # before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used # shortest path that makes the file name unique will be used
# The default value is: YES. # The default value is: YES.
@@ -177,7 +169,7 @@ SHORT_NAMES = NO
# description.) # description.)
# The default value is: NO. # The default value is: NO.
JAVADOC_AUTOBRIEF = NO JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If # line (until the first dot) of a Qt-style comment as the brief description. If
@@ -205,9 +197,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
# page for each member. If set to NO, the documentation of a member will be part # new page for each member. If set to NO, the documentation of a member will be
# of the file/class/namespace that contains it. # part of the file/class/namespace that contains it.
# The default value is: NO. # The default value is: NO.
SEPARATE_MEMBER_PAGES = NO SEPARATE_MEMBER_PAGES = NO
@@ -269,14 +261,11 @@ OPTIMIZE_OUTPUT_VHDL = NO
# extension. Doxygen has a built-in mapping, but you can override or extend it # extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and # using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript, # language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
# Fortran. In the later case the parser tries to guess whether the code is fixed # (default is Fortran), use: inc=Fortran f=C.
# or free formatted code, this is the default for Fortran type files), VHDL. For
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
# #
# Note: For files without extension you can use no_extension as a placeholder. # Note For files without extension you can use no_extension as a placeholder.
# #
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen. # the files are not read by doxygen.
@@ -295,8 +284,8 @@ MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented # When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can # classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or # be prevented in individual cases by by putting a % sign in front of the word
# globally by setting AUTOLINK_SUPPORT to NO. # or globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES. # The default value is: YES.
AUTOLINK_SUPPORT = YES AUTOLINK_SUPPORT = YES
@@ -336,20 +325,13 @@ SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first # tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default # member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly. # all members of a group must be documented explicitly.
# The default value is: NO. # The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO DISTRIBUTE_GROUP_DOC = NO
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
GROUP_NESTED_COMPOUNDS = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type # Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that # (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent # type (e.g. under the Public Functions section). Set it to NO to prevent
@@ -408,7 +390,7 @@ LOOKUP_CACHE_SIZE = 0
# Build related configuration options # Build related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private # documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the # class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -418,35 +400,35 @@ LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = YES EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
# be included in the documentation. # be included in the documentation.
# The default value is: NO. # The default value is: NO.
EXTRACT_PRIVATE = NO EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
# scope will be included in the documentation. # scope will be included in the documentation.
# The default value is: NO. # The default value is: NO.
EXTRACT_PACKAGE = NO EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # If the EXTRACT_STATIC tag is set to YES all static members of a file will be
# included in the documentation. # included in the documentation.
# The default value is: NO. # The default value is: NO.
EXTRACT_STATIC = NO EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO, # locally in source files will be included in the documentation. If set to NO
# only classes defined in header files are included. Does not have any effect # only classes defined in header files are included. Does not have any effect
# for Java sources. # for Java sources.
# The default value is: YES. # The default value is: YES.
EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_CLASSES = NO
# This flag is only useful for Objective-C code. If set to YES, local methods, # This flag is only useful for Objective-C code. When set to YES local methods,
# which are defined in the implementation section but not in the interface are # which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO, only methods in the interface are # included in the documentation. If set to NO only methods in the interface are
# included. # included.
# The default value is: NO. # The default value is: NO.
@@ -471,21 +453,21 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set # undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option # to NO these classes will be included in the various overviews. This option has
# has no effect if EXTRACT_ALL is enabled. # no effect if EXTRACT_ALL is enabled.
# The default value is: NO. # The default value is: NO.
HIDE_UNDOC_CLASSES = NO HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be # (class|struct|union) declarations. If set to NO these declarations will be
# included in the documentation. # included in the documentation.
# The default value is: NO. # The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these # documentation blocks found inside the body of a function. If set to NO these
# blocks will be appended to the function's detailed documentation block. # blocks will be appended to the function's detailed documentation block.
# The default value is: NO. # The default value is: NO.
@@ -499,7 +481,7 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also # names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ # allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows # in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO. # and Mac users are advised to set this option to NO.
@@ -508,19 +490,12 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the # their full class and namespace scopes in the documentation. If set to YES the
# scope will be hidden. # scope will be hidden.
# The default value is: NO. # The default value is: NO.
HIDE_SCOPE_NAMES = NO HIDE_SCOPE_NAMES = NO
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file. # the files that are included by a file in the documentation of that file.
# The default value is: YES. # The default value is: YES.
@@ -548,14 +523,14 @@ INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member # (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. # name. If set to NO the members will appear in declaration order.
# The default value is: YES. # The default value is: YES.
SORT_MEMBER_DOCS = YES SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member # descriptions of file, namespace and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. Note that # name. If set to NO the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list. # this will also influence the order of the classes in the class list.
# The default value is: NO. # The default value is: NO.
@@ -600,25 +575,27 @@ SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
# list. This list is created by putting \todo commands in the documentation. # todo list. This list is created by putting \todo commands in the
# documentation.
# The default value is: YES. # The default value is: YES.
GENERATE_TODOLIST = YES GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
# list. This list is created by putting \test commands in the documentation. # test list. This list is created by putting \test commands in the
# documentation.
# The default value is: YES. # The default value is: YES.
GENERATE_TESTLIST = YES GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
# list. This list is created by putting \bug commands in the documentation. # list. This list is created by putting \bug commands in the documentation.
# The default value is: YES. # The default value is: YES.
GENERATE_BUGLIST = YES GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
# the deprecated list. This list is created by putting \deprecated commands in # the deprecated list. This list is created by putting \deprecated commands in
# the documentation. # the documentation.
# The default value is: YES. # The default value is: YES.
@@ -643,8 +620,8 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30 MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the # the bottom of the documentation of classes and structs. If set to YES the list
# list will mention the files that were used to generate the documentation. # will mention the files that were used to generate the documentation.
# The default value is: YES. # The default value is: YES.
SHOW_USED_FILES = YES SHOW_USED_FILES = YES
@@ -692,7 +669,8 @@ LAYOUT_FILE =
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using # For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references. # search path. Do not use file names with spaces, bibtex cannot handle them. See
# also \cite for info how to create references.
CITE_BIB_FILES = CITE_BIB_FILES =
@@ -708,7 +686,7 @@ CITE_BIB_FILES =
QUIET = NO QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are # The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on. # this implies that the warnings are on.
# #
# Tip: Turn warnings on while writing the documentation. # Tip: Turn warnings on while writing the documentation.
@@ -716,7 +694,7 @@ QUIET = NO
WARNINGS = YES WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled. # will automatically be disabled.
# The default value is: YES. # The default value is: YES.
@@ -733,8 +711,8 @@ WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return # are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete # value. If set to NO doxygen will only warn about wrong or incomplete parameter
# parameter documentation, but not about the absence of documentation. # documentation, but not about the absence of documentation.
# The default value is: NO. # The default value is: NO.
WARN_NO_PARAMDOC = NO WARN_NO_PARAMDOC = NO
@@ -762,7 +740,7 @@ WARN_LOGFILE =
# The INPUT tag is used to specify the files and/or directories that contain # The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or # documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with # directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces.
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = include INPUT = include
@@ -778,17 +756,12 @@ INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the # If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories. # *.h) to filter out the source-files in the directories. If left blank the
# # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
# Note that for custom extensions or not directly supported extensions you also # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
# need to set EXTENSION_MAPPING for the extension otherwise the files are not # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
# read by doxygen. # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
# # *.qsf, *.as and *.js.
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
# *.vhdl, *.ucf, *.qsf, *.as and *.js.
FILE_PATTERNS = FILE_PATTERNS =
@@ -887,7 +860,7 @@ INPUT_FILTER =
FILTER_PATTERNS = FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for # INPUT_FILTER ) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO. # The default value is: NO.
@@ -947,7 +920,7 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and # to YES, then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation. # link to the documentation.
# The default value is: YES. # The default value is: YES.
@@ -1024,7 +997,7 @@ IGNORE_PREFIX =
# Configuration options related to the HTML output # Configuration options related to the HTML output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
# The default value is: YES. # The default value is: YES.
GENERATE_HTML = YES GENERATE_HTML = YES
@@ -1086,15 +1059,13 @@ HTML_FOOTER =
HTML_STYLESHEET = HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
# cascading style sheets that are included after the standard style sheets # defined cascading style sheet that is included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects. # created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the # This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefore more robust against future updates. # standard style sheet and is therefor more robust against future updates.
# Doxygen will copy the style sheet files to the output directory. # Doxygen will copy the style sheet file to the output directory. For an example
# Note: The order of the extra style sheet files is of importance (e.g. the last # see the documentation.
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = HTML_EXTRA_STYLESHEET =
@@ -1107,10 +1078,10 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available. # files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES = HTML_EXTRA_FILES = documentation/overview.html
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to # will adjust the colors in the stylesheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see # this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value # http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
@@ -1141,9 +1112,8 @@ HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this # page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the # to NO can help when comparing the output of multiple runs.
# documentation is up to date. # The default value is: YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES HTML_TIMESTAMP = YES
@@ -1239,29 +1209,28 @@ GENERATE_HTMLHELP = NO
CHM_FILE = CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path # The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty, # including file name) of the HTML help compiler ( hhc.exe). If non-empty
# doxygen will try to run the HTML help compiler on the generated index.hhp. # doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path. # The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION = HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated # The GENERATE_CHI flag controls if a separate .chi index file is generated (
# (YES) or that it should be included in the master .chm file (NO). # YES) or that it should be included in the master .chm file ( NO).
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
# and project file content. # and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING = CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated # The BINARY_TOC flag controls whether a binary table of contents is generated (
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # YES) or a normal table of contents ( NO) in the .chm file.
# enables the Previous and Next buttons.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1374,7 +1343,7 @@ DISABLE_INDEX = NO
# index structure (just like the one that is generated for HTML Help). For this # index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required # to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the # (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style # further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at # sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@@ -1402,7 +1371,7 @@ ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250 TREEVIEW_WIDTH = 250
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
# external symbols imported via tag files in a separate window. # external symbols imported via tag files in a separate window.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1431,7 +1400,7 @@ FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering # http://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # instead of using prerendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When # installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path # enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option. # to it using the MATHJAX_RELPATH option.
@@ -1501,11 +1470,11 @@ SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There # implemented using a web server instead of a web client using Javascript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH # are two flavours of web server based searching depending on the
# setting. When disabled, doxygen will generate a PHP script for searching and # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing # searching and an index file used by the script. When EXTERNAL_SEARCH is
# and searching needs to be provided by external tools. See the section # enabled the indexing and searching needs to be provided by external tools. See
# "External Indexing and Searching" for details. # the section "External Indexing and Searching" for details.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES. # This tag requires that the tag SEARCHENGINE is set to YES.
@@ -1517,7 +1486,7 @@ SERVER_BASED_SEARCH = NO
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the # external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results. # search results.
# #
# Doxygen ships with an example indexer (doxyindexer) and search engine # Doxygen ships with an example indexer ( doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). # Xapian (see: http://xapian.org/).
# #
@@ -1530,7 +1499,7 @@ EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server # The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled. # which will return the search results when EXTERNAL_SEARCH is enabled.
# #
# Doxygen ships with an example indexer (doxyindexer) and search engine # Doxygen ships with an example indexer ( doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library # (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and # Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details. # Searching" for details.
@@ -1568,7 +1537,7 @@ EXTRA_SEARCH_MAPPINGS =
# Configuration options related to the LaTeX output # Configuration options related to the LaTeX output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
# The default value is: YES. # The default value is: YES.
GENERATE_LATEX = NO GENERATE_LATEX = NO
@@ -1599,7 +1568,7 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some # documents. This may be useful for small projects and may help to save some
# trees in general. # trees in general.
# The default value is: NO. # The default value is: NO.
@@ -1617,12 +1586,9 @@ COMPACT_LATEX = NO
PAPER_TYPE = a4wide PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. The package can be specified just # that should be included in the LaTeX output. To get the times font for
# by its name or with the correct syntax as to be used with the LaTeX # instance you can specify
# \usepackage command. To get the times font for instance you can specify : # EXTRA_PACKAGES=times
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
# To use the option intlimits with the amsmath package you can specify:
# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included. # If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1636,36 +1602,23 @@ EXTRA_PACKAGES =
# #
# Note: Only use a user-defined header if you know what you are doing! The # Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title, # following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber, # $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty # replace them by respectively the title of the page, the current date and time,
# string, for the replacement values of the other commands the user is referred # only the current date, the version number of doxygen, the project name (see
# to HTML_HEADER. # PROJECT_NAME), or the project number (see PROJECT_NUMBER).
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER = LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last # generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See # chapter. If it is left blank doxygen will generate a standard footer.
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
# #
# Note: Only use a user-defined footer if you know what you are doing! # Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER = LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
# will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output # other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or # directory. Note that the files will be copied as-is; there are no commands or
@@ -1683,8 +1636,8 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = NO PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate # If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a # the PDF file directly from the LaTeX files. Set this option to YES to get a
# higher quality PDF documentation. # higher quality PDF documentation.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1725,19 +1678,11 @@ LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the RTF output # Configuration options related to the RTF output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The # If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF # RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors. # readers/editors.
# The default value is: NO. # The default value is: NO.
@@ -1752,7 +1697,7 @@ GENERATE_RTF = NO
RTF_OUTPUT = rtf RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF # If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some # documents. This may be useful for small projects and may help to save some
# trees in general. # trees in general.
# The default value is: NO. # The default value is: NO.
@@ -1789,21 +1734,11 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE = RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the man page output # Configuration options related to the man page output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for # If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
# classes and files. # classes and files.
# The default value is: NO. # The default value is: NO.
@@ -1827,13 +1762,6 @@ MAN_OUTPUT = man
MAN_EXTENSION = .3 MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real # will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without # man page(s). These additional files only source the real man page, but without
@@ -1847,7 +1775,7 @@ MAN_LINKS = NO
# Configuration options related to the XML output # Configuration options related to the XML output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that # If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
# captures the structure of the code including all documentation. # captures the structure of the code including all documentation.
# The default value is: NO. # The default value is: NO.
@@ -1861,7 +1789,19 @@ GENERATE_XML = NO
XML_OUTPUT = xml XML_OUTPUT = xml
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
# validating XML parser to check the syntax of the XML files.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_SCHEMA =
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
# validating XML parser to check the syntax of the XML files.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to # listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size # the XML output. Note that enabling this will significantly increase the size
# of the XML output. # of the XML output.
@@ -1874,7 +1814,7 @@ XML_PROGRAMLISTING = YES
# Configuration options related to the DOCBOOK output # Configuration options related to the DOCBOOK output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files # If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
# that can be used to generate PDF. # that can be used to generate PDF.
# The default value is: NO. # The default value is: NO.
@@ -1888,23 +1828,14 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output # Configuration options for the AutoGen Definitions output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an # If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
# AutoGen Definitions (see http://autogen.sf.net) file that captures the # Definitions (see http://autogen.sf.net) file that captures the structure of
# structure of the code including all documentation. Note that this feature is # the code including all documentation. Note that this feature is still
# still experimental and incomplete at the moment. # experimental and incomplete at the moment.
# The default value is: NO. # The default value is: NO.
GENERATE_AUTOGEN_DEF = NO GENERATE_AUTOGEN_DEF = NO
@@ -1913,7 +1844,7 @@ GENERATE_AUTOGEN_DEF = NO
# Configuration options related to the Perl module output # Configuration options related to the Perl module output
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module # If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
# file that captures the structure of the code including all documentation. # file that captures the structure of the code including all documentation.
# #
# Note that this feature is still experimental and incomplete at the moment. # Note that this feature is still experimental and incomplete at the moment.
@@ -1921,7 +1852,7 @@ GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary # If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output. # output from the Perl module output.
# The default value is: NO. # The default value is: NO.
@@ -1929,9 +1860,9 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to # formatted so it can be parsed by a human reader. This is useful if you want to
# understand what is going on. On the other hand, if this tag is set to NO, the # understand what is going on. On the other hand, if this tag is set to NO the
# size of the Perl module output will be much smaller and Perl will parse it # size of the Perl module output will be much smaller and Perl will parse it
# just the same. # just the same.
# The default value is: YES. # The default value is: YES.
@@ -1951,14 +1882,14 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor # Configuration options related to the preprocessor
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all # If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
# C-preprocessor directives found in the sources and include files. # C-preprocessor directives found in the sources and include files.
# The default value is: YES. # The default value is: YES.
ENABLE_PREPROCESSING = YES ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names # If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be # in the source code. If set to NO only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting # performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES. # EXPAND_ONLY_PREDEF to YES.
# The default value is: NO. # The default value is: NO.
@@ -1974,7 +1905,7 @@ MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES, the include files in the # If the SEARCH_INCLUDES tag is set to YES the includes files in the
# INCLUDE_PATH will be searched if a #include is found. # INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2016,9 +1947,9 @@ PREDEFINED =
EXPAND_AS_DEFINED = EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have # remove all refrences to function-like macros that are alone on a line, have an
# an all uppercase name, and do not end with a semicolon. Such function macros # all uppercase name, and do not end with a semicolon. Such function macros are
# are typically used for boiler-plate code, and will confuse the parser if not # typically used for boiler-plate code, and will confuse the parser if not
# removed. # removed.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2038,7 +1969,7 @@ SKIP_FUNCTION_MACROS = YES
# where loc1 and loc2 can be relative or absolute paths or URLs. See the # where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use # section "Linking to external documentation" for more information about the use
# of tag files. # of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include # Note: Each tag file must have an unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is # 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. # run, you must also specify the path to the tagfile here.
@@ -2050,21 +1981,20 @@ TAGFILES =
GENERATE_TAGFILE = GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in # If the ALLEXTERNALS tag is set to YES all external class will be listed in the
# the class index. If set to NO, only the inherited external classes will be # class index. If set to NO only the inherited external classes will be listed.
# listed.
# The default value is: NO. # The default value is: NO.
ALLEXTERNALS = NO ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
# in the modules index. If set to NO, only the current project's groups will be # the modules index. If set to NO, only the current project's groups will be
# listed. # listed.
# The default value is: YES. # The default value is: YES.
EXTERNAL_GROUPS = YES EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in # 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 # the related pages index. If set to NO, only the current project's pages will
# be listed. # be listed.
# The default value is: YES. # The default value is: YES.
@@ -2081,7 +2011,7 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool # Configuration options related to the dot tool
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram # If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT # NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more # disabled, but it is recommended to install and use dot, since it yields more
@@ -2106,7 +2036,7 @@ MSCGEN_PATH =
DIA_PATH = DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance # If set to YES, the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class. # and usage relations if the target is undocumented or is not a class.
# The default value is: YES. # The default value is: YES.
@@ -2131,7 +2061,7 @@ HAVE_DOT = NO
DOT_NUM_THREADS = 0 DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen # When you want a differently looking font n the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make # generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a # sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by # standard location or by setting the DOTFONTPATH environment variable or by
@@ -2179,7 +2109,7 @@ COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling # collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language. # Language.
# The default value is: NO. # The default value is: NO.
@@ -2231,8 +2161,7 @@ INCLUDED_BY_GRAPH = YES
# #
# Note that enabling this option will significantly increase the time of a run. # Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected # So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command. Disabling a call graph can be # functions only using the \callgraph command.
# accomplished by means of the command \hidecallgraph.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@@ -2243,8 +2172,7 @@ CALL_GRAPH = NO
# #
# Note that enabling this option will significantly increase the time of a run. # Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected # So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command. Disabling a caller graph can be # functions only using the \callergraph command.
# accomplished by means of the command \hidecallergraph.
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@@ -2267,15 +2195,11 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section # generated by dot.
# output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this # to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement). # requirement).
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, # Possible values are: png, jpg, gif and svg.
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png. # The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
@@ -2318,19 +2242,6 @@ MSCFILE_DIRS =
DIAFILE_DIRS = DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
PLANTUML_JAR_PATH =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes # that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized # larger than this value, doxygen will truncate the graph, which is visualized
@@ -2367,7 +2278,7 @@ MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This # files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support # makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default. # this, this feature is disabled by default.
@@ -2384,7 +2295,7 @@ DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot # If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
# files that are used to generate the various graphs. # files that are used to generate the various graphs.
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES. # This tag requires that the tag HAVE_DOT is set to YES.
+44 -31
View File
@@ -1,17 +1,12 @@
Copyright and License Terms
---------------------------
Copyright (c) 2006-2016 Martin R. Kraimer Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006-2016 UChicago Argonne LLC, as Operator of Argonne Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory. National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchrotron, Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007-2016 Control System Laboratory, Copyright (c) 2007 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia (COSYLAB) Ljubljana Slovenia
Copyright (c) 2010-2016 Brookhaven Science Associates, as Operator
of Brookhaven National Laboratory
Copyright (c) 2011-2016 Diamond Light Source Limited,
(DLS) Didcot, United Kingdom
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation
@@ -36,30 +31,48 @@ OTHER DEALINGS IN THE SOFTWARE.
________________________________________________________________________ ________________________________________________________________________
Additional Disclaimers This software is in part copyrighted by the University of Chicago (UofC)
----------------------
This software is copyright in part by these institutions: In no event shall UofC be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
UofC has been advised of the possibility of such damage.
* Brookhaven Science Associates, as Operator of Brookhaven UofC specifically disclaims any warranties, including, but not limited
National Laboratory, New York, USA to, the implied warranties of merchantability, fitness for a particular
* Control System Laboratory, Ljubljana, Slovenia purpose, and non-infringement. This software is provided on an "as is"
* Deutsches Elektronen-Synchroton, Member of the Helmholtz basis, and UofC has no obligation to provide maintenance, support,
Association, Hamburg, Germany updates, enhancements, or modifications.
* Diamond Light Source Limited, Didcot, United Kingdom
* Helmholtz-Zentrum Berlin fuer Materialien und Energie m.b.H.,
Berlin, Germany.
* UChicage Argonne LLC, as Operator of Argonne National Laboratory,
Illinois, USA
In no event shall these institutions be liable to any party for direct, ________________________________________________________________________
indirect, special, incidental, or consequential damages arising out of
the use of this software, its documentation, or any derivatives thereof,
even if advised of the possibility of such damage.
These institutions specifically disclaim any warranties, including, but This software is in part copyrighted by the BERLINER SPEICHERRING
not limited to, the implied warranties of merchantability, fitness for a GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. (BESSY), BERLIN, GERMANY.
particular purpose, and non-infringement. This software is provided on
an "as is" basis, and these institutions have no obligation to provide
maintenance, support, updates, enhancements, or modifications.
In no event shall BESSY be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
BESSY has been advised of the possibility of such damage.
BESSY specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and BESSY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the Deutsches Elektronen-Synchroton,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
In no event shall DESY be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
DESY has been advised of the possibility of such damage.
DESY specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and DESY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
+14 -4
View File
@@ -1,10 +1,20 @@
#Makefile at top of application tree #Makefile at top of application tree
TOP = . TOP = .
include $(TOP)/configure/CONFIG include $(TOP)/configure/CONFIG
DIRS += configure DIRS := $(DIRS) $(filter-out $(DIRS), configure)
DIRS := $(DIRS) $(filter-out $(DIRS), src)
DIRS := $(DIRS) $(filter-out $(DIRS), example)
DIRS += src EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), example)
src_DEPEND_DIRS = configure
define DIR_template
$(1)_DEPEND_DIRS = configure
endef
$(foreach dir, $(filter-out configure,$(DIRS)),$(eval $(call DIR_template,$(dir))))
define EMB_template
$(1)_DEPEND_DIRS = src
endef
$(foreach dir, $(EMBEDDED_TOPS),$(eval $(call EMB_template,$(dir))))
include $(TOP)/configure/RULES_TOP include $(TOP)/configure/RULES_TOP
+10 -9
View File
@@ -15,22 +15,23 @@ then just type:
make make
It can also be built by: If RELEASE.local does not exist then look at <b>configure/RELEASE</b>
for directions for how to build.
cp configure/ExampleRELEASE.local configure/RELEASE.local
edit configure/RELEASE.local
make
Examples Examples
------------ ------------
Project exampleCPP has examples for pvaClientCPP The examples require the database in pvaClientTestCPP.
For example:
mrk> pwd
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
Status Status
------ ------
* The API is for EPICS Version 4 release 4.6.0 * The API is for EPICS Version 4 release 4.5.0
* Everything defined in pvaClient.h is ready but see below for remaining work. * Everything defined in pvaClient.h is ready but see below for remaining work.
* Everything defined in pvaClientMultiChannel.h is ready but see below for remaining work. * Everything defined in pvaClientMultiChannel.h is ready but see below for remaining work.
@@ -38,7 +39,7 @@ Status
pvaClientChannel pvaClientChannel
--------------- ---------------
Channel::getField and channelArray are not supported for release 4.6 Channel::getField and channelArray are not supported for release 4.5
pvaClientMultiChannel pvaClientMultiChannel
--------------- ---------------
+21
View File
@@ -0,0 +1,21 @@
Release 4.1.2
=============
The only change since release 4.1.1 is:
Added libraries needed for static builds
----------------------------------------
The missing ca and nt libraries needed for static builds have been added to
each of the examples.
Release 4.1.1
=============
pvaClient is a synchronous API for pvAccess.
This is the first release of pvaClientCPP.
It provides an API that is similar to pvaClientJava.
+3
View File
@@ -20,5 +20,8 @@
# INSTALL_LOCATION here. # INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top> #INSTALL_LOCATION=</path/name/to/install/top>
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../CONFIG_SITE.local -include $(TOP)/../CONFIG_SITE.local
-include $(TOP)/configure/CONFIG_SITE.local -include $(TOP)/configure/CONFIG_SITE.local
+6 -5
View File
@@ -1,8 +1,9 @@
EPICS4_DIR=/home/epicsv4/master
PVACCESS=${EPICS4_DIR}/pvAccessCPP
NORMATIVETYPES=${EPICS4_DIR}/normativeTypesCPP
PVDATA=${EPICS4_DIR}/pvDataCPP
PVCOMMON=${EPICS4_DIR}/pvCommonCPP
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
EPICS_BASE=/home/install/epics/base EPICS_BASE=/home/install/epics/base
V4BASE=/home/epicsv4
PVCOMMON=${V4BASE}/pvCommonCPP
PVDATA=${V4BASE}/pvDataCPP
NORMATIVETYPES=${V4BASE}/normativeTypesCPP
PVACCESS=${V4BASE}/pvAccessCPP
+1 -1
View File
@@ -21,7 +21,7 @@
# EPICS4_DIR=/home/epicsv4 # EPICS4_DIR=/home/epicsv4
# PVCOMMON=${EPICS4_DIR}/pvCommonCPP # PVCOMMON=${EPICS4_DIR}/pvCommonCPP
# PVDATA=${EPICS4_DIR}/pvDataCPP # PVDATA=${EPICS4_DIR}/pvDataCPP
# NORMATIVETYPES=${EPICSV4}/normativeTypesCPP # NORMATIVETYPES=${EPICS4_DIR}/normativeTypesCPP
# PVACCESS=${EPICS4_DIR}/pvAccessCPP # PVACCESS=${EPICS4_DIR}/pvAccessCPP
#Either create a RELEASE.local one level above the TOP for this module #Either create a RELEASE.local one level above the TOP for this module
#OR copy ExampleRELEASE.local to RELEASE.local and edit it. #OR copy ExampleRELEASE.local to RELEASE.local and edit it.
-19
View File
@@ -1,19 +0,0 @@
EPICS V4 release 4.6
==========================
* The examples are moved to exampleCPP.
* Support for channelRPC is now available.
* In PvaClientMultiChannel checkConnected() now throws an exception if connect fails.
EPICS V4 release 4.5
==========================
pvaClient is a synchronous API for pvAccess.
This is the first release of pvaClientCPP.
It provides an API that is similar to pvaClientJava.
+103 -36
View File
@@ -26,7 +26,25 @@
<div class="head"> <div class="head">
<h1>EPICS pvaClientCPP</h1> <h1>EPICS pvaClientCPP</h1>
<h2 class="nocount">Release 4.2.1 - 2016-08-26</h2> <!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
02-October-2015</h2>
<dl>
<dt>This version:</dt>
<dd><a
href="pvaClientCPP.html">pvaClientCPP.html
</a> </dd>
<dt>Latest version:</dt>
<dd><a
href="pvaClientCPP_20151002.html">pvaClientCPP_20151002.html
</a> </dd>
<dt>Previous version:</dt>
<dd><a
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
</a> </dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
</dl>
<h2 class="nocount">Abstract</h2> <h2 class="nocount">Abstract</h2>
@@ -60,6 +78,11 @@ The data for the channels is presented via normative type NTMultiChannel.
Control System</a>.</p> Control System</a>.</p>
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
<p>pvaClientCPP is ready for use.</p>
</div> <!-- head --> </div> <!-- head -->
<div id="toc"> <div id="toc">
@@ -69,51 +92,95 @@ The data for the channels is presented via normative type NTMultiChannel.
<!-- Place what you would like in the Table of Contents, inside the contents div --> <!-- Place what you would like in the Table of Contents, inside the contents div -->
<div id="contents" class="contents"> <div id="contents" class="contents">
<hr /> <hr />
<h2>Overview</h2>
<h2>Introduction</h2>
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
an interface to many of the features provided by pvData and pvAccess.</p>
<p>This document describes the layout of the source files in this project.</p>
<p> <p>
pvaClientCPP is one of the components of A user overview is available via
<a href="http://epics-pvdata.sourceforge.net"> <a
EPICS Version 4 href="./pvaClientOverview.html">pvaClientOverview.html
</a> </a>
</p> </p>
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
</p>
<p> <p>
It is intended for developers that want to use pvDatabaseCPP. Doxygen documentation is available at
</p>
<h2>Developer Guide</h2>
<p>A guide for developers is available at
<a <a
href="http://epics-pvdata.sourceforge.net/informative/developerGuide/developerGuide.html"> href="./html/index.html">doxygenDoc
developerGuide
</a> </a>
</p> </p>
<p>This guide discusses all the components that are part of an <b>EPICS V4</b> release. <h2>Example Database</h2>
Some understanding of the components and how they are related is necessary in order to <p>The examples require that the database provided by project pvaClientTestCPP
develop code that uses pvDatabaseCPP. is running.
In particular read everything related to pvaClient. For example:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
mrk&gt; ../../bin/linux-x86_64/exampleDatabase st.cmd
</pre>
<h2>Examples</h2>
<p>Examples are in directory <b>example/src</b>.
An example of how to run them is:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientCPP/example
mrk&gt; bin/linux-x86_64/examplePvaClientGet
</pre>
<p>The following is a brief description of each example.
In order to understand each example it
helps to also look at the source for the example.</p>
<h2>examplePvaClientGet</h2>
<p>This has a number of examples:</p>
<dl>
<dt>exampleDouble</dt>
<dd>
This shows two methods for getting data from a channel that has a numeric
scalar value field.
</dd>
<dt>exampleDoubleArray</dt>
<dd>
This shows two methods for getting data from a channel that has a
double array value field.
</dd>
<dt>exampleCADouble</dt>
<dd>
This is like exampleDouble except it uses provider <b>ca</b>.
</dd>
<dt>exampleCADoubleArray</dt>
<dd>
This is like exampleDoubleArray except it uses provider <b>ca</b>.
</dd>
<dt>examplePowerSupply</dt>
<dd>
This is an example of getting data from a channel that does not
have a value field.
</dd>
</dl>
<h2>examplePvaClientMonitor</h2>
<p>This is an example of creating a monitor on a channel.
It monitors a scalar double field.
It also issues puts to the same channel so that it can make the monitors occur.
</p> </p>
<p>The developerGuide discusses code in a way that applies to both CPP and C++. <h2>examplePvaClientPut</h2>
For the descriptions of the CPP specific code consult the next section. <p>This example gets and puts to channels exampleDouble
and exampleDoubleArray.</p>
<h2>examplePvaClientProcess</h2>
<p>This example makes a process request to channel exampleDouble.</p>
<h2>helloWorldPutGet</h2>
<p>This is an example of issuing a channelPutGet.</p>
<h2>examplePvaClientMultiDouble</h2>
<p>This is an example of using pvaClientMultiChannel,
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
</p> </p>
<h2>examplePvaClientNTMulti</h2>
<h2>doxygen</h2> <p>This is an example of using pvaClientMultiChannel,
<p>doxygen documentation is available at pvaClientNTMultiGet, pvaClientNTMultiPut, pvaClientNTMultiMonitor, and pvaClientNTMultiData.
<a
href="./html/index.html">doxygen</a>
</p> </p>
<h2>helloWorldRPC</h2>
<h2>exampleCPP</h2> <p>This is an example of issuing a channelRPC request.
<p>Example code is available as part of this release. It does <b>not</b> use pva.</p>
<a
href="http://epics-pvdata.sourceforge.net/docbuild/exampleCPP/tip/documentation/exampleCPP.html">
exampleCPP
</a>
</p>
<p>In particular look at exampleClient.
It has many examples of using pvaClientCPP.
</p>
</div> <!-- class="contents" --> </div> <!-- class="contents" -->
</body> </body>
</html> </html>
+199
View File
@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pva</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
body { margin-right: 10% }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
</head>
<body>
<div class="head">
<h1>EPICS pvaClientCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
26-June-2015</h2>
<dl>
<dt>This version:</dt>
<dd><a
href="pvaClientCPP.html">pvaClientCPP.html
</a> </dd>
<dt>Latest version:</dt>
<dd><a
href="pvaClientCPP_20150626.html">pvaClientCPP_20150626.html
</a> </dd>
<dt>Previous version:</dt>
<dd><a
href="easyPVA_20150609.html">easyPVA_20150609.html</a>
</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
</dl>
<h2 class="nocount">Abstract</h2>
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
client side programming interface to the data of an EPICS based control system. It is intended
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
scientists a way to directly develop analytical applications.</p>
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
software support for high speed controls network communications used in EPICS version 4.
pvAccess provides a callback based interface, which can be hard to use.
pvaClient provides an interface that does not require callbacks even for monitors.
</p>
pvaClientChannel provides many "convenience" methods to directly get and put
scalar and scalarArray data types.
Additional methods provide access to the full features of pvAccess.
</p>
<p>
pvaClientMultiChannel provides access to data from multiple channels.
It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
pvaClientMultiDouble allows the client to get and put data to multiple channels.
But each channel must have a value field that is a numeric scalar.
pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
Each channel must have a value field.
The data for the channels is presented via normative type NTMultiChannel.
</p>
<!-- last para of Abstract is boilerplate reference to EPICS -->
<p>For more information about EPICS generally, please refer to the home page of the <a
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
Control System</a>.</p>
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
<p>pvaClientCPP is ready for use.</p>
</div> <!-- head -->
<div id="toc">
<h2 class="nocount">Table of Contents</h2>
</div>
<!-- Place what you would like in the Table of Contents, inside the contents div -->
<div id="contents" class="contents">
<hr />
<h2>Introduction</h2>
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
an interface to many of the features provided by pvData and pvAccess.</p>
<p>This document describes the layout of the source files in this project.</p>
<p>
A user overview is available via
<a
href="./pvaClientOverview.html">pvaClientOverview.html
</a>
</p>
<p>
Doxygen documentation is available at
<a
href="./html/index.html">doxygenDoc
</a>
</p>
<h2>Example Database</h2>
<p>The examples require that an example pvAccess server is runnimg.
To get the test database go to:</p>
<a
href="https://github.com/epics_base/pvaClientTestCPP/blob/master/database.zip">pvaClientTestCPP/database.zip
</a>
Then select "raw file" and You will be able to download the zip file.
<p>
When unzipped this is used to create an example IOC database.
</p>
<p>
After unzipping the file:
</p>
<pre>
cd database/configure
cp ExampleRELEASE.local RELEASE.local
edit RELEASE.local
cd ..
make
cd iocBoot/exampleDatabase
../../bin/&lt;arch:&gt;/exampleDatabase st.cmd
</pre>
<h2>Examples</h2>
<p>Examples are in directory <b>example/src</b>.
An example of how to run them is:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientCPP/example
mrk&gt; bin/linux-x86_64/examplePvaClientGet
</pre>
<p>The following is a brief description of each example.
In order to understand each example it
helps to also look at the source for the example.</p>
<h2>examplePvaClientGet</h2>
<p>This has a number of examples:</p>
<dl>
<dt>exampleDouble</dt>
<dd>
This shows two methods for getting data from a channel that has a numeric
scalar value field.
</dd>
<dt>exampleDoubleArray</dt>
<dd>
This shows two methods for getting data from a channel that has a
double array value field.
</dd>
<dt>exampleCADouble</dt>
<dd>
This is like exampleDouble except it uses provider <b>ca</b>.
</dd>
<dt>exampleCADoubleArray</dt>
<dd>
This is like exampleDoubleArray except it uses provider <b>ca</b>.
</dd>
<dt>examplePowerSupply</dt>
<dd>
This is an example of getting data from a channel that does not
have a value field.
</dd>
</dl>
<h2>examplePvaClientMonitor</h2>
<p>This is an example of creating a monitor on a channel.
It monitors a channel that models a powerSupply, i. e. it is not a "standard" record.
It does not have a value field.
</p>
<p>After starting the example a change can be made to the powerSupply by issuing:</p>
<pre>
pvput -r "power.value,voltage.value" examplePowerSupply 6 6
</pre>
<h2>examplePvaClientPut</h2>
<p>This example gets and puts to channel exampleDouble.</p>
<h2>examplePvaClientProcess</h2>
<p>This example makes a process request to channel exampleDouble.</p>
<h2>helloWorldPutGet</h2>
<p>This is an example of issuing a channelPutGet.</p>
<h2>examplePvaClientMultiDouble</h2>
<p>This is an example of issuing gets and puts to multiple channels where each
channel has a numeric scalar value field.</p>
<h2>examplePvaClientNTMultiChannel</h2>
<p>This is an example of using NDMultiChannel to obtain data from multiple channels.
</p>
<h2>helloWorldRPC</h2>
<p>This is an example of issuing a channelRPC request.
It does <b>not</b> use pva.</p>
</div> <!-- class="contents" -->
</body>
</html>
+182
View File
@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pva</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
body { margin-right: 10% }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
</head>
<body>
<div class="head">
<h1>EPICS pvaClientCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
03-August-2015</h2>
<dl>
<dt>This version:</dt>
<dd><a
href="pvaClientCPP.html">pvaClientCPP.html
</a> </dd>
<dt>Latest version:</dt>
<dd><a
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
</a> </dd>
<dt>Previous version:</dt>
<dd><a
href="pvaClientCPP_20150626.html">pvaClientCPP_20150626.html
</a> </dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
</dl>
<h2 class="nocount">Abstract</h2>
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
client side programming interface to the data of an EPICS based control system. It is intended
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
scientists a way to directly develop analytical applications.</p>
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
software support for high speed controls network communications used in EPICS version 4.
pvAccess provides a callback based interface, which can be hard to use.
pvaClient provides an interface that does not require callbacks even for monitors.
</p>
<p>
pvaClientChannel provides many "convenience" methods to directly get and put
scalar and scalarArray data types.
Additional methods provide access to the full features of pvAccess.
</p>
<p>
pvaClientMultiChannel provides access to data from multiple channels.
It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
pvaClientMultiDouble allows the client to get and put data to multiple channels.
But each channel must have a value field that is a numeric scalar.
pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
Each channel must have a value field.
The data for the channels is presented via normative type NTMultiChannel.
</p>
<!-- last para of Abstract is boilerplate reference to EPICS -->
<p>For more information about EPICS generally, please refer to the home page of the <a
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
Control System</a>.</p>
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
<p>pvaClientCPP is ready for use.</p>
</div> <!-- head -->
<div id="toc">
<h2 class="nocount">Table of Contents</h2>
</div>
<!-- Place what you would like in the Table of Contents, inside the contents div -->
<div id="contents" class="contents">
<hr />
<h2>Introduction</h2>
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
an interface to many of the features provided by pvData and pvAccess.</p>
<p>This document describes the layout of the source files in this project.</p>
<p>
A user overview is available via
<a
href="./pvaClientOverview.html">pvaClientOverview.html
</a>
</p>
<p>
Doxygen documentation is available at
<a
href="./html/index.html">doxygenDoc
</a>
</p>
<h2>Example Database</h2>
<p>The examples require that the database provided by project pvaClientTestCPP
is running.
For example:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
mrk&gt; ../../bin/linux-x86_64/exampleDatabase st.cmd
</pre>
<h2>Examples</h2>
<p>Examples are in directory <b>example/src</b>.
An example of how to run them is:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientCPP/example
mrk&gt; bin/linux-x86_64/examplePvaClientGet
</pre>
<p>The following is a brief description of each example.
In order to understand each example it
helps to also look at the source for the example.</p>
<h2>examplePvaClientGet</h2>
<p>This has a number of examples:</p>
<dl>
<dt>exampleDouble</dt>
<dd>
This shows two methods for getting data from a channel that has a numeric
scalar value field.
</dd>
<dt>exampleDoubleArray</dt>
<dd>
This shows two methods for getting data from a channel that has a
double array value field.
</dd>
<dt>exampleCADouble</dt>
<dd>
This is like exampleDouble except it uses provider <b>ca</b>.
</dd>
<dt>exampleCADoubleArray</dt>
<dd>
This is like exampleDoubleArray except it uses provider <b>ca</b>.
</dd>
<dt>examplePowerSupply</dt>
<dd>
This is an example of getting data from a channel that does not
have a value field.
</dd>
</dl>
<h2>examplePvaClientMonitor</h2>
<p>This is an example of creating a monitor on a channel.
It monitors a scalar double field.
It also issues puts to the same channel so that it can make the monitors occur.
</p>
<h2>examplePvaClientPut</h2>
<p>This example gets and puts to channels exampleDouble
and exampleDoubleArray.</p>
<h2>examplePvaClientProcess</h2>
<p>This example makes a process request to channel exampleDouble.</p>
<h2>helloWorldPutGet</h2>
<p>This is an example of issuing a channelPutGet.</p>
<h2>examplePvaClientMultiDouble</h2>
<p>This is an example of using pvaClientMultiChannel,
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
</p>
<h2>helloWorldRPC</h2>
<p>This is an example of issuing a channelRPC request.
It does <b>not</b> use pva.</p>
</div> <!-- class="contents" -->
</body>
</html>
+186
View File
@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pva</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
body { margin-right: 10% }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
</head>
<body>
<div class="head">
<h1>EPICS pvaClientCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
02-October-2015</h2>
<dl>
<dt>This version:</dt>
<dd><a
href="pvaClientCPP.html">pvaClientCPP.html
</a> </dd>
<dt>Latest version:</dt>
<dd><a
href="pvaClientCPP_20151002.html">pvaClientCPP_20151002.html
</a> </dd>
<dt>Previous version:</dt>
<dd><a
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
</a> </dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
</dl>
<h2 class="nocount">Abstract</h2>
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
client side programming interface to the data of an EPICS based control system. It is intended
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
scientists a way to directly develop analytical applications.</p>
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
software support for high speed controls network communications used in EPICS version 4.
pvAccess provides a callback based interface, which can be hard to use.
pvaClient provides an interface that does not require callbacks even for monitors.
</p>
<p>
pvaClientChannel provides many "convenience" methods to directly get and put
scalar and scalarArray data types.
Additional methods provide access to the full features of pvAccess.
</p>
<p>
pvaClientMultiChannel provides access to data from multiple channels.
It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
pvaClientMultiDouble allows the client to get and put data to multiple channels.
But each channel must have a value field that is a numeric scalar.
pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
Each channel must have a value field.
The data for the channels is presented via normative type NTMultiChannel.
</p>
<!-- last para of Abstract is boilerplate reference to EPICS -->
<p>For more information about EPICS generally, please refer to the home page of the <a
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
Control System</a>.</p>
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
<p>pvaClientCPP is ready for use.</p>
</div> <!-- head -->
<div id="toc">
<h2 class="nocount">Table of Contents</h2>
</div>
<!-- Place what you would like in the Table of Contents, inside the contents div -->
<div id="contents" class="contents">
<hr />
<h2>Introduction</h2>
<p>pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
an interface to many of the features provided by pvData and pvAccess.</p>
<p>This document describes the layout of the source files in this project.</p>
<p>
A user overview is available via
<a
href="./pvaClientOverview.html">pvaClientOverview.html
</a>
</p>
<p>
Doxygen documentation is available at
<a
href="./html/index.html">doxygenDoc
</a>
</p>
<h2>Example Database</h2>
<p>The examples require that the database provided by project pvaClientTestCPP
is running.
For example:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
mrk&gt; ../../bin/linux-x86_64/exampleDatabase st.cmd
</pre>
<h2>Examples</h2>
<p>Examples are in directory <b>example/src</b>.
An example of how to run them is:</p>
<pre>
mrk&gt; pwd
/home/epicsv4/pvaClientCPP/example
mrk&gt; bin/linux-x86_64/examplePvaClientGet
</pre>
<p>The following is a brief description of each example.
In order to understand each example it
helps to also look at the source for the example.</p>
<h2>examplePvaClientGet</h2>
<p>This has a number of examples:</p>
<dl>
<dt>exampleDouble</dt>
<dd>
This shows two methods for getting data from a channel that has a numeric
scalar value field.
</dd>
<dt>exampleDoubleArray</dt>
<dd>
This shows two methods for getting data from a channel that has a
double array value field.
</dd>
<dt>exampleCADouble</dt>
<dd>
This is like exampleDouble except it uses provider <b>ca</b>.
</dd>
<dt>exampleCADoubleArray</dt>
<dd>
This is like exampleDoubleArray except it uses provider <b>ca</b>.
</dd>
<dt>examplePowerSupply</dt>
<dd>
This is an example of getting data from a channel that does not
have a value field.
</dd>
</dl>
<h2>examplePvaClientMonitor</h2>
<p>This is an example of creating a monitor on a channel.
It monitors a scalar double field.
It also issues puts to the same channel so that it can make the monitors occur.
</p>
<h2>examplePvaClientPut</h2>
<p>This example gets and puts to channels exampleDouble
and exampleDoubleArray.</p>
<h2>examplePvaClientProcess</h2>
<p>This example makes a process request to channel exampleDouble.</p>
<h2>helloWorldPutGet</h2>
<p>This is an example of issuing a channelPutGet.</p>
<h2>examplePvaClientMultiDouble</h2>
<p>This is an example of using pvaClientMultiChannel,
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
</p>
<h2>examplePvaClientNTMulti</h2>
<p>This is an example of using pvaClientMultiChannel,
pvaClientNTMultiGet, pvaClientNTMultiPut, pvaClientNTMultiMonitor, and pvaClientNTMultiData.
</p>
<h2>helloWorldRPC</h2>
<p>This is an example of issuing a channelRPC request.
It does <b>not</b> use pva.</p>
</div> <!-- class="contents" -->
</body>
</html>
+328
View File
@@ -0,0 +1,328 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>pva C++ Overview</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
body { margin-right: 10% }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
</head>
<body>
<div class="head">
<h1>PvaClient C++ Overview</h1>
</div> <!-- head -->
<div id="toc">
<h2 class="nocount">Table of Contents</h2>
</div>
<!-- Place what you would like in the Table of Contents, inside the contents div -->
<div id="contents" class="contents">
<hr />
<h2>Introduction</h2>
<p>PvaClient is a synchronous API for accessing PVData via PVAccess.
It also provides a number of convenience methods.
It allows the client to request access without checking for failure,
but throws an exception if a request fails.
A client can also check for failues and thus prevent exceptions.</p>
<p>The PvaClient API has the following features:</p>
<ol>
<li>Provides a synchronous API rather than the callback API provided by pvAccess.</li>
<li>Makes common requests pva.</li>
<li>Provides full access to the pvAccess API for more demanding
applications</li>
<li>Allows efficient client side programs.</li>
<li>Takes care of most object resource management problems.</li>
</ol>
<p>Simple examples of using pva:</p>
<pre>
// pvaGet
PvaClientPtr pva = PvaClient::create();
double value = pva-&gt;channel("exampleDouble")-&gt;get()-&gt;getData()-&gt;getDouble();
// pvaPut
PvaClientChannelPtr channel = pva-&gt;channel("exampleDouble");
PvaClientPutPtr put = channel-&gt;put();
PvaClientPutDataPtr putData = put-&gt;getData();
putData-&gt;putDouble(3.0); put-&gt;put();
// pvaMonitor
PvaClientMonitorPtr monitor = pva-&gt;channel("examplePowerSupply")-&gt;monitor("");
PvaClientMonitorDataPtr pvaData = monitor-&gt;getData();
while(true) {
monitor-&gt;waitEvent();
cout &lt;&lt; "changed\n";
pvaData-&gt;showChanged(cout);
cout &lt;&lt; "overrun\n";
pvaData-&gt;showOverrun(cout);
monitor-&gt;releaseEvent();
}
// pvaProcess
PvaClientChannelPtr channel = pva-&gt;channel("exampleDouble");
PvaClientProcessPtr process = channel-&gt;createProcess();
process-&gt;process();
</pre>
<p><b>pvClientCPP/example</b> includes a number of examples.</p>
<p>pvaClient does <b>not</b> provide support for:</p>
<dl>
<dt>ChannelArray</dt>
<dd>TBD</dd>
<dt>ChannelRPC</dt>
<dd>pvAccess itself already provides a synchronous interface.
The examples include helloWorldRPC, which is an example of using channelRP.
</dd>
</dl>
<h2>PvaClient</h2>
<p>An instance of PvaClient is obtained via the call:</p>
<pre>
PvaClientPtr pva = PvaClient::create();
</pre>
<p>PvaClient has methods to create instances of <b>PvaClientChannel</b>.
The client can specify the provider name or use the default provider.
The client can manage it's own channels or can let pvaClient cache channels.
An example of using the cached method is:</p>
<pre>
PvaClientChannelPtr pvaChannel = pva-&gt;channel("exampleDouble");
</pre>
<p>This will attempt to connect to channel exampleDouble.
Since the client did not specify a timeout an exception wll be thrown if
the connection request fails.
The client will block until the connection is made or an exception is thrown.
If the request succeeds, pva caches the pvaChannel so that if the
client makes another request for the same channel the cached object is
returned to the client.
</p>
<p>An example of using a non cached method is:</p>
<pre>
PvaClientChannelPtr pvaChannel = pva-&gt;createChannel("exampleDouble");
</pre>
<p>This will create an PvaClientChannel and return it to the client.
The client must itself connect.
This is useful if the client wants to connect to multiple channels in parallel.
</p>
<h2>PvaClientChannel - Wrapper For Single Channel</h2>
<h3>PvaClientChannel</h3>
<p>This provides methods for connecting to a channel and for creating instances of
PvaClientField, PvaClientProcess, ..., PvaClientPutGet.</p>
<p>Connection must be made before any create method is called or
an exception is raised.
The following is a synchronous connection request:</p>
<pre>
pvaChannel-&gt;connect(5.0); // BLOCKS AND THROWS IF NO CONNECT
</pre>
<p>This blocks until then connection is made or until timout occurs.
An exception is raised if the connection request fails.
</p>
<p>The same request can be made without blocking and without exceptions.</p>
<pre>
pvaChannel-&gt;issueConnect(); // DOES NOT BLOCK
.....
Status status =pvaChannel-&gt;waitConnect(5.0); // BLOCKS DOES NOT THROW
if(!status.isOK()) {
// failure do something
}
</pre>
<p>Once the channel is connected other PvaClient objects can be created.
For example:</p>
<pre>
PvaClientGetPtr pvaGet = pvaChannel-&gt;get(); // DOES BLOCK
</pre>
<p>This is a caching request.
If the client already has made an identical request the client will receive the
cached object.
If a new pvaGet is created than it is connected before it is returned to the client.
</p>
<p>The client can also managed it's own objects:</p>
<pre>
PvaClientGetPtr pvaGet = pvaChannel-&gt;createGet(); // DOES NOT BLOCK
</pre>
<p>The client must connect the pvaGet.</p>
<h3>PvaClientGetData</h3>
<p>This provides the data returned by pvaGet and pvaPutGet.
It is obtained via:</p>
<pre>
PvaClientGetDataPtr pvaData = pvaGet-&gt;getData();
</pre>
<p>It provides methods to get everything returned by channelGet.
In addition there are methods that make it easier to handle a value
field that is a scalar or a scalarArray.
Also for a scalar that is a double or a scalarArray with element type double.
</p>
<p>An example is:</p>
<pre>
double value = pvaData-&gt;getDouble();
</pre>
<p>It also keeps a bitSet showing which fields have changed since the last channelGet or channelPutGet.</p>
<h3>PvaClientMonitorData</h3>
<p>To the client this looks identical to PvaClientGetData except that
it provides two BitSets: changedBitSet and overrrunBitSet.
It is used by pvaMonitor.
</p>
<h3>PvaClientPutData</h3>
<p>This is used to provided data for pvaPut and pvaPutGet.
It has many of the same methods as pvaGetData.
It does not have a bitSet.
It also has put methods like:</p>
<pre>
void pvaData-&gt;putDouble(5.0);
</pre>
<h3>PvaClientGet</h3>
<p>This provides methods to connect to channelGet and to issue get request.
To connect via a single synchronous call:</p>
<pre>
eastGet-&gt;connect(); // BLOCKS AND CAN THROW
</pre>
<p>This can also be done in two steps:</p>
<pre>
pvaGet-&gt;issueConnect(); // DOES NOT BLOCK
...
Status status = pvaGet-&gt;waitConnect(); // BLOCKS AND DOES NOT HROW
</pre>
<p>Once connected gets are issued via either:</p>
<pre>
void pvaGet-&gt;get(); // BLOCKS AND CAN THROW
</pre>
or
<pre>
pvaGet-&gt;issueGet(); // DOES NOT BLOCK
...
Status status = pvaGet-&gt;waitGet(); // BLOCKS AND DOES NOT THROW
</pre>
<h3>PvaClientPut</h3>
<p>This is similar to pvaGet except that it wraps channelPut instead of channelGet.
</p>
<p>Once connected puts are issued via either:</p>
<pre>
void pvaPut-&gt;put(); // BLOCKS AND CAN THROW
</pre>
or
<pre>
pvaPut-&gt;issuePut(); // DOES NOT BLOCK
...
Status status = pvaPut-&gt;waitPut(); // BLOCKS AND DOES NOT THROW
</pre>
<h3>PvaClientMonitor</h3>
<p>Connecting is similar to pvaGet and pvaPut.
The other methods are:</p>
<dl>
<dt>start</dt>
<dd>Starts monitoring</dd>
<dt>stop</dt>
<dd>Stops monitoring</dd>
<dt>poll</dt>
<dd>polls for a monitorEvent.
The data is avalable via pvaMonitorData.
</dd>
<dt>releaseEvent</dt>
<dd>Release the data from the last poll.
Note that this must be called before another poll is requested.
</dd>
<dt>waitEvent</dt>
<dd>Block until a monitorEvent is available.
If true is returned a poll has already been issued.
</dd>
<dt>setRequester</dt>
<dd>A client callback is registered to receive notice of monitorEvents.</dd>
</dl>
<h3>PvaClientProcess</h3>
<p>Connecting is similar to pvaGet.
It has methods:</p>
<dl>
<dt>process</dt>
<dd>call issueProcess and waitProcess.</dd>
<dt>issueProcess</dt>
<dd>call channelProcess-&gt;process() and return immediately.
</dd>
<dt>waitProcess</dt>
<dd>Wait for process to complete.</dd>
</dl>
<h3>PvaClientPutGet</h3>
<p>Connecting is similar to pvaGet.
It has methods:</p>
<dl>
<dt>putGet</dt>
<dd>calls issuePutGet and waitPutGet.
throws an exception if not successfull.
</dd>
<dt>issuePutGet</dt>
<dd>
Calls channel-&gt;putGet() and returns.
</dd>
<dt>waitPutGet</dt>
<dd>
Waits until putGet completes and returns status.
</dd>
<dt>getGet,issueGetGet, and waitGetGet</dt>
<dd>Gets the data for the get part of channelPutGet.</dd>
<dt>getPut,issueGetPut,and waitGetPut</dt>
<dd>Gets the data for the put part of channelPutGet.</dd>
<dt>getPutData</dt>
<dd>
Returns the PvaClientData for the put part of channelPutGet.
</dd>
<dt>getGetData</dt>
<dd>
Returns the PvaClientData for the get part of channelPutGet.
</dd>
</dl>
<p>Look at javaDoc for details.</p>
<h2>PvaClientMultiChannel - Wrapper For Multiple Channels</h2>
<h3>PvaClientMultiChannel</h3>
<p>This provides methods for connecting to multiple channels.
</p>
<h3>PvaClientMultiGetDouble</h3>
<p>This provides support for channelGet to multiple channels where each channel has a value field that is a numeric scalar.
</p>
<h3>PvaClientMultiPutDouble</h3>
<p>This provides support for channelPut to multiple channels where each channel has a value field that is a numeric scalar.
</p>
<h3>PvaClientMultiMonitorDouble</h3>
<p>This provides support for monitoring changes to multiple channels where each channel has a value field that is a numeric scalar.
</p>
<h3>PvaClientNTMultiGet</h3>
<p>This provides support for channelGet to multiple channels where each channel has a value field that has any valid type.
</p>
<h3>PvaClientNTMultiPut</h3>
<p>This provides support for channelPut to multiple channels where each channel has a value
field that has any valid type.
</p>
<h3>PvaClientNTMultiMonitor</h3>
<p>This provides support for monitoring changes to multiple channels where each channel has a
value field that has any valid type.
</p>
<h3>PvaClientNTMultiData</h3>
<p>This provides support for monitoring changes to multiple channels where each channel has a value field that has any valid type.
The client can get the data as normative type NTMultiChannel.
</p>
</div> <!-- class="contents" -->
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
# Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
DIRS += configure
DIRS += src
src_DEPEND_DIRS = configure
include $(TOP)/configure/RULES_TOP
+29
View File
@@ -0,0 +1,29 @@
# CONFIG - Load build configuration data
#
# Do not make changes to this file!
# Allow user to override where the build rules come from
RULES = $(EPICS_BASE)
# RELEASE files point to other application tops
include $(TOP)/configure/RELEASE
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/RELEASE.Common.$(T_A)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
endif
CONFIG = $(RULES)/configure
include $(CONFIG)/CONFIG
# Override the Base definition:
INSTALL_LOCATION = $(TOP)
# CONFIG_SITE files contain other build configuration settings
include $(TOP)/configure/CONFIG_SITE
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
endif
+27
View File
@@ -0,0 +1,27 @@
# CONFIG_SITE
# Make any application-specific changes to the EPICS build
# configuration variables in this file.
#
# Host/target specific settings can be specified in files named
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
# CONFIG_SITE.Common.$(T_A)
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# CHECK_RELEASE controls the consistency checking of the support
# applications pointed to by the RELEASE* files.
# Normally CHECK_RELEASE should be set to YES.
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = WARN
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../../CONFIG_SITE.local
-include $(TOP)/../configure/CONFIG_SITE.local
+7
View File
@@ -0,0 +1,7 @@
EPICS_BASE=/home/install/epics/base
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
EPICSV4HOME=/home/hg
PVCOMMON=${EPICSV4HOME}/pvCommonCPP
PVDATA=${EPICSV4HOME}/pvDataCPP
PVACCESS=${EPICSV4HOME}/pvAccessCPP
EASYPVA==${EPICSV4HOME}/easyPVACPP
+8
View File
@@ -0,0 +1,8 @@
TOP=..
include $(TOP)/configure/CONFIG
TARGETS = $(CONFIG_TARGETS)
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
include $(TOP)/configure/RULES
+41
View File
@@ -0,0 +1,41 @@
# pvDatabaseCPP/example RELEASE - Location of external support modules
#
# IF YOU CHANGE this file or any file it includes you must
# subsequently do a "gnumake rebuild" in the application's
# top level directory.
#
# The build process does not check dependencies against files
# that are outside this application, thus you should also do a
# "gnumake rebuild" in the top level directory after EPICS_BASE
# or any other external module pointed to below is rebuilt.
#
# Host- or target-specific settings can be given in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A)
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
# EPICS V4 Developers: Do not edit the locations in this file!
#
# Create a file RELEASE.local pointing to your PVASRV, PVACCESS,
# PVDATA, PVCOMMON and EPICS_BASE build directories, e.g.
# PVASRV = /path/to/epics/pvaSrvCPP
# PVACCESS = /path/to/epics/pvAccessCPP
# PVDATA = /path/to/epics/pvDataCPP
# PVCOMMON = /path/to/epics/pvCommonCPP
# EPICS_BASE = /path/to/epics/base
# If this example is built in a directory under pvDatabaseCPP,
# use the following definitions:
EASYPVA = $(TOP)/..
-include $(TOP)/../configure/RELEASE.local
-include $(TOP)/../../RELEASE.local
# If you copied this example from pvDatabaseCPP to be built as a
# standalone TOP, adjust and use the following definitions:
#EASYPVA = /path/to/epics/easyPVACPP
#-include $(TOP)/../RELEASE.local
#-include $(TOP)/configure/RELEASE.local
+6
View File
@@ -0,0 +1,6 @@
# RULES
include $(CONFIG)/RULES
# Library should be rebuilt because LIBOBJS may have changed.
$(LIBNAME): ../Makefile
+2
View File
@@ -0,0 +1,2 @@
#RULES.ioc
include $(CONFIG)/RULES.ioc
+2
View File
@@ -0,0 +1,2 @@
#RULES_DIRS
include $(CONFIG)/RULES_DIRS
+3
View File
@@ -0,0 +1,3 @@
#RULES_TOP
include $(CONFIG)/RULES_TOP
+84
View File
@@ -0,0 +1,84 @@
TOP=..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
PROD_HOST += examplePvaClientProcess
examplePvaClientProcess_SRCS += examplePvaClientProcess.cpp
examplePvaClientProcess_LIBS += pvaClient
examplePvaClientProcess_LIBS += pvAccess
examplePvaClientProcess_LIBS += nt
examplePvaClientProcess_LIBS += pvData
examplePvaClientProcess_LIBS += ca
examplePvaClientProcess_LIBS += Com
PROD_HOST += examplePvaClientGet
examplePvaClientGet_SRCS += examplePvaClientGet.cpp
examplePvaClientGet_LIBS += pvaClient
examplePvaClientGet_LIBS += pvAccess
examplePvaClientGet_LIBS += nt
examplePvaClientGet_LIBS += pvData
examplePvaClientGet_LIBS += ca
examplePvaClientGet_LIBS += Com
PROD_HOST += examplePvaClientPut
examplePvaClientPut_SRCS += examplePvaClientPut.cpp
examplePvaClientPut_LIBS += pvaClient
examplePvaClientPut_LIBS += pvAccess
examplePvaClientPut_LIBS += nt
examplePvaClientPut_LIBS += pvData
examplePvaClientPut_LIBS += ca
examplePvaClientPut_LIBS += Com
PROD_HOST += examplePvaClientMonitor
examplePvaClientMonitor_SRCS += examplePvaClientMonitor.cpp
examplePvaClientMonitor_LIBS += pvaClient
examplePvaClientMonitor_LIBS += pvAccess
examplePvaClientMonitor_LIBS += nt
examplePvaClientMonitor_LIBS += pvData
examplePvaClientMonitor_LIBS += ca
examplePvaClientMonitor_LIBS += Com
PROD_HOST += examplePvaClientMultiDouble
examplePvaClientMultiDouble_SRCS += examplePvaClientMultiDouble.cpp
examplePvaClientMultiDouble_LIBS += pvaClient
examplePvaClientMultiDouble_LIBS += pvAccess
examplePvaClientMultiDouble_LIBS += nt
examplePvaClientMultiDouble_LIBS += pvData
examplePvaClientMultiDouble_LIBS += ca
examplePvaClientMultiDouble_LIBS += Com
PROD_HOST += examplePvaClientNTMulti
examplePvaClientNTMulti_SRCS += examplePvaClientNTMulti.cpp
examplePvaClientNTMulti_LIBS += pvaClient
examplePvaClientNTMulti_LIBS += pvAccess
examplePvaClientNTMulti_LIBS += nt
examplePvaClientNTMulti_LIBS += pvData
examplePvaClientNTMulti_LIBS += ca
examplePvaClientNTMulti_LIBS += Com
PROD_HOST += helloWorldRPC
helloWorldRPC_SRCS += helloWorldRPC.cpp
helloWorldRPC_LIBS += pvaClient
helloWorldRPC_LIBS += pvAccess
helloWorldRPC_LIBS += nt
helloWorldRPC_LIBS += pvData
helloWorldRPC_LIBS += Com
PROD_HOST += helloWorldPutGet
helloWorldPutGet_SRCS += helloWorldPutGet.cpp
helloWorldPutGet_LIBS += pvaClient
helloWorldPutGet_LIBS += pvAccess
helloWorldPutGet_LIBS += nt
helloWorldPutGet_LIBS += pvData
helloWorldPutGet_LIBS += ca
helloWorldPutGet_LIBS += Com
#===========================
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE
+146
View File
@@ -0,0 +1,146 @@
/*examplePvaClientGet.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvaClient.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static void exampleDouble(PvaClientPtr const &pva)
{
cout << "example double scalar\n";
double value;
try {
cout << "short way\n";
value = pva->channel("exampleDouble")->get()->getData()->getDouble();
cout << "as double " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
cout << "long way\n";
PvaClientChannelPtr pvaChannel = pva->createChannel("exampleDouble");
pvaChannel->issueConnect();
Status status = pvaChannel->waitConnect(2.0);
if(!status.isOK()) {cout << " connect failed\n"; return;}
PvaClientGetPtr pvaGet = pvaChannel->createGet();
pvaGet->issueConnect();
status = pvaGet->waitConnect();
if(!status.isOK()) {cout << " createGet failed\n"; return;}
PvaClientGetDataPtr pvaData = pvaGet->getData();
value = pvaData->getDouble();
cout << "as double " << value << endl;
}
static void exampleDoubleArray(PvaClientPtr const &pva)
{
cout << "example double array\n";
shared_vector<const double> value;
try {
cout << "short way\n";
value = pva->channel("exampleDoubleArray")->get()->getData()->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "long way\n";
PvaClientChannelPtr pvaChannel = pva->createChannel("exampleDoubleArray");
pvaChannel->connect(2.0);
PvaClientGetPtr pvaGet = pvaChannel->createGet();
PvaClientGetDataPtr pvaData = pvaGet->getData();
value = pvaData->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
static void examplePowerSupply(PvaClientPtr const &pva)
{
cout << "example powerSupply\n";
PVStructurePtr pvStructure;
try {
cout << "short way\n";
pvStructure = pva->channel("examplePowerSupply")->
get("field()")->getData()->getPVStructure();
cout << pvStructure << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
static void exampleCADouble(PvaClientPtr const &pva)
{
cout << "example double scalar\n";
double value;
try {
cout << "short way\n";
value = pva->channel("double00","ca",5.0)->get()->getData()->getDouble();
cout << "as double " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
cout << "long way\n";
PvaClientChannelPtr pvaChannel = pva->createChannel("double00","ca");
pvaChannel->issueConnect();
Status status = pvaChannel->waitConnect(2.0);
if(!status.isOK()) {cout << " connect failed\n"; return;}
PvaClientGetPtr pvaGet = pvaChannel->createGet();
pvaGet->issueConnect();
status = pvaGet->waitConnect();
if(!status.isOK()) {cout << " createGet failed\n"; return;}
PvaClientGetDataPtr pvaData = pvaGet->getData();
value = pvaData->getDouble();
cout << "as double " << value << endl;
}
static void exampleCADoubleArray(PvaClientPtr const &pva)
{
cout << "example double array\n";
shared_vector<const double> value;
try {
cout << "short way\n";
value = pva->channel("doubleArray","ca",5.0)->get()->getData()->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "long way\n";
PvaClientChannelPtr pvaChannel = pva->createChannel("doubleArray","ca");
pvaChannel->connect(2.0);
PvaClientGetPtr pvaGet = pvaChannel->createGet();
PvaClientGetDataPtr pvaData = pvaGet->getData();
value = pvaData->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva= PvaClient::create();
exampleDouble(pva);
exampleDoubleArray(pva);
examplePowerSupply(pva);
exampleCADouble(pva);
exampleCADoubleArray(pva);
cout << "done\n";
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
/*examplePvaClientMonitor.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <epicsThread.h>
#include <iostream>
#include <pv/pvaClient.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static void exampleMonitor(PvaClientPtr const &pva,string provider)
{
PvaClientMonitorPtr monitor = pva->channel("double00",provider,2.0)->monitor("");
PvaClientMonitorDataPtr monitorData = monitor->getData();
PvaClientPutPtr put = pva->channel("double00",provider,2.0)->put("");
PvaClientPutDataPtr putData = put->getData();
for(size_t ntimes=0; ntimes<5; ++ntimes)
{
double value = ntimes;
cout << "put " << value << endl;
putData->putDouble(value); put->put();
if(!monitor->waitEvent(.1)) {
cout << "waitEvent returned false. Why???";
continue;
} else while(true) {
cout << "monitor " << monitorData->getDouble() << endl;
cout << "changed\n";
monitorData->showChanged(cout);
cout << "overrun\n";
monitorData->showOverrun(cout);
monitor->releaseEvent();
if(!monitor->poll()) break;
}
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
cout << "exampleMonitor pva\n";
exampleMonitor(pva,"pva");
cout << "exampleMonitor ca\n";
exampleMonitor(pva,"ca");
cout << "done\n";
return 0;
}
@@ -0,0 +1,79 @@
/*examplePvaClientMultiDouble.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvaClientMultiChannel.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static void example(
PvaClientPtr const &pva,
string provider,
shared_vector<const string> const &channelNames)
{
size_t num = channelNames.size();
cout << "num " << num << " names " << channelNames << endl;
PvaClientMultiChannelPtr multiChannel(
PvaClientMultiChannel::create(pva,channelNames,provider));
PvaClientMultiGetDoublePtr multiGet(multiChannel->createGet());
PvaClientMultiPutDoublePtr multiPut(multiChannel->createPut());
PvaClientMultiMonitorDoublePtr multiMonitor(multiChannel->createMonitor());
shared_vector<double> data(num,0);
for(double value = 0.2; value< 2.3; value+= 1.0) {
try {
for(size_t i=0; i<num; ++i) data[i] = value + i;
cout << "put " << data << endl;
multiPut->put(data);
data = multiGet->get();
cout << "get " << data << endl;
bool result = multiMonitor->waitEvent(.1);
while(result) {
cout << "monitor data " << multiMonitor->get() << endl;
result = multiMonitor->poll();
}
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
size_t num = 5;
shared_vector<string> channelNames(num);
channelNames[0] = "double01";
channelNames[1] = "int01";
channelNames[2] = "double03";
channelNames[3] = "double04";
channelNames[4] = "double05";
cout << "double pva\n";
shared_vector<const string> names(freeze(channelNames));
example(pva,"pva",names);
cout << "double ca\n";
example(pva,"ca",names);
channelNames = shared_vector<string>(num);
channelNames[0] = "exampleDouble01";
channelNames[1] = "exampleInt";
channelNames[2] = "exampleDouble03";
channelNames[3] = "exampleDouble04";
channelNames[4] = "exampleDouble05";
names = freeze(channelNames);
cout << "exampleDouble pva\n";
example(pva,"pva",names);
return 0;
}
+141
View File
@@ -0,0 +1,141 @@
/*examplePvaClientNTMulti.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvaClientMultiChannel.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static ConvertPtr convert = getConvert();
static void setValue(PVUnionPtr const &pvUnion, double value)
{
UnionConstPtr u = pvUnion->getUnion();
FieldConstPtr field = u->getField(0);
Type type = field->getType();
if(type==scalar) {
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
ScalarType scalarType = scalar->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
pvDataCreate->createPVScalar(pvDouble));
pvValue->put(value);
pvUnion->set(0,pvValue);
return;
}
if(scalarType==pvString) {
PVStringPtr pvValue = static_pointer_cast<PVString>(
pvDataCreate->createPVScalar(pvString));
stringstream ss;
ss << "value" << value;
pvValue->put(ss.str());
pvUnion->set(0,pvValue);
return;
}
throw std::runtime_error("only pvDouble and pvString are supported");
}
if(type==scalarArray) {
ScalarArrayConstPtr scalarArray = static_pointer_cast<const ScalarArray>(field);
ScalarType scalarType = scalarArray->getElementType();
if(scalarType==pvDouble) {
size_t num = 5;
PVDoubleArrayPtr pvValue = static_pointer_cast<PVDoubleArray>(
pvDataCreate->createPVScalarArray(pvDouble));
shared_vector<double> data(num);
for(size_t i=0; i<num; ++i) data[i] = value +i;
pvValue->replace(freeze(data));
pvUnion->set(0,pvValue);
return;
}
if(scalarType==pvString) {
size_t num = 5;
PVStringArrayPtr pvValue = static_pointer_cast<PVStringArray>(
pvDataCreate->createPVScalarArray(pvString));
shared_vector<string> data(num);
for(size_t i=0; i<num; ++i) {
stringstream ss;
ss << "value" << value << i;
data[i] = ss.str();
}
pvValue->replace(freeze(data));
pvUnion->set(0,pvValue);
return;
}
throw std::runtime_error("only pvDouble and pvString are supported");
}
throw std::runtime_error("only scalar and scalarArray fields are supported");
}
static void example(
PvaClientPtr const &pva,
string provider,
shared_vector<const string> const &channelNames)
{
size_t num = channelNames.size();
PvaClientMultiChannelPtr multiChannel(
PvaClientMultiChannel::create(pva,channelNames,provider));
PvaClientNTMultiGetPtr multiGet(multiChannel->createNTGet());
PvaClientNTMultiPutPtr multiPut(multiChannel->createNTPut());
PvaClientNTMultiMonitorPtr multiMonitor(multiChannel->createNTMonitor());
shared_vector<epics::pvData::PVUnionPtr> data = multiPut->getValues();
for(double value = 0.0; value< 2.1; value+= 1.0) {
for(size_t i=0; i<num ; ++i) {
PVUnionPtr pvUnion = data[i];
setValue(pvUnion,value);
}
multiPut->put();
multiGet->get();
PvaClientNTMultiDataPtr multiData = multiGet->getData();
PVStructurePtr pvStructure = multiData->getNTMultiChannel()->getPVStructure();
cout << "pvStructure\n" << pvStructure << endl;
bool result = multiMonitor->waitEvent(.1);
while(result) {
multiData = multiMonitor->getData();
pvStructure = multiData->getNTMultiChannel()->getPVStructure();
cout << "monitor pvStructure\n" << pvStructure << endl;
result = multiMonitor->poll();
}
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
size_t num = 4;
shared_vector<string> channelNames(num);
channelNames[0] = "double01";
channelNames[1] = "string01";
channelNames[2] = "doubleArray01";
channelNames[3] = "stringArray01";
cout << "dbRecord pva\n";
shared_vector<const string> names(freeze(channelNames));
example(pva,"pva",names);
cout << "dbRecord ca\n";
example(pva,"ca",names);
channelNames = shared_vector<string>(num);
channelNames[0] = "exampleDouble";
channelNames[1] = "exampleString";
channelNames[2] = "exampleDoubleArray";
channelNames[3] = "exampleStringArray";
names = freeze(channelNames);
cout << "pvRecord pva\n";
example(pva,"pva",names);
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
/*examplePvaClientProcess.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvaClient.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static void exampleProcess(PvaClientPtr const &pva)
{
cout << "example process\n";
PvaClientChannelPtr channel = pva->channel("exampleDouble");
PvaClientProcessPtr process = channel->createProcess();
try {
process->process();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
process->process();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
exampleProcess(pva);
return 0;
}
+77
View File
@@ -0,0 +1,77 @@
/*examplePvaClientPut.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvaClient.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static ConvertPtr convert = getConvert();
static void examplePut(PvaClientPtr const &pva)
{
cout << "example put\n";
PvaClientChannelPtr channel = pva->channel("exampleDouble");
PvaClientPutPtr put = channel->put();
PvaClientPutDataPtr putData = put->getData();
PvaClientMonitorPtr monitor = pva->channel("exampleDouble")->monitor("");
PvaClientMonitorDataPtr monitorData = monitor->getData();
try {
putData->putDouble(3.0); put->put();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
putData->putDouble(4.0); put->put();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
if(!monitor->waitEvent()) {
cout << "waitEvent returned false. Why???";
} else while(true) {
cout << "monitor changed\n" << monitorData->showChanged(cout);
monitor->releaseEvent();
if(!monitor->poll()) break;
}
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
static void examplePVFieldPut(PvaClientPtr const &pva)
{
cout << "example put\n";
PvaClientChannelPtr channel = pva->channel("exampleDouble");
PvaClientPutPtr put = channel->put();
PvaClientPutDataPtr putData = put->getData();
PVFieldPtr pvField = putData->getValue();
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
try {
convert->fromDouble(pvScalar,1.0); put->put();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
convert->fromDouble(pvScalar,2.0); put->put();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
examplePut(pva);
examplePVFieldPut(pva);
return 0;
}
+48
View File
@@ -0,0 +1,48 @@
/*helloWorldPutGet.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvaClient.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
static void example(PvaClientPtr const &pva)
{
cout << "helloWorldPutGet\n";
try {
PvaClientChannelPtr channel = pva->channel("exampleHello");
PvaClientPutGetPtr putGet = channel->createPutGet();
putGet->connect();
PvaClientPutDataPtr putData = putGet->getPutData();
PVStructurePtr arg = putData->getPVStructure();
PVStringPtr pvValue = arg->getSubField<PVString>("argument.value");
pvValue->put("World");
putGet->putGet();
PvaClientGetDataPtr getData = putGet->getGetData();
cout << getData->getPVStructure() << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
example(pva);
return 0;
}
+77
View File
@@ -0,0 +1,77 @@
/*helloWorldRPC.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <iostream>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/rpcClient.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static void exampleSimple()
{
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
add("value",pvString)->
createStructure();
PVStructurePtr pvRequest = pvDataCreate->createPVStructure(topStructure);
PVStringPtr pvArgument = pvRequest->getSubField<PVString>("value");
pvArgument->put("World");
cout << "example channeRPC simple\n";
try {
PVStructurePtr pvResult =
RPCClient::sendRequest("exampleHelloRPC", pvRequest);
cout << "result\n" << pvResult << endl;
} catch (RPCRequestException &e) {
cout << e.what() << endl;
}
}
void exampleMore()
{
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
add("value",pvString)->
createStructure();
PVStructurePtr pvRequest = pvDataCreate->createPVStructure(topStructure);
PVStringPtr pvArgument = pvRequest->getSubField<PVString>("value");
pvArgument->put("World");
cout << "example channeRPC more\n";
try {
RPCClient::shared_pointer client = RPCClient::create("exampleHelloRPC");
client->issueConnect();
if (client->waitConnect())
{
client->issueRequest(pvRequest);
PVStructure::shared_pointer result = client->waitResponse();
std::cout << *result << std::endl;
}
else {
cout << "waitConnect timeout\n";
return;
}
} catch (RPCRequestException &e) {
cout << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
exampleSimple();
exampleMore();
return 0;
}
+23 -42
View File
@@ -6,46 +6,22 @@
# #
# Author: Ralph Lange <ralph.lange@gmx.de> # Author: Ralph Lange <ralph.lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH # Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# Copyright (C) 2014-2016 ITER Organization. # Copyright (C) 2014-2015 ITER Organization.
# All rights reserved. Use is subject to license terms. # All rights reserved. Use is subject to license terms.
installTool () {
local module=$1
local version=$2
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
}
installE4 () {
local module=$1
local branch=$2
# If microbench version does not exist, try without
if [ "${MB}" = "WITH_MICROBENCH" ]; then
if ! wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=WITH_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz; then
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
else
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
tar -xzf ${module}.CB-dist.tar.gz
}
########################################### ###########################################
# Defaults for EPICS Base and MB # Determine EPICS Base version
DEFAULT_BASE=3.15.4 DEFAULT_BASE=3.14.12.5
BASE=${BASE:-${DEFAULT_BASE}}
MB=${MB:-"NO_MICROBENCH"}
########################################### BASE=${1:-${DEFAULT_BASE}}
# Dependent module branches USE_MB=${2:-"MB_NO"}
PVCOMMON_BRANCH="release-4.2" # Dependent module branches (empty = master)
PVDATA_BRANCH="release-6.0" PVCOMMON_BRANCH="Release-4.1-"
PVACCESS_BRANCH="release-5.0" PVDATA_BRANCH="Release-5.0-"
NORMATIVETYPES_BRANCH="release-5.1" PVACCESS_BRANCH="Release-4.1-"
NORMATIVETYPES_BRANCH="Release-5.0-"
########################################### ###########################################
# Fetch and unpack dependencies # Fetch and unpack dependencies
@@ -56,13 +32,19 @@ rm -fr ${STUFF}
mkdir -p ${STUFF} mkdir -p ${STUFF}
cd ${STUFF} cd ${STUFF}
installTool Boost 1.61.0 wget -nv https://openepics.ci.cloudbees.com/job/Base-${BASE}_Build/lastSuccessfulBuild/artifact/base-${BASE}.CB-dist.tar.gz
installTool Base ${BASE} wget -nv https://openepics.ci.cloudbees.com/job/pvDataCPP_${PVDATA_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
wget -nv https://openepics.ci.cloudbees.com/job/pvAccessCPP_${PVACCESS_BRANCH}Build/BASE=${BASE},USE_MB=${USE_MB}/lastSuccessfulBuild/artifact/pvAccess.CB-dist.tar.gz
wget -nv https://openepics.ci.cloudbees.com/job/normativeTypesCPP_${NORMATIVETYPES_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/normativeTypes.CB-dist.tar.gz
tar -xzf base-${BASE}.CB-dist.tar.gz
tar -xzf pvData.CB-dist.tar.gz
tar -xzf pvAccess.CB-dist.tar.gz
tar -xzf normativeTypes.CB-dist.tar.gz
installE4 pvCommon ${PVCOMMON_BRANCH} if [ "${USE_MB}" = "MB_YES" ]; then
installE4 pvData ${PVDATA_BRANCH} wget -nv https://openepics.ci.cloudbees.com/job/pvCommonCPP_${PVCOMMON_BRANCH}Build/BASE=${BASE},USE_MB=MB_YES/lastSuccessfulBuild/artifact/pvCommon.CB-dist.tar.gz
installE4 pvAccess ${PVACCESS_BRANCH} tar -xzf pvCommon.CB-dist.tar.gz
installE4 normativeTypes ${NORMATIVETYPES_BRANCH} fi
########################################### ###########################################
# Build # Build
@@ -83,8 +65,7 @@ make distclean all
########################################### ###########################################
# Test # Test
# no regression tests make runtests
#make runtests
########################################### ###########################################
# Create distribution # Create distribution
+10 -32
View File
@@ -6,39 +6,14 @@
# #
# Author: Ralph Lange <ralph.lange@gmx.de> # Author: Ralph Lange <ralph.lange@gmx.de>
# Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH # Copyright (C) 2013 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
# Copyright (C) 2014-2016 ITER Organization. # Copyright (C) 2014-2015 ITER Organization.
# All rights reserved. Use is subject to license terms. # All rights reserved. Use is subject to license terms.
installTool () {
local module=$1
local version=$2
wget -nv https://openepics.ci.cloudbees.com/job/${module}-${version}_Build/lastSuccessfulBuild/artifact/${module,,}-${version}.CB-dist.tar.gz
tar -xzf ${module,,}-${version}.CB-dist.tar.gz
}
installE4 () {
local module=$1
local branch=$2
# If microbench version does not exist, try without
if [ "${MB}" = "WITH_MICROBENCH" ]; then
if ! wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=WITH_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz; then
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
else
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
tar -xzf ${module}.CB-dist.tar.gz
}
########################################### ###########################################
# Defaults for EPICS Base and parameters # Set EPICS Base version and upload target
BASE=3.15.4 BASE=3.15.2
PUBLISH=${PUBLISH:-NO} PUBLISH=${1:-DONT}
BRANCH=${BRANCH:-master}
MB=NO_MICROBENCH
########################################### ###########################################
# Fetch and unpack dependencies # Fetch and unpack dependencies
@@ -49,14 +24,16 @@ rm -fr ${STUFF}
mkdir -p ${STUFF} mkdir -p ${STUFF}
cd ${STUFF} cd ${STUFF}
installTool Doxygen 1.8.11 wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
########################################### ###########################################
# Generate # Generate
cd ${WORKSPACE} cd ${WORKSPACE}
installE4 pvaClient ${BRANCH} wget -nv https://openepics.ci.cloudbees.com/job/pvaClientCPP_Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvaClient.CB-dist.tar.gz
tar -xzf pvaClient.CB-dist.tar.gz
export PATH=${STUFF}/bin:${PATH} export PATH=${STUFF}/bin:${PATH}
@@ -65,9 +42,10 @@ doxygen
########################################### ###########################################
# Publish # Publish
if [ "${PUBLISH}" != "NO" ]; then if [ "${PUBLISH}" != "DONT" ]; then
# Upload explicit dummy to ensure target directory exists # Upload explicit dummy to ensure target directory exists
echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY
rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/ rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/ rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/
fi fi
+3 -7
View File
@@ -5,11 +5,8 @@ include $(TOP)/configure/CONFIG
LIBRARY += pvaClient LIBRARY += pvaClient
# shared library ABI version. INC += pvaClient.h
SHRLIB_VERSION ?= 4.2 INC += pvaClientMultiChannel.h
INC += pv/pvaClient.h
INC += pv/pvaClientMultiChannel.h
LIBSRCS += pvaClient.cpp LIBSRCS += pvaClient.cpp
LIBSRCS += pvaClientPutData.cpp LIBSRCS += pvaClientPutData.cpp
@@ -29,9 +26,8 @@ LIBSRCS += pvaClientNTMultiPut.cpp
LIBSRCS += pvaClientNTMultiData.cpp LIBSRCS += pvaClientNTMultiData.cpp
LIBSRCS += pvaClientNTMultiGet.cpp LIBSRCS += pvaClientNTMultiGet.cpp
LIBSRCS += pvaClientNTMultiMonitor.cpp LIBSRCS += pvaClientNTMultiMonitor.cpp
LIBSRCS += pvaClientRPC.cpp
pvaClient_LIBS += pvAccess nt pvData Com pvaClient_LIBS += pvAccess pvData nt Com
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS) pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES include $(TOP)/configure/RULES
+86 -63
View File
@@ -9,15 +9,13 @@
* @date 2015.02 * @date 2015.02
*/ */
#define epicsExportSharedSymbols
#include <map> #include <map>
#include <pv/pvaClient.h>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#include <pv/clientFactory.h> #include <pv/clientFactory.h>
#include <pv/caProvider.h> #include <pv/caProvider.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
using namespace epics::pvAccess; using namespace epics::pvAccess;
@@ -26,18 +24,65 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static FieldCreatePtr fieldCreate = getFieldCreate();
static const string pvaClientName = "pvaClient";
static const string defaultProvider = "pva";
static UnionConstPtr variantUnion = fieldCreate->createVariantUnion();
class epicsShareClass PvaClientChannelCache namespace pvaClientPvt {
static size_t numberPvaClient = 0;
static bool firstTime = true;
static Mutex mutex;
class StartStopClientFactory {
public:
static void PvaClientBeingConstructed()
{
bool saveFirst = false;
{
Lock xx(mutex);
++numberPvaClient;
saveFirst = firstTime;
firstTime = false;
}
if(saveFirst) {
ClientFactory::start();
CAClientFactory::start();
}
}
static void PvaClientBeingDestroyed() {
size_t numLeft = 0;
{
Lock xx(mutex);
--numberPvaClient;
numLeft = numberPvaClient;
}
if(numLeft<=0) {
ClientFactory::stop();
CAClientFactory::stop();
}
}
};
} // namespace pvaClientPvt
class PvaClientChannelCache
{ {
public: public:
PvaClientChannelCache(){} PvaClientChannelCache(){}
~PvaClientChannelCache(){ ~PvaClientChannelCache(){
if(PvaClient::getDebug()) cout << "PvaClientChannelCache::~PvaClientChannelCache\n"; destroy();
} }
void destroy() {
pvaClientChannelMap.clear();
}
PvaClientChannelPtr getChannel( PvaClientChannelPtr getChannel(
string const & channelName, string const & channelName,
string const & providerName); string const & providerName);
void addChannel(PvaClientChannelPtr const & pvaClientChannel); void addChannel(PvaClientChannelPtr const & pvaClientChannel);
void removeChannel(string const & channelName,string const & providerName);
void showCache(); void showCache();
size_t cacheSize(); size_t cacheSize();
private: private:
@@ -59,14 +104,19 @@ void PvaClientChannelCache::addChannel(PvaClientChannelPtr const & pvaClientChan
Channel::shared_pointer channel = pvaClientChannel->getChannel(); Channel::shared_pointer channel = pvaClientChannel->getChannel();
string name = channel->getChannelName() string name = channel->getChannelName()
+ channel->getProvider()->getProviderName(); + channel->getProvider()->getProviderName();
map<string,PvaClientChannelPtr>::iterator iter = pvaClientChannelMap.find(name); pvaClientChannelMap.insert(std::pair<string,PvaClientChannelPtr>(
if(iter!=pvaClientChannelMap.end()) {
throw std::runtime_error("pvaClientChannelCache::addChannel channel already cached");
}
pvaClientChannelMap.insert(std::pair<string,PvaClientChannelPtr>(
name,pvaClientChannel)); name,pvaClientChannel));
} }
void PvaClientChannelCache::removeChannel(
string const & channelName,
string const & providerName)
{
string name = channelName + providerName;
map<string,PvaClientChannelPtr>::iterator iter = pvaClientChannelMap.find(name);
if(iter!=pvaClientChannelMap.end()) pvaClientChannelMap.erase(iter);
}
void PvaClientChannelCache::showCache() void PvaClientChannelCache::showCache()
{ {
map<string,PvaClientChannelPtr>::iterator iter; map<string,PvaClientChannelPtr>::iterator iter;
@@ -77,8 +127,10 @@ void PvaClientChannelCache::showCache()
string channelName = channel->getChannelName(); string channelName = channel->getChannelName();
string providerName = channel->getProvider()->getProviderName(); string providerName = channel->getProvider()->getProviderName();
cout << "channel " << channelName << " provider " << providerName << endl; cout << "channel " << channelName << " provider " << providerName << endl;
cout << " get and put cacheSize " << pvaChannel->cacheSize() << endl;
pvaChannel->showCache(); pvaChannel->showCache();
} }
} }
size_t PvaClientChannelCache::cacheSize() size_t PvaClientChannelCache::cacheSize()
@@ -87,60 +139,35 @@ size_t PvaClientChannelCache::cacheSize()
} }
bool PvaClient::debug = false; using namespace epics::pvaClient::pvaClientPvt;
PvaClientPtr PvaClient::get(std::string const & providerNames) PvaClientPtr PvaClient::create()
{ {
static PvaClientPtr master; PvaClientPtr xx(new PvaClient());
static Mutex mutex; StartStopClientFactory::PvaClientBeingConstructed();
Lock xx(mutex); return xx;
if(!master) {
master = PvaClientPtr(new PvaClient(providerNames));
}
return master;
} }
PvaClient::PvaClient(std::string const & providerNames) PvaClient::PvaClient()
: pvaClientChannelCache(new PvaClientChannelCache()), : pvaClientChannelCache(new PvaClientChannelCache()),
pvaStarted(false), isDestroyed(false)
caStarted(false)
{ {
stringstream ss(providerNames);
string providerName;
while (getline(ss, providerName, ' '))
{
ChannelProviderRegistry::shared_pointer registry(getChannelProviderRegistry());
if(providerName=="pva") {
ClientFactory::start();
pvaStarted = true;
} else if(providerName=="ca") {
CAClientFactory::start();
caStarted = true;
} else {
if(!registry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
}
}
}
} }
PvaClient::~PvaClient() { PvaClient::~PvaClient() {
if(PvaClient::debug) { destroy();
cout<< "PvaClient::~PvaClient()\n" }
<< "pvaChannel cache:\n";
showCache(); void PvaClient::destroy()
} {
if(pvaStarted){ {
if(PvaClient::debug) cout<< "calling ClientFactory::stop()\n"; Lock xx(mutex);
ClientFactory::stop(); if(isDestroyed) return;
if(PvaClient::debug) cout<< "after calling ClientFactory::stop()\n"; isDestroyed = true;
}
if(caStarted) {
if(PvaClient::debug) cout<< "calling CAClientFactory::stop()\n";
CAClientFactory::stop();
if(PvaClient::debug) cout<< "after calling CAClientFactory::stop()\n";
} }
pvaClientChannelCache.reset();
StartStopClientFactory::PvaClientBeingDestroyed();
} }
string PvaClient:: getRequesterName() string PvaClient:: getRequesterName()
@@ -181,7 +208,7 @@ PvaClientChannelPtr PvaClient::channel(
PvaClientChannelPtr PvaClient::createChannel(string const & channelName, string const & providerName) PvaClientChannelPtr PvaClient::createChannel(string const & channelName, string const & providerName)
{ {
return PvaClientChannel::create(shared_from_this(),channelName,providerName); return PvaClientChannel::create(getPtrSelf(),channelName,providerName);
} }
void PvaClient::setRequester(RequesterPtr const & requester) void PvaClient::setRequester(RequesterPtr const & requester)
@@ -191,16 +218,12 @@ void PvaClient::setRequester(RequesterPtr const & requester)
void PvaClient::clearRequester() void PvaClient::clearRequester()
{ {
requester.reset(); requester = Requester::weak_pointer();
} }
void PvaClient::showCache() void PvaClient::showCache()
{ {
if(pvaClientChannelCache->cacheSize()>=1) { pvaClientChannelCache->showCache();
pvaClientChannelCache->showCache();
} else {
cout << "pvaClientChannelCache is empty\n";
}
} }
File diff suppressed because it is too large Load Diff
+143 -218
View File
@@ -8,15 +8,14 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#define epicsExportSharedSymbols
#include <map> #include <map>
#include <pv/event.h> #include <pv/event.h>
#include <pv/lock.h> #include <pv/lock.h>
#include <pv/pvaClient.h>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
@@ -26,13 +25,13 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
class epicsShareClass PvaClientGetCache class PvaClientGetCache
{ {
public: public:
PvaClientGetCache(){} PvaClientGetCache(){}
~PvaClientGetCache() ~PvaClientGetCache();
{ void destroy() {
if(PvaClient::getDebug()) cout << "PvaClientGetCache::~PvaClientGetCache\n"; pvaClientGetMap.clear();
} }
PvaClientGetPtr getGet(string const & request); PvaClientGetPtr getGet(string const & request);
void addGet(string const & request,PvaClientGetPtr const & pvaClientGet); void addGet(string const & request,PvaClientGetPtr const & pvaClientGet);
@@ -42,6 +41,11 @@ private:
map<string,PvaClientGetPtr> pvaClientGetMap; map<string,PvaClientGetPtr> pvaClientGetMap;
}; };
PvaClientGetCache::~PvaClientGetCache()
{
destroy();
}
PvaClientGetPtr PvaClientGetCache::getGet(string const & request) PvaClientGetPtr PvaClientGetCache::getGet(string const & request)
{ {
map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request); map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request);
@@ -51,11 +55,8 @@ PvaClientGetPtr PvaClientGetCache::getGet(string const & request)
void PvaClientGetCache::addGet(string const & request,PvaClientGetPtr const & pvaClientGet) void PvaClientGetCache::addGet(string const & request,PvaClientGetPtr const & pvaClientGet)
{ {
map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request); pvaClientGetMap.insert(std::pair<string,PvaClientGetPtr>(
if(iter!=pvaClientGetMap.end()) { request,pvaClientGet));
throw std::runtime_error("pvaClientGetCache::addGet pvaClientGet already cached");
}
pvaClientGetMap.insert(std::pair<string,PvaClientGetPtr>(request,pvaClientGet));
} }
void PvaClientGetCache::showCache() void PvaClientGetCache::showCache()
@@ -73,13 +74,13 @@ size_t PvaClientGetCache::cacheSize()
} }
class epicsShareClass PvaClientPutCache class PvaClientPutCache
{ {
public: public:
PvaClientPutCache(){} PvaClientPutCache(){}
~PvaClientPutCache() ~PvaClientPutCache();
{ void destroy() {
if(PvaClient::getDebug()) cout << "PvaClientPutCache::~PvaClientPutCache\n"; pvaClientPutMap.clear();
} }
PvaClientPutPtr getPut(string const & request); PvaClientPutPtr getPut(string const & request);
void addPut(string const & request,PvaClientPutPtr const & pvaClientPut); void addPut(string const & request,PvaClientPutPtr const & pvaClientPut);
@@ -89,6 +90,10 @@ private:
map<string,PvaClientPutPtr> pvaClientPutMap; map<string,PvaClientPutPtr> pvaClientPutMap;
}; };
PvaClientPutCache::~PvaClientPutCache()
{
destroy();
}
PvaClientPutPtr PvaClientPutCache::getPut(string const & request) PvaClientPutPtr PvaClientPutCache::getPut(string const & request)
{ {
@@ -99,10 +104,6 @@ PvaClientPutPtr PvaClientPutCache::getPut(string const & request)
void PvaClientPutCache::addPut(string const & request,PvaClientPutPtr const & pvaClientPut) void PvaClientPutCache::addPut(string const & request,PvaClientPutPtr const & pvaClientPut)
{ {
map<string,PvaClientPutPtr>::iterator iter = pvaClientPutMap.find(request);
if(iter!=pvaClientPutMap.end()) {
throw std::runtime_error("pvaClientPutCache::addPut pvaClientPut already cached");
}
pvaClientPutMap.insert(std::pair<string,PvaClientPutPtr>( pvaClientPutMap.insert(std::pair<string,PvaClientPutPtr>(
request,pvaClientPut)); request,pvaClientPut));
} }
@@ -122,63 +123,30 @@ size_t PvaClientPutCache::cacheSize()
} }
class epicsShareClass ChannelRequesterImpl : public ChannelRequester class ChannelRequesterImpl : public ChannelRequester
{ {
PvaClientChannel::weak_pointer pvaClientChannel; PvaClientChannel *pvaClientChannel;
PvaClient::weak_pointer pvaClient;
public: public:
ChannelRequesterImpl( ChannelRequesterImpl(PvaClientChannel *pvaClientChannel)
PvaClientChannelPtr const & pvaClientChannel, : pvaClientChannel(pvaClientChannel) {}
PvaClientPtr const &pvaClient) void channelCreated(
: pvaClientChannel(pvaClientChannel), const Status& status,
pvaClient(pvaClient) Channel::shared_pointer const & channel)
{} { pvaClientChannel->channelCreated(status,channel); }
virtual ~ChannelRequesterImpl() { void channelStateChange(
if(PvaClient::getDebug()) std::cout << "~ChannelRequesterImpl" << std::endl; Channel::shared_pointer const & channel,
} Channel::ConnectionState connectionState)
{pvaClientChannel->channelStateChange(channel,connectionState);}
virtual std::string getRequesterName() { tr1::shared_ptr<Channel> getChannel() {return pvaClientChannel->getChannel();}
PvaClientChannelPtr clientChannel(pvaClientChannel.lock()); string getRequesterName()
if(!clientChannel) return string("clientChannel is null"); {return pvaClientChannel->getRequesterName();}
return clientChannel->getRequesterName(); void message(
} string const & message,
MessageType messageType)
virtual void message(std::string const & message, epics::pvData::MessageType messageType) { { pvaClientChannel->message(message,messageType); }
PvaClientChannelPtr clientChannel(pvaClientChannel.lock()); void destroy() {pvaClientChannel->destroy();}
if(!clientChannel) return;
clientChannel->message(message,messageType);
}
virtual void channelCreated(
const epics::pvData::Status& status,
Channel::shared_pointer const & channel)
{
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->channelCreated(status,channel);
}
virtual void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->channelStateChange(channel,connectionState);
}
}; };
PvaClientChannelPtr PvaClientChannel::create(
PvaClientPtr const &pvaClient,
string const & channelName,
string const & providerName)
{
PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
channel->channelRequester = ChannelRequesterImplPtr(
new ChannelRequesterImpl(channel,pvaClient));
return channel;
}
PvaClientChannel::PvaClientChannel( PvaClientChannel::PvaClientChannel(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
@@ -188,81 +156,44 @@ PvaClientChannel::PvaClientChannel(
channelName(channelName), channelName(channelName),
providerName(providerName), providerName(providerName),
connectState(connectIdle), connectState(connectIdle),
isDestroyed(false),
createRequest(CreateRequest::create()), createRequest(CreateRequest::create()),
pvaClientGetCache(new PvaClientGetCache()), pvaClientGetCache(new PvaClientGetCache()),
pvaClientPutCache(new PvaClientPutCache()) pvaClientPutCache(new PvaClientPutCache())
{ {}
if(PvaClient::getDebug()) {
cout << "PvaClientChannel::PvaClientChannel channelName " << channelName << endl;
}
}
PvaClientChannel::~PvaClientChannel() PvaClientChannel::~PvaClientChannel()
{ {
if(PvaClient::getDebug()) { destroy();
cout << "PvaClientChannel::~PvaClientChannel() "
<< " channelName " << channelName
<< endl;
}
if(PvaClient::getDebug()) showCache();
} }
void PvaClientChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel) void PvaClientChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
cout << "PvaClientChannel::channelCreated" if(status.isOK()) {
<< " channelName " << channelName this->channel = channel;
<< " connectState " << connectState return;
<< " isConnected " << (channel->isConnected() ? "true" : "false")
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
Lock xx(mutex);
if(connectState==connected) return;
if(connectState!=connectActive) {
string message("PvaClientChannel::channelCreated");
message += " channel " + channelName
+ " why was this called when connectState!=ConnectState.connectActive";
throw std::runtime_error(message);
}
if(!status.isOK()) {
string message("PvaClientChannel::channelCreated");
+ " status " + status.getMessage() + " why??";
throw std::runtime_error(message);
}
if(channel->isConnected()) {
connectState = connected;
waitForConnect.signal();
} }
cout << "PvaClientChannel::channelCreated status " << status.getMessage() << " why??\n";
} }
void PvaClientChannel::channelStateChange( void PvaClientChannel::channelStateChange(
Channel::shared_pointer const & channel, Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState) Channel::ConnectionState connectionState)
{ {
if(PvaClient::getDebug()) {
cout << " PvaClientChannel::channelStateChange "
<< " channelName " << channelName
<< " " << Channel::ConnectionStateNames[connectionState]
<< endl;
}
PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock());
if(req) {
bool value = (connectionState==Channel::CONNECTED ? true : false);
req->channelStateChange(shared_from_this(),value);
}
Lock xx(mutex); Lock xx(mutex);
if(isDestroyed) return;
bool waitingForConnect = false; bool waitingForConnect = false;
if(connectState==connectActive) waitingForConnect = true; if(connectState==connectActive) waitingForConnect = true;
if(connectionState!=Channel::CONNECTED) { if(connectionState!=Channel::CONNECTED) {
string mess(channelName + string mess(channelName +
" connection state " + Channel::ConnectionStateNames[connectionState]); " connection state " + Channel::ConnectionStateNames[connectionState]);
message(mess,errorMessage); message(mess,errorMessage);
connectState = notConnected; channelConnectStatus = Status(Status::STATUSTYPE_ERROR,mess);
return; connectState = notConnected;
} else { } else {
connectState = connected; connectState = connected;
channelConnectStatus = Status::Ok;
} }
if(waitingForConnect) waitForConnect.signal(); if(waitingForConnect) waitForConnect.signal();
} }
@@ -270,7 +201,7 @@ void PvaClientChannel::channelStateChange(
string PvaClientChannel::getRequesterName() string PvaClientChannel::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientChannel::getRequesterName() PvaClient isDestroyed"); if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return yyy->getRequesterName(); return yyy->getRequesterName();
} }
@@ -278,87 +209,82 @@ void PvaClientChannel::message(
string const & message, string const & message,
MessageType messageType) MessageType messageType)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return; if(!yyy) throw std::runtime_error("PvaClient was destroyed");
yyy->message(channelName + " " + message, messageType); yyy->message(channelName + " " + message, messageType);
} }
void PvaClientChannel::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channel) channel->destroy();
channel.reset();
pvaClientGetCache.reset();
pvaClientPutCache.reset();
}
string PvaClientChannel::getChannelName() string PvaClientChannel::getChannelName()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
return channelName; return channelName;
} }
Channel::shared_pointer PvaClientChannel::getChannel() Channel::shared_pointer PvaClientChannel::getChannel()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
return channel; return channel;
} }
void PvaClientChannel::setStateChangeRequester(
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester)
{
this->stateChangeRequester = stateChangeRequester;
}
void PvaClientChannel::connect(double timeout) void PvaClientChannel::connect(double timeout)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
cout << "PvaClientChannel::connect"
<< " channelName " << channelName << endl;
}
issueConnect(); issueConnect();
Status status = waitConnect(timeout); Status status = waitConnect(timeout);
if(status.isOK()) return; if(status.isOK()) return;
if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n"; string message = string("channel ") + getChannelName()
string message = string("channel ") + channelName
+ " PvaClientChannel::connect " + status.getMessage(); + " PvaClientChannel::connect " + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientChannel::issueConnect() void PvaClientChannel::issueConnect()
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
cout << "PvaClientChannel::issueConnect" if(connectState!=connectIdle) {
<< " channelName " << channelName << endl; throw std::runtime_error("pvaClientChannel already connected");
}
{
Lock xx(mutex);
if(connectState==connected) return;
if(connectState!=connectIdle) {
throw std::runtime_error("pvaClientChannel already connected");
}
connectState = connectActive;
} }
channelRequester = ChannelRequester::shared_pointer(new ChannelRequesterImpl(this));
channelConnectStatus = Status(
Status::STATUSTYPE_ERROR,
getChannelName() + " createChannel failed");
connectState = connectActive;
ChannelProviderRegistry::shared_pointer reg = getChannelProviderRegistry(); ChannelProviderRegistry::shared_pointer reg = getChannelProviderRegistry();
ChannelProvider::shared_pointer provider = reg->getProvider(providerName); ChannelProvider::shared_pointer provider = reg->getProvider(providerName);
if(!provider) { if(!provider) {
throw std::runtime_error(channelName + " provider " + providerName + " not registered"); throw std::runtime_error(getChannelName() + " provider " + providerName + " not registered");
} }
if(PvaClient::getDebug()) cout << "PvaClientChannel::issueConnect calling provider->createChannel\n";
channel = provider->createChannel(channelName,channelRequester,ChannelProvider::PRIORITY_DEFAULT); channel = provider->createChannel(channelName,channelRequester,ChannelProvider::PRIORITY_DEFAULT);
if(!channel) { if(!channel) {
throw std::runtime_error(channelName + " channelCreate failed "); throw std::runtime_error(getChannelName() + " channelCreate failed ");
} }
} }
Status PvaClientChannel::waitConnect(double timeout) Status PvaClientChannel::waitConnect(double timeout)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientChannel was destroyed");
cout << "PvaClientChannel::waitConnect" waitForConnect.wait(timeout);
<< " channelName " << channelName << endl; return channelConnectStatus;
}
{
Lock xx(mutex);
if(channel->isConnected()) return Status::Ok;
}
if(timeout>0.0) {
waitForConnect.wait(timeout);
} else {
waitForConnect.wait();
}
if(channel->isConnected()) return Status::Ok;
return Status(Status::STATUSTYPE_ERROR,channelName + " not connected");
} }
PvaClientFieldPtr PvaClientChannel::createField()
{
return createField("");
}
PvaClientFieldPtr PvaClientChannel::createField(string const & subField) PvaClientFieldPtr PvaClientChannel::createField(string const & subField)
{ {
@@ -366,11 +292,16 @@ PvaClientFieldPtr PvaClientChannel::createField(string const & subField)
throw std::runtime_error("PvaClientChannel::createField not implemented"); throw std::runtime_error("PvaClientChannel::createField not implemented");
} }
PvaClientProcessPtr PvaClientChannel::createProcess()
{
return createProcess("");
}
PvaClientProcessPtr PvaClientChannel::createProcess(string const & request) PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) { if(!pvRequest) {
string message = string("channel ") + channelName string message = string("channel ") + getChannelName()
+ " PvaClientChannel::createProcess invalid pvRequest: " + " PvaClientChannel::createProcess invalid pvRequest: "
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -386,6 +317,7 @@ PvaClientProcessPtr PvaClientChannel::createProcess(PVStructurePtr const & pvRe
return PvaClientProcess::create(yyy,channel,pvRequest); return PvaClientProcess::create(yyy,channel,pvRequest);
} }
PvaClientGetPtr PvaClientChannel::get() {return get("value,alarm,timeStamp");}
PvaClientGetPtr PvaClientChannel::get(string const & request) PvaClientGetPtr PvaClientChannel::get(string const & request)
{ {
@@ -397,12 +329,16 @@ PvaClientGetPtr PvaClientChannel::get(string const & request)
return pvaClientGet; return pvaClientGet;
} }
PvaClientGetPtr PvaClientChannel::createGet()
{
return PvaClientChannel::createGet("value,alarm,timeStamp");
}
PvaClientGetPtr PvaClientChannel::createGet(string const & request) PvaClientGetPtr PvaClientChannel::createGet(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) { if(!pvRequest) {
string message = string("channel ") + channelName string message = string("channel ") + getChannelName()
+ " PvaClientChannel::createGet invalid pvRequest: " + " PvaClientChannel::createGet invalid pvRequest: "
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -418,6 +354,7 @@ PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest)
return PvaClientGet::create(yyy,channel,pvRequest); return PvaClientGet::create(yyy,channel,pvRequest);
} }
PvaClientPutPtr PvaClientChannel::put() {return put("value");}
PvaClientPutPtr PvaClientChannel::put(string const & request) PvaClientPutPtr PvaClientChannel::put(string const & request)
{ {
@@ -430,12 +367,16 @@ PvaClientPutPtr PvaClientChannel::put(string const & request)
return pvaClientPut; return pvaClientPut;
} }
PvaClientPutPtr PvaClientChannel::createPut()
{
return createPut("value");
}
PvaClientPutPtr PvaClientChannel::createPut(string const & request) PvaClientPutPtr PvaClientChannel::createPut(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) { if(!pvRequest) {
string message = string("channel ") + channelName string message = string("channel ") + getChannelName()
+ " PvaClientChannel::createPut invalid pvRequest: " + " PvaClientChannel::createPut invalid pvRequest: "
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -451,11 +392,16 @@ PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
return PvaClientPut::create(yyy,channel,pvRequest); return PvaClientPut::create(yyy,channel,pvRequest);
} }
PvaClientPutGetPtr PvaClientChannel::createPutGet()
{
return createPutGet("putField(argument)getField(result)");
}
PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request) PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) { if(!pvRequest) {
string message = string("channel ") + channelName string message = string("channel ") + getChannelName()
+ " PvaClientChannel::createPutGet invalid pvRequest: " + " PvaClientChannel::createPutGet invalid pvRequest: "
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -472,12 +418,16 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
} }
PvaClientArrayPtr PvaClientChannel::createArray()
{
return createArray("value");
}
PvaClientArrayPtr PvaClientChannel::createArray(string const & request) PvaClientArrayPtr PvaClientChannel::createArray(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) { if(!pvRequest) {
string message = string("channel ") + channelName string message = string("channel ") + getChannelName()
+ " PvaClientChannel::createArray invalid pvRequest: " + " PvaClientChannel::createArray invalid pvRequest: "
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -492,6 +442,8 @@ PvaClientArrayPtr PvaClientChannel::createArray(PVStructurePtr const & pvReques
} }
PvaClientMonitorPtr PvaClientChannel::monitor() {return monitor("value,alarm,timeStamp");}
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request) PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
{ {
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request); PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
@@ -502,7 +454,7 @@ PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
PvaClientMonitorPtr PvaClientChannel::monitor(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester) PvaClientMonitorPtr PvaClientChannel::monitor(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
{ {
return monitor("field(value,alarm,timeStamp)",pvaClientMonitorRequester); return monitor("value,alarm,timeStamp",pvaClientMonitorRequester);
} }
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request, PvaClientMonitorPtr PvaClientChannel::monitor(string const & request,
@@ -515,11 +467,16 @@ PvaClientMonitorPtr PvaClientChannel::monitor(string const & request,
return pvaClientMonitor; return pvaClientMonitor;
} }
PvaClientMonitorPtr PvaClientChannel::createMonitor()
{
return createMonitor("value,alarm,timeStamp");
}
PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request) PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) { if(!pvRequest) {
string message = string("channel ") + channelName string message = string("channel ") + getChannelName()
+ " PvaClientChannel::createMonitor invalid pvRequest: " + " PvaClientChannel::createMonitor invalid pvRequest: "
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -535,52 +492,12 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(PVStructurePtr const & pvR
return PvaClientMonitor::create(yyy,channel,pvRequest); return PvaClientMonitor::create(yyy,channel,pvRequest);
} }
PVStructurePtr PvaClientChannel::rpc(
PVStructurePtr const & pvRequest,
PVStructurePtr const & pvArgument)
{
PvaClientRPCPtr rpc = createRPC(pvRequest);
return rpc->request(pvArgument);
}
PVStructurePtr PvaClientChannel::rpc(
PVStructurePtr const & pvArgument)
{
PvaClientRPCPtr rpc = createRPC();
return rpc->request(pvArgument);
}
PvaClientRPCPtr PvaClientChannel::createRPC()
{
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientRPC::create(yyy,channel);
}
PvaClientRPCPtr PvaClientChannel::createRPC(PVStructurePtr const & pvRequest)
{
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientRPC::create(yyy,channel,pvRequest);
}
void PvaClientChannel::showCache() void PvaClientChannel::showCache()
{ {
if(pvaClientGetCache->cacheSize()>=1) { cout << " pvaClientGet" << endl;
cout << " pvaClientGet cache" << endl; pvaClientGetCache->showCache();
pvaClientGetCache->showCache(); cout << " pvaClientPut" << endl;
} else { pvaClientPutCache->showCache();
cout << " pvaClientGet cache is empty\n";
}
if(pvaClientPutCache->cacheSize()>=1) {
cout << " pvaClientPut cache" << endl;
pvaClientPutCache->showCache();
} else {
cout << " pvaClientPut cache is empty\n";
}
} }
size_t PvaClientChannel::cacheSize() size_t PvaClientChannel::cacheSize()
@@ -589,5 +506,13 @@ size_t PvaClientChannel::cacheSize()
} }
PvaClientChannelPtr PvaClientChannel::create(
PvaClientPtr const &pvaClient,
string const & channelName,
string const & providerName)
{
PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
return channel;
}
}} }}
+80 -155
View File
@@ -8,11 +8,9 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#include <pv/event.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/event.h>
#include <pv/pvaClient.h> #include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
@@ -22,67 +20,30 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
class ChannelGetRequesterImpl : public ChannelGetRequester class ChannelGetRequesterImpl : public ChannelGetRequester
{ {
PvaClientGet::weak_pointer pvaClientGet; PvaClientGet * pvaClientGet;
PvaClient::weak_pointer pvaClient;
public: public:
ChannelGetRequesterImpl( ChannelGetRequesterImpl(PvaClientGet * pvaClientGet)
PvaClientGetPtr const & pvaClientGet, : pvaClientGet(pvaClientGet) {}
PvaClientPtr const &pvaClient) string getRequesterName()
: pvaClientGet(pvaClientGet), {return pvaClientGet->getRequesterName();}
pvaClient(pvaClient) void message(string const & message,MessageType messageType)
{} {pvaClientGet->message(message,messageType);}
virtual ~ChannelGetRequesterImpl() { void channelGetConnect(
if(PvaClient::getDebug()) std::cout << "~ChannelGetRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return string("clientGet is null");
return clientGet->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return;
clientGet->message(message,messageType);
}
virtual void channelGetConnect(
const Status& status, const Status& status,
ChannelGet::shared_pointer const & channelGet, ChannelGet::shared_pointer const & channelGet,
Structure::const_shared_pointer const & structure) StructureConstPtr const & structure)
{ {pvaClientGet->channelGetConnect(status,channelGet,structure);}
PvaClientGetPtr clientGet(pvaClientGet.lock()); void getDone(
if(!clientGet) return;
clientGet->channelGetConnect(status,channelGet,structure);
}
virtual void getDone(
const Status& status, const Status& status,
ChannelGet::shared_pointer const & channelGet, ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure, PVStructurePtr const & pvStructure,
BitSet::shared_pointer const & bitSet) BitSetPtr const & bitSet)
{ {pvaClientGet->getDone(status,channelGet,pvStructure,bitSet);}
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return;
clientGet->getDone(status,channelGet,pvStructure,bitSet);
}
}; };
PvaClientGetPtr PvaClientGet::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientGetPtr epv(new PvaClientGet(pvaClient,channel,pvRequest));
epv->channelGetRequester = ChannelGetRequesterImplPtr(
new ChannelGetRequesterImpl(epv,pvaClient));
return epv;
}
PvaClientGet::PvaClientGet( PvaClientGet::PvaClientGet(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, Channel::shared_pointer const & channel,
@@ -90,31 +51,20 @@ PvaClientGet::PvaClientGet(
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), channel(channel),
pvRequest(pvRequest), pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle), connectState(connectIdle),
getState(getIdle) getState(getIdle)
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGet::PvaClientGet::PvaClientGet"
<< " channelName " << channel->getChannelName()
<< endl;
}
} }
PvaClientGet::~PvaClientGet() PvaClientGet::~PvaClientGet()
{ {
if(PvaClient::getDebug()) { destroy();
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientGet::~PvaClientGet"
<< " channelName " << channelName
<< endl;
}
if(channelGet) channelGet->destroy();
} }
void PvaClientGet::checkGetState() void PvaClientGet::checkGetState()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(getState==getIdle) get(); if(getState==getIdle) get();
} }
@@ -122,15 +72,16 @@ void PvaClientGet::checkGetState()
// from ChannelGetRequester // from ChannelGetRequester
string PvaClientGet::getRequesterName() string PvaClientGet::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientGet::getRequesterName PvaClient isDestroyed"); if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName(); return yyy->getRequesterName();
} }
void PvaClientGet::message(string const & message,MessageType messageType) void PvaClientGet::message(string const & message,MessageType messageType)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return; if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType); yyy->message(message, messageType);
} }
@@ -139,24 +90,13 @@ void PvaClientGet::channelGetConnect(
ChannelGet::shared_pointer const & channelGet, ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const & structure) StructureConstPtr const & structure)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
string channelName("disconnected"); channelGetConnectStatus = status;
Channel::shared_pointer chan(channel.lock()); this->channelGet = channelGet;
if(chan) channelName = chan->getChannelName(); if(status.isOK()) {
cout << "PvaClientGet::channelGetConnect" pvaClientData = PvaClientGetData::create(structure);
<< " channelName " << channelName pvaClientData->setMessagePrefix(channel->getChannelName());
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelGetConnectStatus = status;
connectState = connected; connectState = connected;
this->channelGet = channelGet;
if(status.isOK()) {
pvaClientData = PvaClientGetData::create(structure);
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName());
}
} }
waitForConnect.signal(); waitForConnect.signal();
@@ -168,99 +108,82 @@ void PvaClientGet::getDone(
PVStructurePtr const & pvStructure, PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet) BitSetPtr const & bitSet)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
string channelName("disconnected"); channelGetStatus = status;
Channel::shared_pointer chan(channel.lock()); if(status.isOK()) {
if(chan) channelName = chan->getChannelName(); pvaClientData->setData(pvStructure,bitSet);
cout << "PvaClientGet::getDone"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelGetStatus = status;
if(status.isOK()) {
pvaClientData->setData(pvStructure,bitSet);
}
} }
waitForGet.signal(); waitForGet.signal();
} }
// from PvaClientGet
void PvaClientGet::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelGet) channelGet->destroy();
channelGet.reset();
}
void PvaClientGet::connect() void PvaClientGet::connect()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::connect " + status.getMessage(); + " PvaClientGet::connect " + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientGet::issueConnect() void PvaClientGet::issueConnect()
{ {
Channel::shared_pointer chan(channel.lock()); if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ") + channel->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " pvaClientGet already connected "; + " pvaClientGet already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { getRequester = ChannelGetRequester::shared_pointer(new ChannelGetRequesterImpl(this));
connectState = connectActive; connectState = connectActive;
channelGet = chan->createChannelGet(channelGetRequester,pvRequest); channelGet = channel->createChannelGet(getRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientGet::issueConnect channel was destroyed");
} }
Status PvaClientGet::waitConnect() Status PvaClientGet::waitConnect()
{ {
{ if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
Lock xx(mutex); if(connectState==connected) return channelGetConnectStatus;
if(connectState==connected) { if(connectState!=connectActive) {
if(!channelGetConnectStatus.isOK()) connectState = connectIdle; string message = string("channel ") + channel->getChannelName()
return channelGetConnectStatus; + " pvaClientGet illegal connect state ";
} throw std::runtime_error(message);
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
} }
waitForConnect.wait(); waitForConnect.wait();
if(!channelGetConnectStatus.isOK()) connectState = connectIdle; connectState = channelGetConnectStatus.isOK() ? connected : connectIdle;
return channelGetConnectStatus; return channelGetConnectStatus;
} }
void PvaClientGet::get() void PvaClientGet::get()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
issueGet(); issueGet();
Status status = waitGet(); Status status = waitGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::get " + status.getMessage(); + " PvaClientGet::get " + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientGet::issueGet() void PvaClientGet::issueGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(getState!=getIdle) { if(getState!=getIdle) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::issueGet get aleady active "; + " PvaClientGet::issueGet get aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -270,23 +193,17 @@ void PvaClientGet::issueGet()
Status PvaClientGet::waitGet() Status PvaClientGet::waitGet()
{ {
{ if(isDestroyed) throw std::runtime_error("pvaClientGet was destroyed");
Lock xx(mutex); if(getState!=getActive){
if(getState==getComplete) { string message = string("channel ") + channel->getChannelName()
getState =getIdle; + " PvaClientGet::waitGet llegal get state";
return channelGetStatus; throw std::runtime_error(message);
}
if(getState!=getActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::waitGet llegal get state";
throw std::runtime_error(message);
}
} }
waitForGet.wait(); waitForGet.wait();
getState = getIdle; getState = getIdle;
if(channelGetStatus.isOK()) {
return Status::Ok;
}
return channelGetStatus; return channelGetStatus;
} }
PvaClientGetDataPtr PvaClientGet::getData() PvaClientGetDataPtr PvaClientGet::getData()
@@ -295,5 +212,13 @@ PvaClientGetDataPtr PvaClientGet::getData()
return pvaClientData; return pvaClientData;
} }
PvaClientGetPtr PvaClientGet::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientGetPtr epv(new PvaClientGet(pvaClient,channel,pvRequest));
return epv;
}
}} }}
+3 -4
View File
@@ -8,16 +8,15 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#define epicsExportSharedSymbols
#include <typeinfo> #include <typeinfo>
#include <sstream>
#include <sstream>
#include <pv/pvaClient.h>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#include <pv/convert.h> #include <pv/convert.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
+79 -298
View File
@@ -8,87 +8,44 @@
* @author mrk * @author mrk
* @date 2015.03 * @date 2015.03
*/ */
#define epicsExportSharedSymbols
#include <sstream> #include <sstream>
#include <pv/event.h> #include <pv/event.h>
#include <pv/pvaClient.h>
#include <pv/bitSetUtil.h> #include <pv/bitSetUtil.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
using namespace epics::pvAccess; using namespace epics::pvAccess;
using namespace std; using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
class MonitorRequesterImpl : public MonitorRequester
class ChannelMonitorRequester : public MonitorRequester
{ {
PvaClientMonitor::weak_pointer pvaClientMonitor; PvaClientMonitor * pvaClientMonitor;
PvaClient::weak_pointer pvaClient;
public: public:
MonitorRequesterImpl( ChannelMonitorRequester(PvaClientMonitor * pvaClientMonitor)
PvaClientMonitorPtr const & pvaClientMonitor, : pvaClientMonitor(pvaClientMonitor) {}
PvaClientPtr const &pvaClient) string getRequesterName()
: pvaClientMonitor(pvaClientMonitor), {return pvaClientMonitor->getRequesterName();}
pvaClient(pvaClient) void message(string const & message,MessageType messageType)
{} {pvaClientMonitor->message(message,messageType);}
virtual ~MonitorRequesterImpl() { void monitorConnect(
if(PvaClient::getDebug()) std::cout << "~MonitorRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return string("pvaClientMonitor is null");
return clientMonitor->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->message(message,messageType);
}
virtual void monitorConnect(
const Status& status, const Status& status,
Monitor::shared_pointer const & monitor, Monitor::shared_pointer const & monitor,
Structure::const_shared_pointer const & structure) StructureConstPtr const & structure)
{pvaClientMonitor->monitorConnect(status,monitor,structure);}
void monitorEvent(MonitorPtr const & monitor)
{ {
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock()); pvaClientMonitor->monitorEvent(monitor);
if(!clientMonitor) return;
clientMonitor->monitorConnect(status,monitor,structure);
}
virtual void unlisten(epics::pvData::MonitorPtr const & monitor)
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->unlisten(monitor);
}
virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor)
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->monitorEvent(monitor);
} }
void unlisten(MonitorPtr const & monitor)
{pvaClientMonitor->unlisten();}
}; };
PvaClientMonitorPtr PvaClientMonitor::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientMonitorPtr epv(new PvaClientMonitor(pvaClient,channel,pvRequest));
epv->monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(epv,pvaClient));
return epv;
}
PvaClientMonitor::PvaClientMonitor( PvaClientMonitor::PvaClientMonitor(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, Channel::shared_pointer const & channel,
@@ -96,61 +53,38 @@ PvaClientMonitor::PvaClientMonitor(
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), channel(channel),
pvRequest(pvRequest), pvRequest(pvRequest),
isStarted(false), isDestroyed(false),
connectState(connectIdle), connectState(connectIdle),
userPoll(false), userPoll(false),
userWait(false) userWait(false)
{ {
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::PvaClientMonitor()"
<< " channelName " << channel->getChannelName()
<< endl;
}
} }
PvaClientMonitor::~PvaClientMonitor() PvaClientMonitor::~PvaClientMonitor()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMonitor::~PvaClientMonitor\n"; destroy();
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientMonitor::~PvaClientMonitor"
<< " channelName " << channelName
<< endl;
}
if(monitor) {
if(isStarted) monitor->stop();
monitor->destroy();
}
} }
void PvaClientMonitor::checkMonitorState() void PvaClientMonitor::checkMonitorState()
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::checkMonitorState"
<< " channelName " << channelName
<< " connectState " << connectState
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(connectState==connected && !isStarted) start(); if(connectState==connected) start();
} }
// from MonitorRequester
string PvaClientMonitor::getRequesterName() string PvaClientMonitor::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientMonitor::getRequesterName() PvaClient isDestroyed"); if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName(); return yyy->getRequesterName();
} }
void PvaClientMonitor::message(string const & message,MessageType messageType) void PvaClientMonitor::message(string const & message,MessageType messageType)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return; if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType); yyy->message(message, messageType);
} }
@@ -159,37 +93,12 @@ void PvaClientMonitor::monitorConnect(
Monitor::shared_pointer const & monitor, Monitor::shared_pointer const & monitor,
StructureConstPtr const & structure) StructureConstPtr const & structure)
{ {
Channel::shared_pointer chan(channel.lock()); if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorConnect"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
connectStatus = status; connectStatus = status;
connectState = connected;
this->monitor = monitor; this->monitor = monitor;
if(isStarted) { if(status.isOK()) {
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorConnect"
<< " channelName " << channelName
<< " is already started "
<< endl;
}
return;
}
if(status.isOK() && chan) {
pvaClientData = PvaClientMonitorData::create(structure); pvaClientData = PvaClientMonitorData::create(structure);
pvaClientData->setMessagePrefix(chan->getChannelName()); pvaClientData->setMessagePrefix(channel->getChannelName());
}
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
} }
waitForConnect.signal(); waitForConnect.signal();
@@ -197,188 +106,95 @@ void PvaClientMonitor::monitorConnect(
void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor) void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorEvent"
<< " channelName " << channelName
<< endl;
}
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock(); PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) req->event(shared_from_this()); if(req) req->event(getPtrSelf());
if(userWait) waitForEvent.signal(); if(userWait) waitForEvent.signal();
} }
void PvaClientMonitor::unlisten(MonitorPtr const & monitor) void PvaClientMonitor::unlisten()
{ {
if(PvaClient::getDebug()) cout << "PvaClientMonitor::unlisten\n"; destroy();
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) {
req->unlisten();
return;
}
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cerr << channelName + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
} }
void PvaClientMonitor::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(monitor) monitor->destroy();
monitor.reset();
monitorElement.reset();
}
void PvaClientMonitor::connect() void PvaClientMonitor::connect()
{ {
if(PvaClient::getDebug()) cout << "PvaClientMonitor::connect\n"; if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientMonitor::connect " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientMonitor::connect "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientMonitor::issueConnect() void PvaClientMonitor::issueConnect()
{ {
if(PvaClient::getDebug()) cout << "PvaClientMonitor::issueConnect\n"; if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
Channel::shared_pointer chan(channel.lock());
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ") + channel->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " pvaClientMonitor already connected "; + " pvaClientMonitor already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { monitorRequester = ChannelMonitorRequester::shared_pointer(new ChannelMonitorRequester(this));
connectState = connectActive; connectState = connectActive;
monitor = chan->createMonitor(monitorRequester,pvRequest); monitor = channel->createMonitor(monitorRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientMonitor::issueConnect() but channel disconnected");
} }
Status PvaClientMonitor::waitConnect() Status PvaClientMonitor::waitConnect()
{ {
if(PvaClient::getDebug()) cout << "PvaClientMonitor::waitConnect\n"; if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
if(connectState==connected) {
if(!connectStatus.isOK()) connectState = connectIdle;
return connectStatus;
}
if(connectState!=connectActive) { if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " pvaClientMonitor illegal connect state ";
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientMonitor::waitConnect illegal connect state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect calling waitForConnect.wait\n";
}
waitForConnect.wait(); waitForConnect.wait();
connectState = connectStatus.isOK() ? connected : connectIdle; connectState = connectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect"
<< " connectStatus " << (connectStatus.isOK() ? "connected" : "not connected");
}
return connectStatus; return connectStatus;
} }
void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester) void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClientMonitorrRequester)
{ {
if(PvaClient::getDebug()) { this->pvaClientMonitorRequester = pvaClientMonitorrRequester;
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::setRequester"
<< " channelName " << channelName
<< endl;
}
this->pvaClientMonitorRequester = pvaClientMonitorRequester;
} }
void PvaClientMonitor::start() void PvaClientMonitor::start()
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
string channelName("disconnected"); if(connectState==monitorStarted) return;
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::start"
<< " channelName " << channelName
<< " connectState " << connectState
<< endl;
}
if(isStarted) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cerr << "PvaClientMonitor::start"
<< " channelName " << channelName
<< " why is this called twice "
<< endl;
return;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(connectState!=connected) { if(connectState!=connected) throw std::runtime_error("PvaClientMonitor::start illegal state");
Channel::shared_pointer chan(channel.lock()); connectState = monitorStarted;
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::start illegal state ";
throw std::runtime_error(message);
}
isStarted = true;
monitor->start(); monitor->start();
} }
void PvaClientMonitor::stop() void PvaClientMonitor::stop()
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
string channelName("disconnected"); if(connectState!=monitorStarted) return;
Channel::shared_pointer chan(channel.lock()); connectState = connected;
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::stop"
<< " channelName " << channelName
<< endl;
}
if(!isStarted) return;
isStarted = false;
monitor->stop(); monitor->stop();
} }
bool PvaClientMonitor::poll() bool PvaClientMonitor::poll()
{ {
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::poll"
<< " channelName " << channelName
<< endl;
}
checkMonitorState(); checkMonitorState();
if(!isStarted) { if(connectState!=monitorStarted) throw std::runtime_error("PvaClientMonitor::poll illegal state");
string channelName("disconnected"); if(userPoll) throw std::runtime_error("PvaClientMonitor::poll did not release last");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::poll illegal state ";
throw std::runtime_error(message);
}
if(userPoll) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::poll did not release last";
throw std::runtime_error(message);
}
monitorElement = monitor->poll(); monitorElement = monitor->poll();
if(!monitorElement) return false; if(!monitorElement) return false;
userPoll = true; userPoll = true;
@@ -388,22 +204,8 @@ bool PvaClientMonitor::poll()
bool PvaClientMonitor::waitEvent(double secondsToWait) bool PvaClientMonitor::waitEvent(double secondsToWait)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
string channelName("disconnected"); if(connectState!=monitorStarted) throw std::runtime_error("PvaClientMonitor::waitEvent illegal state");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::waitEvent"
<< " channelName " << channelName
<< endl;
}
if(!isStarted) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::waitEvent illegal state ";
throw std::runtime_error(message);
}
if(poll()) return true; if(poll()) return true;
userWait = true; userWait = true;
if(secondsToWait==0.0) { if(secondsToWait==0.0) {
@@ -417,47 +219,26 @@ bool PvaClientMonitor::waitEvent(double secondsToWait)
void PvaClientMonitor::releaseEvent() void PvaClientMonitor::releaseEvent()
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientMonitor was destroyed");
string channelName("disconnected"); if(connectState!=monitorStarted) throw std::runtime_error("PvaClientMonitor::poll illegal state");
Channel::shared_pointer chan(channel.lock()); if(!userPoll) throw std::runtime_error("PvaClientMonitor::releaseEvent did not call poll");
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::releaseEvent"
<< " channelName " << channelName
<< endl;
}
if(!isStarted) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::releaseEvent monitor not started ";
throw std::runtime_error(message);
}
if(!userPoll) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::releaseEvent did not call poll";
throw std::runtime_error(message);
}
userPoll = false; userPoll = false;
monitor->release(monitorElement); monitor->release(monitorElement);
} }
PvaClientMonitorDataPtr PvaClientMonitor::getData() PvaClientMonitorDataPtr PvaClientMonitor::getData()
{ {
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::getData"
<< " channelName " << channelName
<< endl;
}
checkMonitorState(); checkMonitorState();
return pvaClientData; return pvaClientData;
} }
PvaClientMonitorPtr PvaClientMonitor::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientMonitorPtr epv(new PvaClientMonitor(pvaClient,channel,pvRequest));
return epv;
}
}} }}
+3 -4
View File
@@ -8,16 +8,15 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#define epicsExportSharedSymbols
#include <typeinfo> #include <typeinfo>
#include <sstream>
#include <sstream>
#include <pv/pvaClient.h>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#include <pv/convert.h> #include <pv/convert.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
+39 -13
View File
@@ -8,13 +8,11 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#define epicsExportSharedSymbols
#include <map> #include <map>
#include <pv/event.h> #include <pv/event.h>
#include <pv/lock.h> #include <pv/lock.h>
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h> #include <pv/pvaClientMultiChannel.h>
@@ -53,28 +51,40 @@ PvaClientMultiChannel::PvaClientMultiChannel(
numConnected(0), numConnected(0),
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())), pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)), isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
createRequest(CreateRequest::create()) createRequest(CreateRequest::create()),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiChannel::PvaClientMultiChannel()\n";
} }
PvaClientMultiChannel::~PvaClientMultiChannel() PvaClientMultiChannel::~PvaClientMultiChannel()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiChannel::~PvaClientMultiChannel()\n"; destroy();
}
void PvaClientMultiChannel::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
} }
void PvaClientMultiChannel::checkConnected() void PvaClientMultiChannel::checkConnected()
{ {
if(numConnected==0) connect(); if(numConnected==0) connect(3.0);
} }
epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames() epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
return channelName; return channelName;
} }
Status PvaClientMultiChannel::connect(double timeout) Status PvaClientMultiChannel::connect(double timeout)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
for(size_t i=0; i< numChannel; ++i) { for(size_t i=0; i< numChannel; ++i) {
pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName); pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName);
pvaClientChannelArray[i]->issueConnect(); pvaClientChannelArray[i]->issueConnect();
@@ -103,11 +113,13 @@ Status PvaClientMultiChannel::connect(double timeout)
bool PvaClientMultiChannel::allConnected() bool PvaClientMultiChannel::allConnected()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
return (numConnected==numChannel) ? true : false; return (numConnected==numChannel) ? true : false;
} }
bool PvaClientMultiChannel::connectionChange() bool PvaClientMultiChannel::connectionChange()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
for(size_t i=0; i<numChannel; ++i) { for(size_t i=0; i<numChannel; ++i) {
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i]; PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
Channel::shared_pointer channel = pvaClientChannel->getChannel(); Channel::shared_pointer channel = pvaClientChannel->getChannel();
@@ -120,6 +132,7 @@ bool PvaClientMultiChannel::connectionChange()
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected() epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
for(size_t i=0; i<numChannel; ++i) { for(size_t i=0; i<numChannel; ++i) {
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i]; PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
if(!pvaClientChannel) { if(!pvaClientChannel) {
@@ -135,11 +148,13 @@ epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::get
PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray() PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
return pvaClientChannelArray; return pvaClientChannelArray;
} }
PvaClientPtr PvaClientMultiChannel::getPvaClient() PvaClientPtr PvaClientMultiChannel::getPvaClient()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
return pvaClient; return pvaClient;
} }
@@ -148,30 +163,35 @@ PvaClientPtr PvaClientMultiChannel::getPvaClient()
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet() PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
{ {
checkConnected(); checkConnected();
return PvaClientMultiGetDouble::create(shared_from_this(),pvaClientChannelArray); return PvaClientMultiGetDouble::create(getPtrSelf(),pvaClientChannelArray);
} }
PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut() PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut()
{ {
checkConnected(); checkConnected();
return PvaClientMultiPutDouble::create(shared_from_this(),pvaClientChannelArray); return PvaClientMultiPutDouble::create(getPtrSelf(),pvaClientChannelArray);
} }
PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor() PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
{ {
checkConnected(); checkConnected();
return PvaClientMultiMonitorDouble::create(shared_from_this(), pvaClientChannelArray); return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray);
} }
PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut() PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut()
{ {
checkConnected(); checkConnected();
return PvaClientNTMultiPut::create(shared_from_this(), pvaClientChannelArray); return PvaClientNTMultiPut::create(getPtrSelf(), pvaClientChannelArray);
} }
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet()
{
return createNTGet("value,alarm,timeStamp");
}
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request) PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request)
{ {
checkConnected(); checkConnected();
@@ -181,7 +201,13 @@ PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &req
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
return PvaClientNTMultiGet::create(shared_from_this(), pvaClientChannelArray,pvRequest); return PvaClientNTMultiGet::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
}
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor()
{
return createNTMonitor("value,alarm,timeStamp");
} }
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request) PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request)
@@ -193,7 +219,7 @@ PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string co
+ createRequest->getMessage(); + createRequest->getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
return PvaClientNTMultiMonitor::create(shared_from_this(), pvaClientChannelArray,pvRequest); return PvaClientNTMultiMonitor::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
} }
@@ -12,21 +12,14 @@
#define PVACLIENTMULTICHANNEL_H #define PVACLIENTMULTICHANNEL_H
#ifdef epicsExportSharedSymbols #ifdef epicsExportSharedSymbols
# define pvaClientMultiChannelEpicsExportSharedSymbols # define pvaClientEpicsExportSharedSymbols
# undef epicsExportSharedSymbols # undef epicsExportSharedSymbols
#endif #endif
#include <pv/pvaClient.h>
#include <pv/ntmultiChannel.h> #include <pv/ntmultiChannel.h>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvaClientMultiChannelEpicsExportSharedSymbols
#endif
#include <pv/pvaClient.h>
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
@@ -62,7 +55,7 @@ class epicsShareClass PvaClientMultiChannel :
{ {
public: public:
POINTER_DEFINITIONS(PvaClientMultiChannel); POINTER_DEFINITIONS(PvaClientMultiChannel);
/** @brief Create a PvaClientMultiChannel. /** Create a PvaClientMultiChannel.
* @param pvaClient The interface to pvaClient. * @param pvaClient The interface to pvaClient.
* @param channelNames The names of the channel.. * @param channelNames The names of the channel..
* @param providerName The name of the provider. * @param providerName The name of the provider.
@@ -76,85 +69,101 @@ public:
size_t maxNotConnected=0 size_t maxNotConnected=0
); );
/** /**
* @brief Destructor * Destructor
*/ */
~PvaClientMultiChannel(); ~PvaClientMultiChannel();
/** @brief Get the channelNames. /** Destroy the pvAccess connections.
*/
void destroy();
/** Get the channelNames.
* @return The names. * @return The names.
*/ */
epics::pvData::shared_vector<const std::string> getChannelNames(); epics::pvData::shared_vector<const std::string> getChannelNames();
/** @brief Connect to the channels. /** Connect to the channels.
*
* This calls issueConnect and waitConnect. * This calls issueConnect and waitConnect.
* An exception is thrown if connect fails. * An exception is thrown if connect fails.
* @param timeout The time to wait for connecting to the channel. * @param timeout The time to wait for connecting to the channel.
* @return status of request * @return status of request
*/ */
epics::pvData::Status connect(double timeout=5); epics::pvData::Status connect(double timeout=5);
/** @brief Are all channels connected? /** Are all channels connected?
* @return if all are connected. * @return if all are connected.
*/ */
bool allConnected(); bool allConnected();
/** @brief Has a connection state change occured? /** Has a connection state change occured?
* @return (true, false) if (at least one, no) channel has changed state. * @return (true, false) if (at least one, no) channel has changed state.
*/ */
bool connectionChange(); bool connectionChange();
/** @brief Get the connection state of each channel. /** Get the connection state of each channel.
* @return The state of each channel. * @return The state of each channel.
*/ */
epics::pvData::shared_vector<epics::pvData::boolean> getIsConnected(); epics::pvData::shared_vector<epics::pvData::boolean> getIsConnected();
/** @brief Get the pvaClientChannelArray. /** Get the pvaClientChannelArray.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientChannelArray getPvaClientChannelArray(); PvaClientChannelArray getPvaClientChannelArray();
/** @brief Get pvaClient. /** Get pvaClient.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientPtr getPvaClient(); PvaClientPtr getPvaClient();
/** /**
* @brief create a pvaClientMultiGetDouble * create a pvaClientMultiGetDouble
* @return The interface. * @return The interface.
*/ */
PvaClientMultiGetDoublePtr createGet(); PvaClientMultiGetDoublePtr createGet();
/** /**
* @brief Create a pvaClientMultiPutDouble. * create a pvaClientMultiPutDouble
* @return The interface. * @return The interface.
*/ */
PvaClientMultiPutDoublePtr createPut(); PvaClientMultiPutDoublePtr createPut();
/** /**
* @brief Create a pvaClientMultiMonitorDouble. * Create a pvaClientMultiMonitorDouble.
* @return The interface. * @return The interface.
*/ */
PvaClientMultiMonitorDoublePtr createMonitor(); PvaClientMultiMonitorDoublePtr createMonitor();
/** /**
* @brief Create a pvaClientNTMultiPut. * Create a pvaClientNTMultiPut.
* @return The interface. * @return The interface.
*/ */
PvaClientNTMultiPutPtr createNTPut(); PvaClientNTMultiPutPtr createNTPut();
/** /**
* @brief Create a pvaClientNTMultiGet; * Create a pvaClientNTMultiGet.
* @param request The request for each channel. * This calls the next method with request = "value,alarm,timeStamp"
* @return The interface. * @return The interface.
*/ */
PvaClientNTMultiGetPtr createNTGet( PvaClientNTMultiGetPtr createNTGet();
std::string const &request = "field(value,alarm,timeStamp)");
/** /**
* @brief Create a pvaClientNTMultiPut. * Create a pvaClientNTMultiGet;
* @param request The request for each channel. * @param request The request for each channel.
* @return The interface. * @return The interface.
*/ */
PvaClientNTMultiMonitorPtr createNTMonitor( PvaClientNTMultiGetPtr createNTGet(std::string const &request);
std::string const &request= "field(value,alarm,timeStamp)"); /**
/** Deprecated method * Create a pvaClientNTMultiMonitor.
* \deprecated This method will go away in future versions. * This calls the next method with request = "value,alarm,timeStamp"
* @return The interface.
*/ */
void destroy() EPICS_DEPRECATED {} PvaClientNTMultiMonitorPtr createNTMonitor();
/**
* Create a pvaClientNTMultiPut.
* @param request The request for each channel.
* @return The interface.
*/
PvaClientNTMultiMonitorPtr createNTMonitor(std::string const &request);
/** Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiChannelPtr getPtrSelf()
{
return shared_from_this();
}
private: private:
PvaClientMultiChannel( PvaClientMultiChannel(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelName, epics::pvData::shared_vector<const std::string> const & channelName,
std::string const & providerName, std::string const & providerName,
size_t maxNotConnected); size_t maxNotConnected);
void checkConnected(); void checkConnected();
PvaClientPtr pvaClient; PvaClientPtr pvaClient;
@@ -169,10 +178,12 @@ private:
PvaClientChannelArray pvaClientChannelArray; PvaClientChannelArray pvaClientChannelArray;
epics::pvData::shared_vector<epics::pvData::boolean> isConnected; epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
epics::pvData::CreateRequest::shared_pointer createRequest; epics::pvData::CreateRequest::shared_pointer createRequest;
bool isDestroyed;
}; };
/** /**
* @brief Provides channelGet to multiple channels where each channel has a numeric scalar value field. * This provides channelGet to multiple channels where each channel has a numeric scalar value field.
*/ */
class epicsShareClass PvaClientMultiGetDouble : class epicsShareClass PvaClientMultiGetDouble :
public std::tr1::enable_shared_from_this<PvaClientMultiGetDouble> public std::tr1::enable_shared_from_this<PvaClientMultiGetDouble>
@@ -182,7 +193,7 @@ public:
POINTER_DEFINITIONS(PvaClientMultiGetDouble); POINTER_DEFINITIONS(PvaClientMultiGetDouble);
/** /**
* @brief Create a PvaClientMultiGetDouble. * Factory method that creates a PvaClientMultiGetDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array. * @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface. * @return The interface.
@@ -193,26 +204,25 @@ public:
~PvaClientMultiGetDouble(); ~PvaClientMultiGetDouble();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Create a channelGet for each channel. * Create a channelGet for each channel.
*/ */
void connect(); void connect();
/** /**
* @brief Get the data. * get the data.
* @return The double[] where each element is the value field of the corresponding channel. * @return The double[] where each element is the value field of the corresponding channel.
*/ */
epics::pvData::shared_vector<double> get(); epics::pvData::shared_vector<double> get();
/** @brief Get the shared pointer to self. /** Get the shared pointer to self.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientMultiGetDoublePtr getPtrSelf() PvaClientMultiGetDoublePtr getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiGetDouble( PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -226,10 +236,11 @@ private:
epics::pvData::shared_vector<double> doubleValue; epics::pvData::shared_vector<double> doubleValue;
std::vector<PvaClientGetPtr> pvaClientGet; std::vector<PvaClientGetPtr> pvaClientGet;
bool isGetConnected; bool isGetConnected;
bool isDestroyed;
}; };
/** /**
* @brief Provides channelPut to multiple channels where each channel has a numeric scalar value field. * This provides channelPut to multiple channels where each channel has a numeric scalar value field.
*/ */
class epicsShareClass PvaClientMultiPutDouble : class epicsShareClass PvaClientMultiPutDouble :
public std::tr1::enable_shared_from_this<PvaClientMultiPutDouble> public std::tr1::enable_shared_from_this<PvaClientMultiPutDouble>
@@ -238,34 +249,35 @@ class epicsShareClass PvaClientMultiPutDouble :
public: public:
POINTER_DEFINITIONS(PvaClientMultiPutDouble); POINTER_DEFINITIONS(PvaClientMultiPutDouble);
/** @brief Create a PvaClientMultiPutDouble. /**
* Factory method that creates a PvaClientMultiPutDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array. * @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface. * @return The interface.
*/ */
static PvaClientMultiPutDoublePtr create( static PvaClientMultiPutDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientMultiPutDouble(); ~PvaClientMultiPutDouble();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Create a channelPut for each channel. * Create a channelPut for each channel.
*/ */
void connect(); void connect();
/** @brief put data to each channel as a double /** put data to each channel as a double
* @param data The array of data for each channel. * @param data The array of data for each channel.
*/ */
void put(epics::pvData::shared_vector<double> const &data); void put(epics::pvData::shared_vector<double> const &data);
/** @brief Get the shared pointer to self. /** Get the shared pointer to self.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientMultiPutDoublePtr getPtrSelf() PvaClientMultiPutDoublePtr getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiPutDouble( PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -278,10 +290,11 @@ private:
std::vector<PvaClientPutPtr> pvaClientPut; std::vector<PvaClientPutPtr> pvaClientPut;
bool isPutConnected; bool isPutConnected;
bool isDestroyed;
}; };
/** /**
* @brief Provides a monitor to multiple channels where each channel has a numeric scalar value field. * This provides a monitor to multiple channels where each channel has a numeric scalar value field.
*/ */
class epicsShareClass PvaClientMultiMonitorDouble : class epicsShareClass PvaClientMultiMonitorDouble :
public std::tr1::enable_shared_from_this<PvaClientMultiMonitorDouble> public std::tr1::enable_shared_from_this<PvaClientMultiMonitorDouble>
@@ -290,49 +303,49 @@ class epicsShareClass PvaClientMultiMonitorDouble :
public: public:
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble); POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
/** @brief Create a PvaClientMultiMonitorDouble. /**
* Factory method that creates a PvaClientMultiMonitorDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array. * @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface. * @return The interface.
*/ */
static PvaClientMultiMonitorDoublePtr create( static PvaClientMultiMonitorDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientMultiMonitorDouble(); ~PvaClientMultiMonitorDouble();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Connect a channel monitor for each channel. * Create a channel monitor for each channel.
*/ */
void connect(); void connect();
/** /**
* @brief Poll each channel. * poll each channel.
*
* If any has new data it is used to update the double[]. * If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated. * @return (false,true) if (no, at least one) value was updated.
*/ */
bool poll(); bool poll();
/** /**
* @brief Wait until poll returns true. * Wait until poll returns true.
* @param secondsToWait The time to keep trying. * @param waitForEvent The time to keep trying.
* A thread sleep of .1 seconds occurs between each call to poll. * A thread sleep of .1 seconds occurs between each call to poll.
* @return (false,true) if (timeOut, poll returned true). * @return (false,true) if (timeOut, poll returned true).
*/ */
bool waitEvent(double secondsToWait); bool waitEvent(double waitForEvent);
/** /**
* get the data. * get the data.
* @return The double[] where each element is the value field of the corresponding channel. * @return The double[] where each element is the value field of the corresponding channel.
*/ */
epics::pvData::shared_vector<double> get(); epics::pvData::shared_vector<double> get();
/** @brief Monitor the shared pointer to self. /** Monitor the shared pointer to self.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientMultiMonitorDoublePtr getPtrSelf() PvaClientMultiMonitorDoublePtr getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiMonitorDouble( PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -346,10 +359,11 @@ private:
epics::pvData::shared_vector<double> doubleValue; epics::pvData::shared_vector<double> doubleValue;
std::vector<PvaClientMonitorPtr> pvaClientMonitor; std::vector<PvaClientMonitorPtr> pvaClientMonitor;
bool isMonitorConnected; bool isMonitorConnected;
bool isDestroyed;
}; };
/** /**
* @brief Provides channelGet to multiple channels where the value field of each channel is presented as a union. * This provides channelGet to multiple channels where the value field of each channel is presented as a union.
*/ */
class epicsShareClass PvaClientNTMultiGet : class epicsShareClass PvaClientNTMultiGet :
public std::tr1::enable_shared_from_this<PvaClientNTMultiGet> public std::tr1::enable_shared_from_this<PvaClientNTMultiGet>
@@ -358,7 +372,7 @@ class epicsShareClass PvaClientNTMultiGet :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiGet); POINTER_DEFINITIONS(PvaClientNTMultiGet);
/** /**
* @brief Create a PvaClientNTMultiGet. * Factory method that creates a PvaClientNTMultiGet.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array. * @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel. * @param pvRequest The pvRequest for each channel.
@@ -370,30 +384,30 @@ public:
epics::pvData::PVStructurePtr const & pvRequest); epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiGet(); ~PvaClientNTMultiGet();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Connect a channelGet for each channel. * Create a channelGet for each channel.
*/ */
void connect(); void connect();
/** /**
* @brief Get each channel. * get data for each channel.
*/ */
void get(); void get();
/** /**
* @brief Get the data from the last get. * get the data.
* @return the pvaClientNTMultiData. * @return the pvaClientNTMultiData.
*/ */
PvaClientNTMultiDataPtr getData(); PvaClientNTMultiDataPtr getData();
/** @brief Get the shared pointer to self. /** Get the shared pointer to self.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientNTMultiGetPtr getPtrSelf() PvaClientNTMultiGetPtr getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiGet( PvaClientNTMultiGet(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -411,10 +425,11 @@ private:
PvaClientNTMultiDataPtr pvaClientNTMultiData; PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientGetPtr> pvaClientGet; std::vector<PvaClientGetPtr> pvaClientGet;
bool isConnected; bool isConnected;
bool isDestroyed;
}; };
/** /**
* @brief Provides channelPut to multiple channels where the value field of each channel is presented as a union. * This provides channelPut to multiple channels where the value field of each channel is presented as a union.
*/ */
class epicsShareClass PvaClientNTMultiPut : class epicsShareClass PvaClientNTMultiPut :
public std::tr1::enable_shared_from_this<PvaClientNTMultiPut> public std::tr1::enable_shared_from_this<PvaClientNTMultiPut>
@@ -423,7 +438,7 @@ class epicsShareClass PvaClientNTMultiPut :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiPut); POINTER_DEFINITIONS(PvaClientNTMultiPut);
/** /**
* @brief Create a PvaClientNTMultiPut. * Factory method that creates a PvaClientNTMultiPut.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array. * @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface. * @return The interface.
@@ -431,32 +446,31 @@ public:
static PvaClientNTMultiPutPtr create( static PvaClientNTMultiPutPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientNTMultiPut(); ~PvaClientNTMultiPut();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Connect a channelPut for each channel. * Create a channelPut for each channel.
*/ */
void connect(); void connect();
/** /**
* @brief Get the value field of each channel as a union. * get the value field of each channel as a union.
* @return A shared vector of union. * @return A shared vector of union.
*/ */
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues(); epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
/** /**
* @brief Issue a put for each channel. * put the data to each channel.
' */ ' */
void put(); void put();
/** @brief Get the shared pointer to self. /** Get the shared pointer to self.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientNTMultiPutPtr getPtrSelf() PvaClientNTMultiPutPtr getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiPut( PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -471,10 +485,11 @@ private:
epics::pvData::shared_vector<epics::pvData::PVFieldPtr> value; epics::pvData::shared_vector<epics::pvData::PVFieldPtr> value;
std::vector<PvaClientPutPtr> pvaClientPut; std::vector<PvaClientPutPtr> pvaClientPut;
bool isConnected; bool isConnected;
bool isDestroyed;
}; };
/** /**
* @brief Provides channel monitor to multiple channels where the value field of each channel is presented as a union. * This provides channel monitor to multiple channels where the value field of each channel is presented as a union.
*/ */
class epicsShareClass PvaClientNTMultiMonitor : class epicsShareClass PvaClientNTMultiMonitor :
public std::tr1::enable_shared_from_this<PvaClientNTMultiMonitor> public std::tr1::enable_shared_from_this<PvaClientNTMultiMonitor>
@@ -482,37 +497,41 @@ class epicsShareClass PvaClientNTMultiMonitor :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiMonitor); POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
/** @brief Create a PvaClientNTMultiMonitor. /**
* Factory method that creates a PvaClientNTMultiMonitor.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array. * @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel. * @param pvRequest The pvRequest for each channel.
* @return The interface. * @return The interface.
*/ */
static PvaClientNTMultiMonitorPtr create( static PvaClientNTMultiMonitorPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaNTMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest); epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiMonitor(); ~PvaClientNTMultiMonitor();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Connect to a channel monitor for each channel. * Create a channel monitor for each channel.
*/ */
void connect(); void connect();
/** /**
* @brief Poll each channel. * poll each channel.
*
* If any has new data it is used to update the double[]. * If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated. * @return (false,true) if (no, at least one) value was updated.
*/ */
bool poll(); bool poll();
/** /**
* @brief Wait until poll returns true. * Wait until poll returns true.
* @param secondsToWait The time to keep trying. * @param waitForEvent The time to keep trying.
* A thread sleep of .1 seconds occurs between each call to poll. * A thread sleep of .1 seconds occurs between each call to poll.
* @return (false,true) if (timeOut, poll returned true). * @return (false,true) if (timeOut, poll returned true).
*/ */
bool waitEvent(double secondsToWait); bool waitEvent(double waitForEvent);
/** /**
* @brief Get the data for the last successfull poll. * get the data.
* @return the pvaClientNTMultiData. * @return the pvaClientNTMultiData.
*/ */
PvaClientNTMultiDataPtr getData(); PvaClientNTMultiDataPtr getData();
@@ -523,10 +542,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiMonitor( PvaClientNTMultiMonitor(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -542,10 +557,11 @@ private:
PvaClientNTMultiDataPtr pvaClientNTMultiData; PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientMonitorPtr> pvaClientMonitor; std::vector<PvaClientMonitorPtr> pvaClientMonitor;
bool isConnected; bool isConnected;
bool isDestroyed;
}; };
/** /**
* @brief Provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor. * This provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
*/ */
class epicsShareClass PvaClientNTMultiData : class epicsShareClass PvaClientNTMultiData :
public std::tr1::enable_shared_from_this<PvaClientNTMultiData> public std::tr1::enable_shared_from_this<PvaClientNTMultiData>
@@ -554,8 +570,7 @@ class epicsShareClass PvaClientNTMultiData :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiData); POINTER_DEFINITIONS(PvaClientNTMultiData);
/** /**
* @brief Create a PvaClientNTMultiData. * Factory method that creates a PvaClientNTMultiData.
*
* Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor. * Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor.
* @param u The union interface for the value field of each channel. * @param u The union interface for the value field of each channel.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel. * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
@@ -564,47 +579,47 @@ public:
*/ */
static PvaClientNTMultiDataPtr create( static PvaClientNTMultiDataPtr create(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaNTMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest); epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiData(); ~PvaClientNTMultiData();
/** Destroy the pvAccess connection.
*/
void destroy();
/** /**
* @brief Get the number of channels. * Get the number of channels.
* @return The number of channels. * @return The number of channels.
*/ */
size_t getNumber(); size_t getNumber();
/** /**
* @brief Set the timeStamp base for computing deltaTimes. * Set the timeStamp base for computing deltaTimes.
*/ */
void startDeltaTime(); void startDeltaTime();
/** /**
* @brief Update NTMultiChannel fields. * Update NTMultiChannel fields.
*/ */
void endDeltaTime(); void endDeltaTime();
/** /**
* @brief Get the time when the last get was made. * Get the time when the last get was made.
* @return The timeStamp. * @return The timeStamp.
*/ */
epics::pvData::TimeStamp getTimeStamp(); epics::pvData::TimeStamp getTimeStamp();
/** /**
* @brief Get the NTMultiChannel. * Get the NTMultiChannel.
* @return The value. * @return The value.
*/ */
epics::nt::NTMultiChannelPtr getNTMultiChannel(); epics::nt::NTMultiChannelPtr getNTMultiChannel();
/** @brief Get the shared pointer to self. /** Get the shared pointer to self.
* @return The shared pointer. * @return The shared pointer.
*/ */
PvaClientNTMultiDataPtr getPtrSelf() PvaClientNTMultiDataPtr getPtrSelf()
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiData( PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -623,6 +638,7 @@ private:
std::vector<epics::pvData::PVStructurePtr> topPVStructure; std::vector<epics::pvData::PVStructurePtr> topPVStructure;
bool gotAlarm; bool gotAlarm;
bool gotTimeStamp; bool gotTimeStamp;
bool isDestroyed;
epics::pvData::StructureConstPtr ntMultiChannelStructure; epics::pvData::StructureConstPtr ntMultiChannelStructure;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue; epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
@@ -645,3 +661,9 @@ private:
#endif /* PVACLIENTMULTICHANNEL_H */ #endif /* PVACLIENTMULTICHANNEL_H */
/** @page Overview Documentation
*
* <a href = "../pvaClientOverview.html">pvaClientOverview.html</a>
*
*/
+22 -8
View File
@@ -9,13 +9,12 @@
* @date 2015.03 * @date 2015.03
*/ */
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
#include <pv/standardField.h>
#include <pv/convert.h> #include <pv/convert.h>
#include <epicsMath.h> #include <epicsMath.h>
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
using namespace epics::pvAccess; using namespace epics::pvAccess;
@@ -24,6 +23,11 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create( PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
@@ -42,14 +46,24 @@ PvaClientMultiGetDouble::PvaClientMultiGetDouble(
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
doubleValue(shared_vector<double>(nchannel)), doubleValue(shared_vector<double>(nchannel)),
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())), pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
isGetConnected(false) isGetConnected(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiGetDouble::PvaClientMultiGetDouble()\n";
} }
PvaClientMultiGetDouble::~PvaClientMultiGetDouble() PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiGetDouble::~PvaClientMultiGetDouble()\n"; destroy();
}
void PvaClientMultiGetDouble::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
} }
void PvaClientMultiGetDouble::connect() void PvaClientMultiGetDouble::connect()
@@ -103,7 +117,7 @@ epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
if(isConnected[i]) if(isConnected[i])
{ {
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure(); PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
doubleValue[i] = getConvert()->toDouble(pvStructure->getSubField<PVScalar>("value")); doubleValue[i] = convert->toDouble(pvStructure->getSubField<PVScalar>("value"));
} else { } else {
doubleValue[i] = epicsNAN; doubleValue[i] = epicsNAN;
} }
+23 -8
View File
@@ -9,12 +9,12 @@
* @date 2015.03 * @date 2015.03
*/ */
#include <epicsThread.h>
#include <epicsMath.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <epicsThread.h>
#include <pv/pvaClientMultiChannel.h> #include <pv/pvaClientMultiChannel.h>
#include <pv/standardField.h>
#include <pv/convert.h>
#include <epicsMath.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
@@ -24,6 +24,11 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create( PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
@@ -42,14 +47,24 @@ PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble(
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
doubleValue(shared_vector<double>(nchannel,epicsNAN)), doubleValue(shared_vector<double>(nchannel,epicsNAN)),
pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())), pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())),
isMonitorConnected(false) isMonitorConnected(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble()\n";
} }
PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble() PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()\n"; destroy();
}
void PvaClientMultiMonitorDouble::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
} }
void PvaClientMultiMonitorDouble::connect() void PvaClientMultiMonitorDouble::connect()
@@ -84,7 +99,7 @@ bool PvaClientMultiMonitorDouble::poll()
{ {
if(!isMonitorConnected){ if(!isMonitorConnected){
connect(); connect();
epicsThreadSleep(.1); epicsThreadSleep(.01);
} }
bool result = false; bool result = false;
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
+22 -8
View File
@@ -9,13 +9,12 @@
* @date 2015.03 * @date 2015.03
*/ */
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
#include <pv/standardField.h>
#include <pv/convert.h> #include <pv/convert.h>
#include <epicsMath.h> #include <epicsMath.h>
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
using namespace epics::pvAccess; using namespace epics::pvAccess;
@@ -24,6 +23,12 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();
static CreateRequest::shared_pointer createRequest = CreateRequest::create();
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create( PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
@@ -41,18 +46,27 @@ PvaClientMultiPutDouble::PvaClientMultiPutDouble(
pvaClientChannelArray(pvaClientChannelArray), pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())), pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())),
isPutConnected(false) isPutConnected(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiPutDouble::PvaClientMultiPutDouble()\n";
} }
PvaClientMultiPutDouble::~PvaClientMultiPutDouble() PvaClientMultiPutDouble::~PvaClientMultiPutDouble()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMultiPutDouble::~PvaClientMultiPutDouble()\n"; destroy();
} }
void PvaClientMultiPutDouble::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
}
void PvaClientMultiPutDouble::connect() void PvaClientMultiPutDouble::connect()
{ {
@@ -89,7 +103,7 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
if(isConnected[i]) { if(isConnected[i]) {
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure(); PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value"); PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
getConvert()->fromDouble(pvValue,data[i]); convert->fromDouble(pvValue,data[i]);
pvaClientPut[i]->issuePut(); pvaClientPut[i]->issuePut();
} }
if(isConnected[i]) { if(isConnected[i]) {
+33 -23
View File
@@ -9,11 +9,9 @@
* @date 2015.03 * @date 2015.03
*/ */
#include <epicsMath.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h> #include <pv/pvaClientMultiChannel.h>
#include <epicsMath.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
@@ -23,6 +21,9 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
PvaClientNTMultiDataPtr PvaClientNTMultiData::create( PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
@@ -42,16 +43,15 @@ PvaClientNTMultiData::PvaClientNTMultiData(
pvaClientChannelArray(pvaClientChannelArray), pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
gotAlarm(false), gotAlarm(false),
gotTimeStamp(false) gotTimeStamp(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
PVFieldPtr pvValue = pvRequest->getSubField("field.value"); PVFieldPtr pvValue = pvRequest->getSubField("field.value");
if(!pvValue) { if(!pvValue) {
throw std::runtime_error("pvRequest did not specify value"); throw std::runtime_error("pvRequest did not specify value");
} }
topPVStructure.resize(nchannel); topPVStructure.resize(nchannel);
unionValue.resize(nchannel); unionValue.resize(nchannel);
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i=0; i< nchannel; ++i) { for(size_t i=0; i< nchannel; ++i) {
topPVStructure[i] = PVStructurePtr(); topPVStructure[i] = PVStructurePtr();
unionValue[i] = pvDataCreate->createPVUnion(u); unionValue[i] = pvDataCreate->createPVUnion(u);
@@ -86,9 +86,18 @@ PvaClientNTMultiData::PvaClientNTMultiData(
PvaClientNTMultiData::~PvaClientNTMultiData() PvaClientNTMultiData::~PvaClientNTMultiData()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n"; destroy();
} }
void PvaClientNTMultiData::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
}
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index) void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
{ {
@@ -144,22 +153,23 @@ void PvaClientNTMultiData::endDeltaTime()
{ {
PVStructurePtr pvst = topPVStructure[i]; PVStructurePtr pvst = topPVStructure[i];
if(!pvst) { if(!pvst) {
unionValue[i] = PVUnionPtr(); unionValue[i] = PVUnionPtr();
} else { } else {
unionValue[i]->set(pvst->getSubField("value")); unionValue[i]->set(pvst->getSubField("value"));
if(gotAlarm) }
{ if(gotAlarm)
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get(); {
status[i] = pvst->getSubField<PVInt>("alarm.status")->get(); severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
message[i] = pvst->getSubField<PVString>("alarm.message")->get(); status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
} message[i] = pvst->getSubField<PVString>("alarm.message")->get();
if(gotTimeStamp) }
{ if(gotTimeStamp)
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get(); {
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get(); secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get(); nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
} userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
} }
} }
} }
@@ -171,7 +181,7 @@ TimeStamp PvaClientNTMultiData::getTimeStamp()
NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel() NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
{ {
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(ntMultiChannelStructure);
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure); NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames()); ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
shared_vector<epics::pvData::PVUnionPtr> val(nchannel); shared_vector<epics::pvData::PVUnionPtr> val(nchannel);
+22 -7
View File
@@ -9,11 +9,11 @@
* @date 2015.03 * @date 2015.03
*/ */
#include <epicsMath.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h> #include <pv/pvaClientMultiChannel.h>
#include <pv/standardField.h>
#include <pv/convert.h>
#include <epicsMath.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
@@ -23,13 +23,18 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create( PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
PVStructurePtr const & pvRequest) PVStructurePtr const & pvRequest)
{ {
UnionConstPtr u = getFieldCreate()->createVariantUnion(); UnionConstPtr u = fieldCreate->createVariantUnion();
PvaClientNTMultiGetPtr pvaClientNTMultiGet( PvaClientNTMultiGetPtr pvaClientNTMultiGet(
new PvaClientNTMultiGet(u,pvaMultiChannel,pvaClientChannelArray,pvRequest)); new PvaClientNTMultiGet(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
return pvaClientNTMultiGet; return pvaClientNTMultiGet;
@@ -50,14 +55,24 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
pvaClientMultiChannel, pvaClientMultiChannel,
pvaClientChannelArray, pvaClientChannelArray,
pvRequest)), pvRequest)),
isConnected(false) isConnected(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiGet::PvaClientNTMultiGet()\n";
} }
PvaClientNTMultiGet::~PvaClientNTMultiGet() PvaClientNTMultiGet::~PvaClientNTMultiGet()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiGet::~PvaClientNTMultiGet()\n"; destroy();
}
void PvaClientNTMultiGet::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
} }
void PvaClientNTMultiGet::connect() void PvaClientNTMultiGet::connect()
+18 -8
View File
@@ -9,15 +9,13 @@
* @date 2015.03 * @date 2015.03
*/ */
#define epicsExportSharedSymbols
#include <epicsThread.h> #include <epicsThread.h>
#include <pv/pvaClientMultiChannel.h>
#include <pv/standardField.h> #include <pv/standardField.h>
#include <pv/convert.h> #include <pv/convert.h>
#include <epicsMath.h> #include <epicsMath.h>
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
using namespace epics::pvAccess; using namespace epics::pvAccess;
@@ -26,12 +24,14 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static FieldCreatePtr fieldCreate = getFieldCreate();
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create( PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest) epics::pvData::PVStructurePtr const & pvRequest)
{ {
UnionConstPtr u = getFieldCreate()->createVariantUnion(); UnionConstPtr u = fieldCreate->createVariantUnion();
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor( PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
new PvaClientNTMultiMonitor(u,pvaMultiChannel,pvaClientChannelArray,pvRequest)); new PvaClientNTMultiMonitor(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
return pvaClientNTMultiMonitor; return pvaClientNTMultiMonitor;
@@ -52,15 +52,25 @@ PvaClientNTMultiMonitor::PvaClientNTMultiMonitor(
pvaClientMultiChannel, pvaClientMultiChannel,
pvaClientChannelArray, pvaClientChannelArray,
pvRequest)), pvRequest)),
isConnected(false) isConnected(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiMonitor::PvaClientNTMultiMonitor()\n";
} }
PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor() PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()\n"; destroy();
}
void PvaClientNTMultiMonitor::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
} }
+19 -9
View File
@@ -9,14 +9,12 @@
* @date 2015.03 * @date 2015.03
*/ */
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
#include <pv/standardField.h> #include <pv/standardField.h>
#include <pv/convert.h> #include <pv/convert.h>
#include <epicsMath.h> #include <epicsMath.h>
#define epicsExportSharedSymbols
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
using namespace epics::pvAccess; using namespace epics::pvAccess;
@@ -25,6 +23,10 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create( PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray) PvaClientChannelArray const &pvaClientChannelArray)
@@ -41,15 +43,25 @@ PvaClientNTMultiPut::PvaClientNTMultiPut(
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())), unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())), value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())),
isConnected(false) isConnected(false),
isDestroyed(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n";
} }
PvaClientNTMultiPut::~PvaClientNTMultiPut() PvaClientNTMultiPut::~PvaClientNTMultiPut()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::~PvaClientNTMultiPut()\n"; destroy();
}
void PvaClientNTMultiPut::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
pvaClientChannelArray.clear();
} }
void PvaClientNTMultiPut::connect() void PvaClientNTMultiPut::connect()
@@ -89,8 +101,6 @@ void PvaClientNTMultiPut::connect()
throw std::runtime_error(message); throw std::runtime_error(message);
} }
} }
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
+50 -68
View File
@@ -8,11 +8,9 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#include <pv/event.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/event.h>
#include <pv/pvaClient.h> #include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
@@ -22,64 +20,27 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
class ChannelProcessRequesterImpl : public ChannelProcessRequester class ChannelProcessRequesterImpl : public ChannelProcessRequester
{ {
PvaClientProcess::weak_pointer pvaClientProcess; PvaClientProcess * pvaClientProcess;
PvaClient::weak_pointer pvaClient;
public: public:
ChannelProcessRequesterImpl( ChannelProcessRequesterImpl(PvaClientProcess * pvaClientProcess)
PvaClientProcessPtr const & pvaClientProcess, : pvaClientProcess(pvaClientProcess) {}
PvaClientPtr const &pvaClient) string getRequesterName()
: pvaClientProcess(pvaClientProcess), {return pvaClientProcess->getRequesterName();}
pvaClient(pvaClient) void message(string const & message,MessageType messageType)
{} {pvaClientProcess->message(message,messageType);}
virtual ~ChannelProcessRequesterImpl() { void channelProcessConnect(
if(PvaClient::getDebug()) std::cout << "~ChannelProcessRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return string("clientProcess is null");
return clientProcess->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return;
clientProcess->message(message,messageType);
}
virtual void channelProcessConnect(
const Status& status, const Status& status,
ChannelProcess::shared_pointer const & channelProcess) ChannelProcess::shared_pointer const & channelProcess)
{ {pvaClientProcess->channelProcessConnect(status,channelProcess);}
PvaClientProcessPtr clientProcess(pvaClientProcess.lock()); void processDone(
if(!clientProcess) return;
clientProcess->channelProcessConnect(status,channelProcess);
}
virtual void processDone(
const Status& status, const Status& status,
ChannelProcess::shared_pointer const & ChannelProcess) ChannelProcess::shared_pointer const & channelProcess)
{ {pvaClientProcess->processDone(status,channelProcess);}
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return;
clientProcess->processDone(status,ChannelProcess);
}
}; };
PvaClientProcessPtr PvaClientProcess::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientProcessPtr epv(new PvaClientProcess(pvaClient,channel,pvRequest));
epv->channelProcessRequester = ChannelProcessRequesterImplPtr(
new ChannelProcessRequesterImpl(epv,pvaClient));
return epv;
}
PvaClientProcess::PvaClientProcess( PvaClientProcess::PvaClientProcess(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, Channel::shared_pointer const & channel,
@@ -87,16 +48,15 @@ PvaClientProcess::PvaClientProcess(
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), channel(channel),
pvRequest(pvRequest), pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle), connectState(connectIdle),
processState(processIdle) processState(processIdle)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientProcess::PvaClientProcess()\n";
} }
PvaClientProcess::~PvaClientProcess() PvaClientProcess::~PvaClientProcess()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientProcess::~PvaClientProcess()\n"; destroy();
channelProcess->destroy();
} }
// from ChannelProcessRequester // from ChannelProcessRequester
@@ -109,6 +69,7 @@ string PvaClientProcess::getRequesterName()
void PvaClientProcess::message(string const & message,MessageType messageType) void PvaClientProcess::message(string const & message,MessageType messageType)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("pvaClient was destroyed"); if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType); yyy->message(message, messageType);
@@ -118,8 +79,8 @@ void PvaClientProcess::channelProcessConnect(
const Status& status, const Status& status,
ChannelProcess::shared_pointer const & channelProcess) ChannelProcess::shared_pointer const & channelProcess)
{ {
if(isDestroyed) return;
channelProcessConnectStatus = status; channelProcessConnectStatus = status;
connectState = connected;
this->channelProcess = channelProcess; this->channelProcess = channelProcess;
waitForConnect.signal(); waitForConnect.signal();
@@ -129,13 +90,27 @@ void PvaClientProcess::processDone(
const Status& status, const Status& status,
ChannelProcess::shared_pointer const & channelProcess) ChannelProcess::shared_pointer const & channelProcess)
{ {
if(isDestroyed) return;
channelProcessStatus = status; channelProcessStatus = status;
processState = processComplete;
waitForProcess.signal(); waitForProcess.signal();
} }
// from PvaClientProcess
void PvaClientProcess::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelProcess) channelProcess->destroy();
channelProcess.reset();
}
void PvaClientProcess::connect() void PvaClientProcess::connect()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
@@ -146,33 +121,33 @@ void PvaClientProcess::connect()
void PvaClientProcess::issueConnect() void PvaClientProcess::issueConnect()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + channel->getChannelName()
+ " pvaClientProcess already connected "; + " pvaClientProcess already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
processRequester = ChannelProcessRequester::shared_pointer(new ChannelProcessRequesterImpl(this));
connectState = connectActive; connectState = connectActive;
channelProcess = channel->createChannelProcess(channelProcessRequester,pvRequest); channelProcess = channel->createChannelProcess(processRequester,pvRequest);
} }
Status PvaClientProcess::waitConnect() Status PvaClientProcess::waitConnect()
{ {
if(connectState==connected) { if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus;
}
if(connectState!=connectActive) { if(connectState!=connectActive) {
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + channel->getChannelName()
+ " pvaClientProcess illegal connect state "; + " pvaClientProcess illegal connect state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForConnect.wait(); waitForConnect.wait();
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle; connectState = channelProcessConnectStatus.isOK() ? connected : connectIdle;
return channelProcessConnectStatus; return channelProcessConnectStatus;
} }
void PvaClientProcess::process() void PvaClientProcess::process()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
issueProcess(); issueProcess();
Status status = waitProcess(); Status status = waitProcess();
if(status.isOK()) return; if(status.isOK()) return;
@@ -183,6 +158,7 @@ void PvaClientProcess::process()
void PvaClientProcess::issueProcess() void PvaClientProcess::issueProcess()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(processState!=processIdle) { if(processState!=processIdle) {
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + channel->getChannelName()
@@ -195,10 +171,7 @@ void PvaClientProcess::issueProcess()
Status PvaClientProcess::waitProcess() Status PvaClientProcess::waitProcess()
{ {
if(processState==processComplete) { if(isDestroyed) throw std::runtime_error("pvaClientProcess was destroyed");
processState = processIdle;
return channelProcessStatus;
}
if(processState!=processActive){ if(processState!=processActive){
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + channel->getChannelName()
+ " PvaClientProcess::waitProcess llegal process state"; + " PvaClientProcess::waitProcess llegal process state";
@@ -209,4 +182,13 @@ Status PvaClientProcess::waitProcess()
return channelProcessStatus; return channelProcessStatus;
} }
PvaClientProcessPtr PvaClientProcess::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientProcessPtr epv(new PvaClientProcess(pvaClient,channel,pvRequest));
return epv;
}
}} }}
+85 -182
View File
@@ -8,11 +8,9 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#include <pv/event.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/event.h>
#include <pv/pvaClient.h> #include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
@@ -24,75 +22,31 @@ namespace epics { namespace pvaClient {
class ChannelPutRequesterImpl : public ChannelPutRequester class ChannelPutRequesterImpl : public ChannelPutRequester
{ {
PvaClientPut::weak_pointer pvaClientPut; PvaClientPut * pvaClientPut;
PvaClient::weak_pointer pvaClient;
public: public:
ChannelPutRequesterImpl( ChannelPutRequesterImpl(PvaClientPut * pvaClientPut)
PvaClientPutPtr const & pvaClientPut, : pvaClientPut(pvaClientPut) {}
PvaClientPtr const &pvaClient) string getRequesterName()
: pvaClientPut(pvaClientPut), {return pvaClientPut->getRequesterName();}
pvaClient(pvaClient) void message(string const & message,MessageType messageType)
{} {pvaClientPut->message(message,messageType);}
virtual ~ChannelPutRequesterImpl() { void channelPutConnect(
if(PvaClient::getDebug()) std::cout << "~ChannelPutRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return string("clientPut is null");
return clientPut->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return;
clientPut->message(message,messageType);
}
virtual void channelPutConnect(
const Status& status, const Status& status,
ChannelPut::shared_pointer const & channelPut, ChannelPut::shared_pointer const & channelPut,
Structure::const_shared_pointer const & structure) StructureConstPtr const & structure)
{ {pvaClientPut->channelPutConnect(status,channelPut,structure);}
PvaClientPutPtr clientPut(pvaClientPut.lock()); void getDone(
if(!clientPut) return;
clientPut->channelPutConnect(status,channelPut,structure);
}
virtual void getDone(
const Status& status, const Status& status,
ChannelPut::shared_pointer const & channelPut, ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const & pvStructure, PVStructurePtr const & pvStructure,
BitSet::shared_pointer const & bitSet) BitSetPtr const & bitSet)
{ {pvaClientPut->getDone(status,channelPut,pvStructure,bitSet);}
PvaClientPutPtr clientPut(pvaClientPut.lock()); void putDone(
if(!clientPut) return;
clientPut->getDone(status,channelPut,pvStructure,bitSet);
}
virtual void putDone(
const Status& status, const Status& status,
ChannelPut::shared_pointer const & channelPut) ChannelPut::shared_pointer const & channelPut)
{ {pvaClientPut->putDone(status,channelPut);}
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return;
clientPut->putDone(status,channelPut);
}
}; };
PvaClientPutPtr PvaClientPut::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientPutPtr epv(new PvaClientPut(pvaClient,channel,pvRequest));
epv->channelPutRequester = ChannelPutRequesterImplPtr(
new ChannelPutRequesterImpl(epv,pvaClient));
return epv;
}
PvaClientPut::PvaClientPut( PvaClientPut::PvaClientPut(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, Channel::shared_pointer const & channel,
@@ -100,48 +54,39 @@ PvaClientPut::PvaClientPut(
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), channel(channel),
pvRequest(pvRequest), pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle), connectState(connectIdle),
putState(putIdle) putState(putIdle)
{ {
if(PvaClient::getDebug()) {
cout<< "PvaClientPut::PvaClientPut"
<< " channelName " << channel->getChannelName()
<< endl;
}
} }
PvaClientPut::~PvaClientPut() PvaClientPut::~PvaClientPut()
{ {
if(PvaClient::getDebug()) { destroy();
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientPut::~PvaClientPut"
<< " channelName " << channelName
<< endl;
}
if(channelPut) channelPut->destroy();
} }
void PvaClientPut::checkPutState() void PvaClientPut::checkPutState()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
if(connectState==connectIdle){ if(connectState==connectIdle){
connect(); connect();
get(); get();
} }
} }
// from ChannelPutRequester
string PvaClientPut::getRequesterName() string PvaClientPut::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientPut::getRequesterName() PvaClient isDestroyed"); if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName(); return yyy->getRequesterName();
} }
void PvaClientPut::message(string const & message,MessageType messageType) void PvaClientPut::message(string const & message,MessageType messageType)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return; if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType); yyy->message(message, messageType);
} }
@@ -150,23 +95,12 @@ void PvaClientPut::channelPutConnect(
ChannelPut::shared_pointer const & channelPut, ChannelPut::shared_pointer const & channelPut,
StructureConstPtr const & structure) StructureConstPtr const & structure)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
string channelName("disconnected"); channelPutConnectStatus = status;
Channel::shared_pointer chan(channel.lock()); this->channelPut = channelPut;
if(chan) channelName = chan->getChannelName(); if(status.isOK()) {
cout << "PvaClientPut::channelPutConnect" pvaClientData = PvaClientPutData::create(structure);
<< " channelName " << channelName pvaClientData->setMessagePrefix(channel->getChannelName());
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelPutConnectStatus = status;
this->channelPut = channelPut;
if(status.isOK()) {
pvaClientData = PvaClientPutData::create(structure);
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
}
} }
waitForConnect.signal(); waitForConnect.signal();
@@ -178,15 +112,7 @@ void PvaClientPut::getDone(
PVStructurePtr const & pvStructure, PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet) BitSetPtr const & bitSet)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::getDone"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelGetPutStatus = status; channelGetPutStatus = status;
if(status.isOK()) { if(status.isOK()) {
PVStructurePtr pvs = pvaClientData->getPVStructure(); PVStructurePtr pvs = pvaClientData->getPVStructure();
@@ -202,114 +128,92 @@ void PvaClientPut::putDone(
const Status& status, const Status& status,
ChannelPut::shared_pointer const & channelPut) ChannelPut::shared_pointer const & channelPut)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::putDone"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelGetPutStatus = status; channelGetPutStatus = status;
waitForGetPut.signal(); waitForGetPut.signal();
} }
// from PvaClientPut
void PvaClientPut::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelPut) channelPut->destroy();
channelPut.reset();
}
void PvaClientPut::connect() void PvaClientPut::connect()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPut::connect " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::connect "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPut::issueConnect() void PvaClientPut::issueConnect()
{ {
Channel::shared_pointer chan(channel.lock()); if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ") + channel->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " pvaClientPut already connected "; + " pvaClientPut already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { putRequester = ChannelPutRequester::shared_pointer(new ChannelPutRequesterImpl(this));
connectState = connectActive; connectState = connectActive;
channelPut = chan->createChannelPut(channelPutRequester,pvRequest); channelPut = channel->createChannelPut(putRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientPut::issueConnect() but channel disconnected");
} }
Status PvaClientPut::waitConnect() Status PvaClientPut::waitConnect()
{ {
{ if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
Lock xx(mutex); if(connectState!=connectActive) {
if(connectState==connected) { string message = string("channel ") + channel->getChannelName()
if(!channelPutConnectStatus.isOK()) connectState = connectIdle; + " pvaClientPut illegal connect state ";
return channelPutConnectStatus; throw std::runtime_error(message);
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPut::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
} }
waitForConnect.wait(); waitForConnect.wait();
if(!channelPutConnectStatus.isOK()) connectState = connectIdle; connectState = channelPutConnectStatus.isOK() ? connected : connectIdle;
return channelPutConnectStatus; return channelPutConnectStatus;
} }
void PvaClientPut::get() void PvaClientPut::get()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
issueGet(); issueGet();
Status status = waitGet(); Status status = waitGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPut::get " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::get "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPut::issueGet() void PvaClientPut::issueGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putState!=putIdle) { if(putState!=putIdle) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ "PvaClientPut::issueGet get or put aleady active "; + "PvaClientPut::issueGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
putState = getActive; putState = getActive;
pvaClientData->getChangedBitSet()->clear();
channelPut->get(); channelPut->get();
} }
Status PvaClientPut::waitGet() Status PvaClientPut::waitGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
if(putState!=getActive){ if(putState!=getActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPut::waitGet llegal put state";
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::waitGet illegal put state";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForGetPut.wait(); waitForGetPut.wait();
@@ -319,28 +223,21 @@ Status PvaClientPut::waitGet()
void PvaClientPut::put() void PvaClientPut::put()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
issuePut(); issuePut();
Status status = waitPut(); Status status = waitPut();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPut::put " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::put "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPut::issuePut() void PvaClientPut::issuePut()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putState!=putIdle) { if(putState!=putIdle) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ "PvaClientPut::issueGet get or put aleady active "; + "PvaClientPut::issueGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -350,14 +247,11 @@ void PvaClientPut::issuePut()
Status PvaClientPut::waitPut() Status PvaClientPut::waitPut()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPut was destroyed");
if(putState!=putActive){ if(putState!=putActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPut::waitPut llegal put state";
if(chan) channelName = chan->getChannelName(); throw std::runtime_error(message);
string message = string("channel ")
+ channelName
+ " PvaClientPut::waitPut illegal put state";
throw std::runtime_error(message);
} }
waitForGetPut.wait(); waitForGetPut.wait();
putState = putIdle; putState = putIdle;
@@ -371,5 +265,14 @@ PvaClientPutDataPtr PvaClientPut::getData()
return pvaClientData; return pvaClientData;
} }
PvaClientPutPtr PvaClientPut::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientPutPtr epv(new PvaClientPut(pvaClient,channel,pvRequest));
return epv;
}
}} }}
+8 -8
View File
@@ -8,16 +8,15 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#define epicsExportSharedSymbols
#include <typeinfo> #include <typeinfo>
#include <sstream>
#include <sstream>
#include <pv/pvaClient.h>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#include <pv/convert.h> #include <pv/convert.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using namespace epics::pvData; using namespace epics::pvData;
@@ -28,14 +27,15 @@ namespace epics { namespace pvaClient {
class PvaClientPostHandlerPvt: public PostHandler class PvaClientPostHandlerPvt: public PostHandler
{ {
PvaClientPutData * putData; PvaClientPutData * easyData;
size_t fieldNumber; size_t fieldNumber;
public: public:
PvaClientPostHandlerPvt(PvaClientPutData *putData,size_t fieldNumber) PvaClientPostHandlerPvt(PvaClientPutData *easyData,size_t fieldNumber)
: putData(putData),fieldNumber(fieldNumber){} : easyData(easyData),fieldNumber(fieldNumber){}
void postPut() { putData->postPut(fieldNumber);} void postPut() { easyData->postPut(fieldNumber);}
}; };
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr; typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static ConvertPtr convert = getConvert(); static ConvertPtr convert = getConvert();
static string noValue("no value field"); static string noValue("no value field");
+109 -206
View File
@@ -8,10 +8,9 @@
* @author mrk * @author mrk
* @date 2015.02 * @date 2015.02
*/ */
#include <pv/event.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
#include <pv/event.h>
#include <pv/pvaClient.h> #include <pv/pvaClient.h>
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
@@ -23,88 +22,48 @@ namespace epics { namespace pvaClient {
class ChannelPutGetRequesterImpl : public ChannelPutGetRequester class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
{ {
PvaClientPutGet::weak_pointer pvaClientPutGet; PvaClientPutGet * pvaClientPutGet;
PvaClient::weak_pointer pvaClient;
public: public:
ChannelPutGetRequesterImpl( ChannelPutGetRequesterImpl(PvaClientPutGet * pvaClientPutGet)
PvaClientPutGetPtr const & pvaClientPutGet, : pvaClientPutGet(pvaClientPutGet) {}
PvaClientPtr const &pvaClient) string getRequesterName()
: pvaClientPutGet(pvaClientPutGet), {return pvaClientPutGet->getRequesterName();}
pvaClient(pvaClient) void message(string const & message,MessageType messageType)
{} {pvaClientPutGet->message(message,messageType);}
virtual ~ChannelPutGetRequesterImpl() { void channelPutGetConnect(
if(PvaClient::getDebug()) std::cout << "~ChannelPutGetRequesterImpl" << std::endl; const epics::pvData::Status& status,
} epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
epics::pvData::StructureConstPtr const & putStructure,
virtual std::string getRequesterName() { epics::pvData::StructureConstPtr const & getStructure)
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return string("clientPutGet is null");
return clientPutGet->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return;
clientPutGet->message(message,messageType);
}
virtual void channelPutGetConnect(
const Status& status,
ChannelPutGet::shared_pointer const & channelPutGet,
Structure::const_shared_pointer const & putStructure,
Structure::const_shared_pointer const & getStructure)
{ {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); pvaClientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
if(!clientPutGet) return;
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
} }
void putGetDone(
virtual void putGetDone( const epics::pvData::Status& status,
const Status& status, epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
ChannelPutGet::shared_pointer const & channelPutGet, epics::pvData::PVStructurePtr const & getPVStructure,
PVStructurePtr const & getPVStructure, epics::pvData::BitSetPtr const & getChangedBitSet)
BitSet::shared_pointer const & getBitSet)
{ {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); pvaClientPutGet->putGetDone(status,channelPutGet,getPVStructure,getChangedBitSet);
if(!clientPutGet) return;
clientPutGet->putGetDone(status,channelPutGet,getPVStructure,getBitSet);
} }
void getPutDone(
virtual void getPutDone( const epics::pvData::Status& status,
const Status& status, epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
ChannelPutGet::shared_pointer const & channelPutGet, epics::pvData::PVStructurePtr const & putPVStructure,
PVStructurePtr const & putPVStructure, epics::pvData::BitSet::shared_pointer const & putBitSet)
BitSet::shared_pointer const & putBitSet)
{ {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); pvaClientPutGet->getPutDone(status,channelPutGet,putPVStructure,putBitSet);
if(!clientPutGet) return;
clientPutGet->getPutDone(status,channelPutGet,putPVStructure,putBitSet);
} }
void getGetDone(
const epics::pvData::Status& status,
virtual void getGetDone( epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
const Status& status, epics::pvData::PVStructurePtr const & getPVStructure,
ChannelPutGet::shared_pointer const & channelPutGet, epics::pvData::BitSet::shared_pointer const & getChangedBitSet)
PVStructurePtr const & getPVStructure,
BitSet::shared_pointer const & getBitSet)
{ {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); pvaClientPutGet->getGetDone(status,channelPutGet,getPVStructure,getChangedBitSet);
if(!clientPutGet) return;
clientPutGet->getGetDone(status,channelPutGet,getPVStructure,getBitSet);
} }
}; };
PvaClientPutGetPtr PvaClientPutGet::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientPutGetPtr epv(new PvaClientPutGet(pvaClient,channel,pvRequest));
epv->channelPutGetRequester = ChannelPutGetRequesterImplPtr(
new ChannelPutGetRequesterImpl(epv,pvaClient));
return epv;
}
PvaClientPutGet::PvaClientPutGet( PvaClientPutGet::PvaClientPutGet(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, Channel::shared_pointer const & channel,
@@ -112,48 +71,39 @@ PvaClientPutGet::PvaClientPutGet(
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), channel(channel),
pvRequest(pvRequest), pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle), connectState(connectIdle),
putGetState(putGetIdle) putGetState(putGetIdle)
{ {
if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::PvaClientPutGet"
<< " channelName " << channel->getChannelName()
<< endl;
}
} }
PvaClientPutGet::~PvaClientPutGet() PvaClientPutGet::~PvaClientPutGet()
{ {
if(PvaClient::getDebug()) { destroy();
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientPutGet::~PvaClientPutGet"
<< " channelName " << channelName
<< endl;
}
channelPutGet->destroy();
} }
void PvaClientPutGet::checkPutGetState() void PvaClientPutGet::checkPutGetState()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(connectState==connectIdle){ if(connectState==connectIdle){
connect(); connect();
getPut(); getPut();
} }
} }
// from ChannelPutGetRequester
string PvaClientPutGet::getRequesterName() string PvaClientPutGet::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientPutGet::getRequesterName() PvaClient isDestroyed"); if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName(); return yyy->getRequesterName();
} }
void PvaClientPutGet::message(string const & message,MessageType messageType) void PvaClientPutGet::message(string const & message,MessageType messageType)
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return; if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType); yyy->message(message, messageType);
} }
@@ -163,19 +113,14 @@ void PvaClientPutGet::channelPutGetConnect(
StructureConstPtr const & putStructure, StructureConstPtr const & putStructure,
StructureConstPtr const & getStructure) StructureConstPtr const & getStructure)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
cout << "PvaClientPutGet::channelPutGetConnect"
<< " channelName " << channelPutGet->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetConnectStatus = status; channelPutGetConnectStatus = status;
this->channelPutGet = channelPutGet; this->channelPutGet = channelPutGet;
if(status.isOK()) { if(status.isOK()) {
pvaClientPutData = PvaClientPutData::create(putStructure); pvaClientPutData = PvaClientPutData::create(putStructure);
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); pvaClientPutData->setMessagePrefix(channel->getChannelName());
pvaClientGetData = PvaClientGetData::create(getStructure); pvaClientGetData = PvaClientGetData::create(getStructure);
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); pvaClientGetData->setMessagePrefix(channel->getChannelName());
} }
waitForConnect.signal(); waitForConnect.signal();
@@ -187,15 +132,7 @@ void PvaClientPutGet::putGetDone(
PVStructurePtr const & getPVStructure, PVStructurePtr const & getPVStructure,
BitSetPtr const & getChangedBitSet) BitSetPtr const & getChangedBitSet)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::putGetDone"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetStatus = status; channelPutGetStatus = status;
if(status.isOK()) { if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet); pvaClientGetData->setData(getPVStructure,getChangedBitSet);
@@ -209,15 +146,7 @@ void PvaClientPutGet::getPutDone(
PVStructurePtr const & putPVStructure, PVStructurePtr const & putPVStructure,
BitSetPtr const & putBitSet) BitSetPtr const & putBitSet)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::getPutDone"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetStatus = status; channelPutGetStatus = status;
if(status.isOK()) { if(status.isOK()) {
PVStructurePtr pvs = pvaClientPutData->getPVStructure(); PVStructurePtr pvs = pvaClientPutData->getPVStructure();
@@ -235,15 +164,7 @@ void PvaClientPutGet::getGetDone(
PVStructurePtr const & getPVStructure, PVStructurePtr const & getPVStructure,
BitSetPtr const & getChangedBitSet) BitSetPtr const & getChangedBitSet)
{ {
if(PvaClient::getDebug()) { if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::getGetDone"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetStatus = status; channelPutGetStatus = status;
if(status.isOK()) { if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet); pvaClientGetData->setData(getPVStructure,getChangedBitSet);
@@ -251,55 +172,51 @@ void PvaClientPutGet::getGetDone(
waitForPutGet.signal(); waitForPutGet.signal();
} }
// from PvaClientPutGet
void PvaClientPutGet::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelPutGet) channelPutGet->destroy();
channelPutGet.reset();
}
void PvaClientPutGet::connect() void PvaClientPutGet::connect()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::connect " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPutGet::connect "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPutGet::issueConnect() void PvaClientPutGet::issueConnect()
{ {
Channel::shared_pointer chan(channel.lock()); if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ") + channel->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " pvaClientPutGet already connected "; + " pvaClientPutGet already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { putGetRequester = ChannelPutGetRequester::shared_pointer(new ChannelPutGetRequesterImpl(this));
connectState = connectActive; connectState = connectActive;
channelPutGet = chan->createChannelPutGet(channelPutGetRequester,pvRequest); channelPutGet = channel->createChannelPutGet(putGetRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientPutGet::issueConnect() but channel disconnected");
} }
Status PvaClientPutGet::waitConnect() Status PvaClientPutGet::waitConnect()
{ {
{ if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
Lock xx(mutex); if(connectState!=connectActive) {
if(connectState==connected) { string message = string("channel ") + channel->getChannelName()
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle; + " pvaClientPutGet illegal connect state ";
return channelPutGetConnectStatus; throw std::runtime_error(message);
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
} }
waitForConnect.wait(); waitForConnect.wait();
connectState = channelPutGetConnectStatus.isOK() ? connected : connectIdle; connectState = channelPutGetConnectStatus.isOK() ? connected : connectIdle;
@@ -309,28 +226,22 @@ Status PvaClientPutGet::waitConnect()
void PvaClientPutGet::putGet() void PvaClientPutGet::putGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
issuePutGet(); issuePutGet();
Status status = waitPutGet(); Status status = waitPutGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::putGet " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::putGet "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPutGet::issuePutGet() void PvaClientPutGet::issuePutGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) { if(putGetState!=putGetIdle) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::issueGet get or put aleady active ";
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::issuePutGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
putGetState = putGetActive; putGetState = putGetActive;
@@ -340,12 +251,10 @@ void PvaClientPutGet::issuePutGet()
Status PvaClientPutGet::waitPutGet() Status PvaClientPutGet::waitPutGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(putGetState!=putGetActive){ if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::waitPutGet llegal put state";
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitPutGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForPutGet.wait(); waitForPutGet.wait();
@@ -355,28 +264,22 @@ Status PvaClientPutGet::waitPutGet()
void PvaClientPutGet::getGet() void PvaClientPutGet::getGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
issueGetGet(); issueGetGet();
Status status = waitGetGet(); Status status = waitGetGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::getGet " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::getGet "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPutGet::issueGetGet() void PvaClientPutGet::issueGetGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) { if(putGetState!=putGetIdle) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::issueGetGet aleady active ";
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::issueGetGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
putGetState = putGetActive; putGetState = putGetActive;
@@ -385,12 +288,10 @@ void PvaClientPutGet::issueGetGet()
Status PvaClientPutGet::waitGetGet() Status PvaClientPutGet::waitGetGet()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(putGetState!=putGetActive){ if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::waitGetGet illegal state";
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitGetGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForPutGet.wait(); waitForPutGet.wait();
@@ -400,28 +301,22 @@ Status PvaClientPutGet::waitGetGet()
void PvaClientPutGet::getPut() void PvaClientPutGet::getPut()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
issueGetPut(); issueGetPut();
Status status = waitGetPut(); Status status = waitGetPut();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::getPut " + status.getMessage();
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::getPut "
+ status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientPutGet::issueGetPut() void PvaClientPutGet::issueGetPut()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) { if(putGetState!=putGetIdle) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::issueGetPut aleady active ";
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::issueGetPut get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
putGetState = putGetActive; putGetState = putGetActive;
@@ -430,12 +325,10 @@ void PvaClientPutGet::issueGetPut()
Status PvaClientPutGet::waitGetPut() Status PvaClientPutGet::waitGetPut()
{ {
if(isDestroyed) throw std::runtime_error("pvaClientPutGet was destroyed");
if(putGetState!=putGetActive){ if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + channel->getChannelName()
string channelName("disconnected"); + " PvaClientPutGet::waitGetPut illegal state";
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitGetPut get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForPutGet.wait(); waitForPutGet.wait();
@@ -455,4 +348,14 @@ PvaClientPutDataPtr PvaClientPutGet::getPutData()
return pvaClientPutData; return pvaClientPutData;
} }
PvaClientPutGetPtr PvaClientPutGet::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientPutGetPtr epv(new PvaClientPutGet(pvaClient,channel,pvRequest));
return epv;
}
}} }}
-344
View File
@@ -1,344 +0,0 @@
/* pvaClientRPC.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.03
*/
#include <sstream>
#include <pv/event.h>
#include <pv/bitSetUtil.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvaClient {
class RPCRequesterImpl : public ChannelRPCRequester
{
PvaClientRPC::weak_pointer pvaClientRPC;
PvaClient::weak_pointer pvaClient;
public:
RPCRequesterImpl(
PvaClientRPCPtr const & pvaClientRPC,
PvaClientPtr const &pvaClient)
: pvaClientRPC(pvaClientRPC),
pvaClient(pvaClient)
{}
virtual ~RPCRequesterImpl() {
if(PvaClient::getDebug()) std::cout << "~RPCRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return string("pvaClientRPC is null");
return clientRPC->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return;
clientRPC->message(message,messageType);
}
virtual void channelRPCConnect(
const epics::pvData::Status& status,
ChannelRPC::shared_pointer const & channelRPC)
{
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return;
clientRPC->rpcConnect(status,channelRPC);
}
virtual void requestDone(
const Status& status,
ChannelRPC::shared_pointer const & channelRPC,
PVStructure::shared_pointer const & pvResponse)
{
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return;
clientRPC->requestDone(status,channelRPC,pvResponse);
}
};
PvaClientRPCPtr PvaClientRPC::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel)
{
StructureConstPtr structure(getFieldCreate()->createStructure());
PVStructurePtr pvRequest(getPVDataCreate()->createPVStructure(structure));
return create(pvaClient,channel,pvRequest);
}
PvaClientRPCPtr PvaClientRPC::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
PvaClientRPCPtr epv(new PvaClientRPC(pvaClient,channel,pvRequest));
epv->rpcRequester = RPCRequesterImplPtr(
new RPCRequesterImpl(epv,pvaClient));
return epv;
}
PvaClientRPC::PvaClientRPC(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
:
connectState(connectIdle),
pvaClient(pvaClient),
channel(channel),
pvRequest(pvRequest),
rpcState(rpcIdle),
responseTimeout(0.0)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientRPC::PvaClientRPC()"
<< " channelName " << channel->getChannelName()
<< endl;
}
}
PvaClientRPC::~PvaClientRPC()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientRPC::~PvaClientRPC"
<< " channelName " << channelName
<< endl;
}
}
void PvaClientRPC::checkRPCState()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientRPC::checkRPCState"
<< " channelName " << channelName
<< " connectState " << connectState
<< endl;
}
if(connectState==connectIdle) connect();
}
string PvaClientRPC::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientRPC::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
}
void PvaClientRPC::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
}
void PvaClientRPC::rpcConnect(
const Status& status,
ChannelRPC::shared_pointer const & channelRPC)
{
Channel::shared_pointer chan(channel.lock());
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientRPC::rpcConnect"
<< " channelName " << channelName
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
if(!chan) return;
connectStatus = status;
connectState = connected;
if(PvaClient::getDebug()) {
cout << "PvaClientRPC::rpcConnect calling waitForConnect.signal\n";
}
waitForConnect.signal();
}
void PvaClientRPC::requestDone(
const Status& status,
ChannelRPC::shared_pointer const & channelRPC,
PVStructure::shared_pointer const & pvResponse)
{
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
{
Lock xx(mutex);
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientRPC::requestDone"
<< " channelName " << channelName
<< endl;
}
if(rpcState!=rpcActive) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+" PvaClientRPC::requestDone"
+ " but not active";
throw std::runtime_error(message);
}
if(req && (responseTimeout<=0.0)) {
rpcState = rpcIdle;
} else {
rpcState = rpcComplete;
if(!req) this->pvResponse = pvResponse;
waitForDone.signal();
}
}
if(req) {
req->requestDone(status,shared_from_this(),pvResponse);
}
}
void PvaClientRPC::connect()
{
if(PvaClient::getDebug()) cout << "PvaClientRPC::connect\n";
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientRPC::connect "
+ status.getMessage();
throw std::runtime_error(message);
}
void PvaClientRPC::issueConnect()
{
if(PvaClient::getDebug()) cout << "PvaClientRPC::issueConnect\n";
Channel::shared_pointer chan(channel.lock());
if(connectState!=connectIdle) {
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " pvaClientRPC already connected ";
throw std::runtime_error(message);
}
if(chan) {
connectState = connectActive;
channelRPC = chan->createChannelRPC(rpcRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientRPC::issueConnect() but channel disconnected");
}
Status PvaClientRPC::waitConnect()
{
if(PvaClient::getDebug()) cout << "PvaClientRPC::waitConnect\n";
if(connectState==connected) {
if(!connectStatus.isOK()) connectState = connectIdle;
return connectStatus;
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientRPC::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
if(PvaClient::getDebug()) {
cout << "PvaClientRPC::waitConnect calling waitForConnect.wait\n";
}
waitForConnect.wait();
connectState = connectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) {
cout << "PvaClientRPC::waitConnect"
<< " connectStatus " << (connectStatus.isOK() ? "connected" : "not connected");
}
return connectStatus;
}
PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer const & pvArgument)
{
checkRPCState();
{
Lock xx(mutex);
if(rpcState!=rpcIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ " PvaClientRPC::request request aleady active ";
throw std::runtime_error(message);
}
rpcState = rpcActive;
}
channelRPC->request(pvArgument);
if(responseTimeout>0.0) {
waitForDone.wait(responseTimeout);
} else {
waitForDone.wait();
}
Lock xx(mutex);
if(rpcState!=rpcComplete) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ " PvaClientRPC::request request timeout ";
throw std::runtime_error(message);
}
rpcState = rpcIdle;
return pvResponse;
}
void PvaClientRPC::request(
PVStructure::shared_pointer const & pvArgument,
PvaClientRPCRequesterPtr const & pvaClientRPCRequester)
{
checkRPCState();
this->pvaClientRPCRequester = pvaClientRPCRequester;
if(responseTimeout<=0.0) {
{
Lock xx(mutex);
if(rpcState!=rpcIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ " PvaClientRPC::request request aleady active ";
throw std::runtime_error(message);
}
rpcState = rpcActive;
}
channelRPC->request(pvArgument);
return;
}
request(pvArgument);
}
}}