Hello and thanks for Your detailed answers.
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(...)
[ 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()
- (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???
* 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?
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...)
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...)
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?
4. where can I find the explanation of this: Lo disp limit, hi disp
limit, Lo alarm limit.... ?
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?)
Thanks for Your patience.
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++).
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?
Thanks again for everything.
Giacomo S.
On 09/04/2017 06:14 PM, Michael Davidsaver wrote:
> On 09/04/2017 04:08 AM, Giacomo S. wrote:
>> On 09/01/2017 06:31 PM, Andrew Johnson wrote:
>> ...
>>>> - the background thread implements a wait condition so that it sleeps
>>>> until a new event arrives (for example, exit event or new variable to be
>>>> monitored is added)
>>> You should be aware that the Channel Access client library creates a
>>> background thread for each separate IOC it connects to, and it calls
>>> your callback routines from those threads. You have no control over
>>> that, if you talk to PVs on 2 IOCs you will get callbacks from 2
>>> threads.
>> That's a relevant information. Thus, monitoring 100 PVs means at least
>> 100 threads in the application.
> Only if each PV is served by a separate IOC. If all 100 are served by
> one IOC, then there is only 1 socket and 2 threads to service it.
>
> ...
>> Inside the connection_handler() i call
>> ca_create_subscription()
>>
>>
>> // Code is taken from camonitor's.
>> //
>> void CuMonitorActivity::connection_handler(connection_handler_args args)
>> {
>>
> ...
>> /* ---------------- */
>> /* install monitor once with first connect */
>> ppv->status = ca_create_subscription(ppv->dbrType,
>> ppv->reqElems,
>> ppv->ch_id,
>> eventMask,
>>
>> CuMonitorActivity::event_handler_cb,
>> (void*)ppv,
>> NULL);
>> }
>> }
>> else if ( args.op == CA_OP_CONN_DOWN ) {
>> nConn--;
>> ppv->status = ECA_DISCONN;
>> print_time_val_sts(ppv, reqElems);
> Subscriptions are not automatically cleaned up on disconnect. You'll
> want to make sure you call ca_clear_subscription() here, and on exit, to
> avoid the situation Andrew mentions.
>
> You'll also want to look at ca_clear_channel() which must be paired with
> ca_create_channel().
>
>
>> }
>> }
>>
>>
>>>> From within connection_handler_cb I extract the current
>>>> CuMonitorActivity instance (stored in pv's monitor_activity field) and I
>>>> invoke the object's extraction method. Data is posted in the main thread.
>>>>
>>>> NOTE: I notice that connection_handler_cb is invoked from ANOTHER
>>>> thread, not my main thread, not my secondary thread. This should be as
>>>> expected I guess for things to work and given the ca_
>>>> enable_preemptive_callback option.
>>> Right, see my remarks about threading above. Note that you are allowed
>>> to make calls to other CA routines from within your callbacks, and in
>>> fact that is the recommended way to set up your subscriptions. However
>>> you should be careful to only subscribe for data from a PV only once; if
>>> the IOC gets restarted your connection handler will be called again on
>>> reconnect, and unless you're careful that code might create a second
>>> subscription to the same PV, which will result in your event callback
>>> being run twice or more for each data update from the IOC.
>>>
>>>> * when I post an "exitEvent" on my secondary thread from the main one
>>>> (e.g. the GUI is closed), "ca_context_destroy();" is invoked in my
>>>> secondary thread (not the Epics thread that calls connection_handler_cb
>>>> during monitoring - is this OK? )
>>> Yes, as long as the thread was attached to the CA context. You should
>>> attach all threads that you want to make CA calls from to your original
>>> context using ca_current_context() and ca_attach_context().
>>>
>>>> * Is there a way to ADD more PVs to monitor WHILE others are being
>>>> monitored (for example, is it legit to call create_pvs() again ) ?
>>> Yes, although you didn't show us your create_pvs() routine. You can add
>>> and remove channels and subscriptions whenever you like; about the only
>>> thing you can't call from within a callback routine is ca_pend_event().
>> OK, now it should be clear how I create the pvs.
> A client does not create PVs. From the prospective of a CA client a
> "PV" is the address string provided when creating a Channel (analogous
> to a URL).
>
>> Could you tell me how to add and remove channels and subscriptions?
> You are already doing this by calling ca_create_channel() and
> ca_create_subscription(). Removal is ca_clear_channel() and
> ca_clear_subscription().
>
>
>
>> As to threading, all channel/monitor setup is made up in a secondary thread.
>> The idea is thus to add and remove channels within that very secondary
>> thread.
>> So, as you stated, the callbacks would be invoked from the N different
>> threads on the event callback within the
>> CuMonitorActivity object.
>> Data, from within the event callback, is then queued and posted on the
>> main thread.
>> I have now to check whether I need to lock guard the code within the
>> event callback or not.
>>
>> Nonetheless, if my observations are correct, that makes a good starting
>> point.
>>
>> Thanks for Your help.
>>
>> Giacomo, Elettra, Trieste, Italy
>>
>>
>>>> * Are there any observations/corrections to my approach and to my
>>>> statements above?
>>> Go check out epicsQt before you spend more time reinventing the wheel.
>>> There is a separate mailing list for EPICS users programming with Qt and
>>> you might want to subscribe to that:
>>> http://www.aps.anl.gov/epics/qti-talk/index.php
>>>
>>> - 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.
- Navigate by Date:
- Prev:
data refresh and add pv 梁雅翔
- 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
<2017>
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: C++ multi threaded application. Michael Davidsaver
- 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
<2017>
2018
2019
2020
2021
2022
2023
2024
|