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  2017  2018  <20192020  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  <20192020 
<== Date ==> <== Thread ==>

Subject: Re: Questions about channel access C API programming
From: "Johnson, Andrew N. via Tech-talk" <tech-talk@aps.anl.gov>
To: Abdalla Ahmad <abdalla.ahmad@sesame.org.jo>, "tech-talk@aps.anl.gov" <tech-talk@aps.anl.gov>
Date: Thu, 7 Mar 2019 00:14:20 +0000
Hi Abdalla,

On 3/6/19 2:11 AM, Abdalla Ahmad wrote:
In my code I added a ca_pend_io after the main loop just to wait for the ca_put calls to finish their IO but kept the same ca_pend_io per each search. For now it is working fine but I still need to test it by applying a real and large sample of PVs.
Your new ca_pend_io() call will do a ca_flush() and then return immediately, since the IOC doesn't send any replies to a ca_put() message so there are no more I/O operations outstanding at that point for the client library to wait for.
For an event-driven API, do you mean something like ca_put_callback in the CA API?
Yes and no; unfortunately ca_put_callback() is the one CA routine that actually does something slightly different than its ca_put() equivalent so there are some circumstances where you might *not* want to use that, although in this I think you probably could (see below for more detail). I did mean to use other routines with callbacks such as ca_create_channel() instead of ca_search() though; in your case if the two PVs you are addressing are on different IOCs and the first IOC happens to be turned off, your code would still write to the second PV, which you might not want to happen. Your code was not checking the status of the two chids to ensure that they have connected before calling ca_put(), or looking at the return value from ca_pend_io().


The problem with ca_put_callback() is that unlike ca_put() it actually asks the IOC to keep track of every internal operation that gets started by this put and to not respond until all those operations have finished. In most cases that won't take very long, but it is possible that the ca_put_callback() might trigger a motor to start moving that won't reach its target position for several minutes, or even trigger an experimental scan that could take hours or even days to finish. The callback will not be run on the client until that slow operation is finished.

Also, there can only be one ca_put_callback() active on a particular record at once, so if you use ca_put_callback() to set a motor moving but you want to stop it before it reaches its target position, you have to use a ca_put() to perform the stop; if you try to use a second ca_put_callback() it will be delayed until the first operation completes.

Unfortunately writing robust code for a distributed control system like EPICS can be challenging!

- Andrew

 

From: Johnson, Andrew N. [mailto:anj@anl.gov]
Sent: Tuesday, March 05, 2019 6:45 PM
To: Abdalla Ahmad <abdalla.ahmad@sesame.org.jo>; tech-talk@aps.anl.gov
Subject: Re: Questions about channel access C API programming

 

On 3/5/19 8:08 AM, Abdalla Ahmad via Tech-talk wrote:

The attached C file is a snippet from a Qt project. In the project there was a function that writes values to many PVs in a loop. What was happening is that some PVs do not get their new value updated immediately but after 3 or 4 seconds. The code shows a similar behavior, two consecutive "ca_put" calls, and the same behavior occurs. I double-checked the database (included in the comments) but there is nothing wrong. I tried to use ca_context_ or ca_task_ but the project crashes maybe because the QE framework is already handling low-level CA. What am I missing here?


If you want to minimize the time between the two puts, you should reorganize the code so all the name searches happen first and get resolved, then do both puts together, more like this:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cadef.h>
 
int main()
{
    srand(time(0));
    double v1 = ((rand() % 100) / 10.0) * 1E-7;
    double v2 = ((rand() % 100) / 10.0);
    
    chid pvID1;
    chid pvID2;
 
    ca_task_initialize();
        
    ca_search("Analog_1", &pvID1);
    ca_search("Analog_2", &pvID2);
    ca_pend_io(1.0);
 
    ca_put(DBR_DOUBLE, pvID1, &v2);
    ca_put(DBR_DOUBLE, pvID2, &v2);
    ca_flush();
 
    ca_task_exit();
}

Of course this code won't behave quite the same as your version if the Analog_2 record isn't available, and it really should be checking the status values returned by all CA routines to detect those kinds of problems. If you don't do that your control system is likely to be very brittle, meaning that when something minor goes wrong (such as a name search taking longer to complete than the 1 second you are allowing because the load on your network has increased since you tested the code) the knock-on effects could bring down your whole control system.

For code that needs to be event driven like I suspect most Qt applications are, you probably shouldn't be using the basic API routines
ca_search() and ca_pend_io() either, but should switch to the event-driven API routines that take callback routines that are called when the operation completes.

- Andrew

-- 
Arguing for surveillance because you have nothing to hide is no
different than making the claim, "I don't care about freedom of
speech because I have nothing to say." -- Edward Snowdon

-- 
Arguing for surveillance because you have nothing to hide is no
different than making the claim, "I don't care about freedom of
speech because I have nothing to say." -- Edward Snowdon

References:
Questions about channel access C API programming Abdalla Ahmad via Tech-talk
Re: Questions about channel access C API programming Johnson, Andrew N. via Tech-talk
RE: Questions about channel access C API programming Abdalla Ahmad via Tech-talk

Navigate by Date:
Prev: Re: epics-Keithley_648x, drvAsynKeithley648x Arms, Dohn A. via Tech-talk
Next: Re: epics-Keithley_648x, drvAsynKeithley648x Heinz Junkes via Tech-talk
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  <20192020 
Navigate by Thread:
Prev: RE: Questions about channel access C API programming Abdalla Ahmad via Tech-talk
Next: RE: Questions about channel access C API programming Abdalla Ahmad via Tech-talk
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  <20192020 
ANJ, 07 Mar 2019 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·