EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <20172018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <20172018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: C++ multi threaded application.
From: "Giacomo S." <[email protected]>
To: Andrew Johnson <[email protected]>, [email protected]
Date: Thu, 7 Sep 2017 11:56:48 +0200
Hello Andrew,
below you will find one more doubt I would like to understand better...

On 09/05/2017 06:58 PM, Andrew Johnson wrote:
> Hi Giacomo,
>
> On 09/05/2017 10:01 AM, Giacomo S. wrote:
>> So, summing up, suppose to recreate this scenario:
>>
>> - application starts
>> --> client requests monitoring of  pv1 = foo:ai1
>>
>> - (first request, so)   ca_context_create(ca_enable_preemptive_callback)
>>
>> - ca_create_channel (...)
>>
>> - (in  connection_handler invoked from EPICS foo thread: ) 
>> ca_create_subscription(...)
> A note: You are allowed to subscribe to channels using a different
> request data type than their native type, and the IOC will do its best
> to convert the data for you. I don't completely understand how your
> connection_handler() method transforms the native type, but I just
> wanted to make that point for later on...
>
>> [ monitors for a while, receive event callbacks from EPICS foo thread]
>>
>> --> client requests pv2  = foo:ai2
>>
>>  - ca_create_channel (...)
>>
>> - (in  connection_handler invoked from EPICS foo thread: ) 
>> ca_create_subscription(...)
>>
>>
>> ---> network goes down
>>
>> - (in pv1 connection callback invoked from EPICS foo thread:)  1. 
>> ca_clear_subscription()   BUT NOT ca_clear_channel()
> Here's where Michael and I have slightly differing opinions: I wouldn't
> necessarily clear the subscription when the connection goes down,
> especially if I'm not relying on the native data type of the channel to
> select what type I subscribe with. CA will remember the original
> subscription and will reconnect it to the IOC when it comes back. In
> connection_handler() you were already storing the fact that you have
> already subscribed, so that code wouldn't create multiple subscriptions.
>
> One issue that you do have to be careful of though is if an IOC gets
> rebooted with a modified database so the data type of a channel you were
> subscribed to changes between the connection going down and coming back
> up. In this case CA subscriptions will reconnect using the type in their
> original subscription request, which might now be different to the
> native type of the channel. The client code has to be aware of that and
> use the type information from the data update callback.
>
> Michael's approach of clearing subscriptions at disconnect is probably
> safer, but requires the application code to do a bit more work, as
> evidenced by the additional calls to ca_create_subscription() below. The
> difference is really a matter of opinion.
>
>> - (in pv2 connection callback invoked from EPICS foo thread:)  1. 
>> ca_clear_subscription()      BUT NOT   ca_clear_channel()
>>
>> ---> network UP again
>>
>>
>> - (in pv1 connection callback invoked from EPICS foo thread:)  1. 
>> ca_create_subscription() 
>>
>> - (in pv2 connection callback invoked from EPICS foo thread:)  1. 
>> ca_create_subscription()  
>>
>> ---> client requests pv3  = bar:ai3
>>
>>  - ca_create_channel (...)
>>
>> - (in  connection_handler invoked from EPICS >>> bar <<<  thread: ) 
>> ca_create_subscription(...)   <--- bar THREAD <----
>>
>> [ receive event callbacks from 2 threads: foo for pv1 and pv2,  bar for
>> pv3 ]
>>
>> ---> client wants to disconnect everything (or application shutdown)
>>
>> - foreach pv:                                                 // is this
>> safe to be called from the thread that initially called the ca_create* 
>> counterparts???
> You can call any ca routine from any thread that has been attached to
> the context, so yes.
>
>>   * ca_clear_subscription();
>>   * ca_clear_channel();
>>
>> - ca_context_destroy();                                // from same
>> thread where ca_context_create() was called
>>
>>
>> Is the above correct? Am I somewhere wrong?
> It looks like you understand it pretty well.
>
>
>> Some more simpler questions:
>>
>> 1. every time I receive an event, evargs contain not only the value /
>> timestamp but also configuration parameters, right (HI, LO thresholds
>> and so on...)
> Not sure what the question is there. Your event_handler_cb() routine is
> given a struct event_handler_args whose void *dbr pointer points to the
> dbr_* type that you subscribed to. There are many different dbr_* data
> types defined in db_access.h containing different subsets of the
> available data, but none of them provides everything, so you may need to
> subscribe to the same channel multiple times with different types and
> different event masks. Channel metadata (enum strings, alarm levels etc)
> usually change much less frequently than the data itself, and the event
> mask DBE_PROPERTY is designed to tell you when metadata has changed.

You mean calling MULTIPLE TIMES

ca_create_subscription()

with different event masks, different user data and parameters or is it
possible to subscribe ONCE
setting the event mask ORing the needed DBE_xxx together?

In this last case, the requested type should be "bigger" (DBR_CTRL*) so
as to contain data and metadata...
Moreover, inside the event callback I should be able to detect whether
the event is a metadata change or a
normal value update...
is this correct? How to do so?

Thanks again for all your help.
Giacomo

>
>> 2. are there utility functions to extract the value and timestamp from
>> the evargs and easily convert them into  the correct type (short,
>> double, int...)
> There are some macros in db_access.h that can help, e.g. dbr_value_ptr
>
> if you limit the number of types you subscribe to you can avoid having
> to write code that understands all the dbr_* types.
>
>> 3. If I monitor a PV, is it possible to know from the args if it's a
>> vector (and its dimension) or a scalar?
> Yes, the struct event_handler_args contains the data type, chid and
> element count for the data contained in this update (look in cadef.h for
> its definition). count==1 means it's a scalar.
>
>> 4. where can I find the explanation of this: Lo disp limit, hi disp
>> limit, Lo alarm limit.... ?
> Those metadata fields are supplied from fields of the record, disp =
> display, so a graph of the channel data over time should expect to use
> the low display limit for the bottom of the y axis and the high display
> limit for the top. Alarm limits tell you if the PV generates alarms what
> data values would trigger those alarms, so you could put a marker on the
> axis if you chose to do so.
>
>> 5. How to extract the timestamp of the event (as far as I've seen from
>> the code, there must be a timestamp from the server and one from the
>> client. In this case, what does the client side timestamp mean. Is it
>> the timestamp when the event is received on the client itself?)
> You appear to be looking at code from catools, which added the idea of
> providing a client-side timestamp as well as or instead of the timestamp
> from the IOC itself. I think it just provides the client's idea of the
> time when the CA library called its callback; this isn't part of the CA
> client library itself.
>
>> Is there a good tutorial for a quick start and the answers to my
>> questions 1 to 5?
>> I mean a quick start to understand how to program a client in C (C++).
> Maybe not at the level of detail you're asking, I think you've probably
> gone beyond what most CA client tutorials covered, but you could browse
> the EPICS Training links to see if there are any that help:
>     http://www.aps.anl.gov/epics/docs/training.php
>
>> One final thing: I've seen a set of C++ libraries (pvaClientCPP,
>> pvCommonCPP)  and in general the
>>
>> "EPICS V4 C++ module"
>>
>> but it looks like it's not up to date with the latest EPICS release.
>>
>> Is this the "official" C++ Epics module?
>>
>> Is it normal that it trails the last EPICS version?
> Those modules are part of the newer EPICS V4 network protocol
> implementation, which are designed to supplement and eventually replace
> the CA protocol. That's a completely different topic and the APIs are
> completely different, I suggest you ignore them for now.
>
> HTH,
>
> - Andrew
>


Replies:
Re: C++ multi threaded application. Andrew Johnson
References:
C++ multi threaded application. Giacomo S.
Re: C++ multi threaded application. Andrew Johnson
Re: C++ multi threaded application. Giacomo S.
Re: C++ multi threaded application. Giacomo S.
Re: C++ multi threaded application. Andrew Johnson

Navigate by Date:
Prev: Re: StreamDevice hexa checksum in lowercase characters Paduan Donadio, Marcio
Next: Re: C++ multi threaded application. Andrew Johnson
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <20172018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: C++ multi threaded application. Andrew Johnson
Next: Re: C++ multi threaded application. Andrew Johnson
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  <20172018  2019  2020  2021  2022  2023  2024 
ANJ, 21 Dec 2017 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·