Torsten, If you only have 20 motors with 1-2 enums then I don't understand why you don't just use the current "correct" solution which does not require a hack to do callbacks. Just implement the readEnum method. This is a search for
ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.
ZjQcmQRYFpfptBannerEnd
Torsten,
If you only have 20 motors with 1-2 enums then I don't understand why you don't just use the current "correct" solution which does not require a hack to do callbacks. Just implement the readEnum method.
This is a search for all current synApps and areaDetector drivers that do that:
(base) [epics@corvette devel]$ find . -name '*.cpp' -exec grep -H readEnum {} \;
./Galil/3-6/GalilSup/src/GalilController.cpp:asynStatus GalilController::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[], size_t nElements, size_t *nIn)
./asyn-4-43/testAsynPortDriverApp/src/testAsynPortDriver.cpp:asynStatus testAsynPortDriver::readEnum(asynUser
*pasynUser, char *strings[], int values[], int severities[], size_t nElements, size_t *nIn)
./asyn-4-43/testErrorsApp/src/testErrors.cpp:asynStatus testErrors::readEnum(asynUser *pasynUser, char *strings[],
int values[], int severities[], size_t nElements, size_t *nIn)
./quadEM-9-4/quadEMApp/src/drvPCR4.cpp:asynStatus drvPCR4::readEnum(asynUser *pasynUser,
./pmac-2-5-13/pmacApp/src/pmacController.cpp:pmacController::readEnum(asynUser *pasynUser, char *strings[],
int values[], int severities[],
./measComp-4-0/measCompApp/src/drvMultiFunction.cpp:asynStatus MultiFunction::readEnum(asynUser *pasynUser,
char *strings[], int values[], int severities[], size_t nElements, size_t *nIn)
../labjack/LabJackApp/src/LabJackDriver.cpp:asynStatus LabJackDriver::readEnum(asynUser *pasynUser, char *strings[],
int values[], int severities[], size_t nElements, size_t *nIn)
./areaDetector-3-13/ADAndor3/andor3App/src/andor3.cpp:asynStatus andor3::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[],
./areaDetector-3-13/ADDexela/dexelaApp/src/Dexela.cpp:asynStatus Dexela::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[],
./areaDetector-3-13/ADPSL/pslApp/src/PSL.cpp:asynStatus PSL::readEnum(asynUser *pasynUser, char *strings[],
int values[], int severities[],
./areaDetector-3-13/ADPointGrey/pointGreyApp/src/pointGrey.cpp:asynStatus pointGrey::readEnum(asynUser *pasynUser,
char *strings[], int values[], int severities[],
./areaDetector-3-13/ADmarCCD/marCCDApp/src/marCCD.cpp:asynStatus marCCD::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[],
../areaDetector-3-13/ADPICam/PICamApp/src/ADPICam.cpp:asynStatus ADPICam::readEnum(asynUser *pasynUser, char
*strings[], int values[],
./areaDetector-3-13/ADAndor/andorApp/src/andorCCD.cpp:asynStatus AndorCCD::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[],
./areaDetector-3-13/ADLightField/lightFieldApp/src/LightField.cpp:asynStatus LightField::readEnum(asynUser
*pasynUser, char *strings[], int values[], int severities[],
./areaDetector-3-13/ADQImaging/App/src/QImaging.cpp:asynStatus QImage::readEnum(asynUser *pasynUser,
./areaDetector-3-13/ADPylon/pylonApp/src/ADPylon.cpp:asynStatus ADPylon::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[],
./areaDetector-3-13/ADSpinnaker/spinnakerApp/src/ADSpinnaker.cpp:asynStatus ADSpinnaker::readEnum(asynUser
*pasynUser, char *strings[], int values[], int severities[],
./areaDetector-3-13/aravisGigE/aravisGigEApp/src/aravisCamera.cpp:asynStatus aravisCamera::readEnum(asynUser
*pasynUser, char *strings[], int values[], int severities[],
../areaDetector-3-13/ADVimba/vimbaApp/src/ADVimba.cpp:asynStatus ADVimba::readEnum(asynUser *pasynUser, char
*strings[], int values[], int severities[],
../areaDetector-3-13/ADGenICam/GenICamApp/src/ADGenICam.cpp:asynStatus ADGenICam::readEnum(asynUser
*pasynUser, char *strings[], int values[], int severities[],
./areaDetector-3-13/specsAnalyser/specsAnalyserApp/src/specsAnalyser.cpp:asynStatus SpecsAnalyser::readEnum(asynUser
*pasynUser, char *strings[], int values[], int severities[], size_t nElements, size_t *nIn)
Mark
From: Core-talk <core-talk-bounces at aps.anl.gov> on behalf of Torsten Bögershausen via Core-talk <core-talk at aps.anl.gov>
Sent: Wednesday, February 28, 2024 11:20 PM
To: Ralph Lange <ralph.lange at gmx.de>; EPICS Core Talk <core-talk at aps.anl.gov>
Subject: Re: pC_->doCallbacksEnum() coming too early
This Message Is From an External Sender
This message came from outside your organization.
Hej Experts,
thanks so much for the help.
Right now I have a somewhat hackish version.
#if 0
/* This version gives:
warning:
'rset' is deprecated [-Wdeprecated-declarations]
rset *prset;
*/
#include <dbAccess.h> /* interruptAccept */
#else
#include <dbCoreAPI.h>
DBCORE_API extern volatile int interruptAccept;
#endif
But it works well.
Ralhp, I think that I do what you suggest already.
When connecting to the PLC, all data is read as fast as possible.
However, we are talking about 20 motors, which have 1--2 enums.
Not Megabytes of data ;-)
All this enum-values (for the mbbi) are today already stored
in a bunch of asyn-parameters.
So it was "only" the determination, when is it a good time for the
callback, that was missing.
Thanks again.
On 2024-02-28 09:53, Ralph Lange via Core-talk wrote:
> My 2cts. . . On Tue, 27 Feb 2024 at 23: 51, Mark Rivers via Core-talk
> <core-talk@ aps. anl. gov> wrote: ZjQcmQRYFpfptBannerEnd Hi Torsten,
> Ø The PLC gives us some names for enmums, resulting in a call to Ø
> pC_->doCallbacksEnum() doCallbacksEnum()
> ZjQcmQRYFpfptBannerStart
> This Message Is From an External Sender
> This message came from outside your organization.
> ZjQcmQRYFpfptBannerEnd
> My 2cts...
>
> On Tue, 27 Feb 2024 at 23:51, Mark Rivers via Core-talk
> <core-talk at aps.anl.gov <mailto:core-talk at aps.anl.gov>> wrote:
>
> __
> ZjQcmQRYFpfptBannerEnd
>
> Hi Torsten,____
>
> __ __
>
> __Ø__The PLC gives us some names for enmums, resulting in a call to____
>
> __Ø__pC_->doCallbacksEnum()____
>
> __ __
>
> doCallbacksEnum() is only intended to be called when an enum value
> changes at run-time, i.e. after iocInit. For enums that the driver
> determines at initialization you should simply implement the
> asynPortDriver::readEnum() method. Device support will call your
> driver during iocInit to read the enum values/strings/severities for
> all records with enum VAL fields.____
>
> __ __
>
> testAsynPortDriver has an example here:____
>
> https://urldefense.us/v3/__https://github.com/epics-modules/asyn/blob/a94a78987a99b1c36bbd641a67341069dc5d627e/testAsynPortDriverApp/src/testAsynPortDriver.cpp*L340__;Iw!!G_uCfscf7eWS!cNPFGdiAvPevZU44dGFiDBVJDU6UCKIHT814ujg1PMT3Y6IUhS7efeCJLa1uEeA5WaHYqwsTz0fMuYpskNU$ <https://urldefense.us/v3/__https://github.com/epics-modules/asyn/blob/a94a78987a99b1c36bbd641a67341069dc5d627e/testAsynPortDriverApp/src/testAsynPortDriver.cpp*L340__;Iw!!G_uCfscf7eWS!fE_LD5q32_jjj9Y2BpELUbcw3yXiB5OnxyWCR4yUcD48lMAvhT1_A34lEQ5JZaBnQaPIH8NUbIHoKoZgjJ-Vp9EB5zY$>____
>
> __ __
>
> It also has an example of using doCallbacksEnum(), which it does
> when the vertical gain is changed at run time.____
>
> https://urldefense.us/v3/__https://github.com/epics-modules/asyn/blob/a94a78987a99b1c36bbd641a67341069dc5d627e/testAsynPortDriverApp/src/testAsynPortDriver.cpp*L374__;Iw!!G_uCfscf7eWS!cNPFGdiAvPevZU44dGFiDBVJDU6UCKIHT814ujg1PMT3Y6IUhS7efeCJLa1uEeA5WaHYqwsTz0fM2ymOgHM$ <https://urldefense.us/v3/__https://github.com/epics-modules/asyn/blob/a94a78987a99b1c36bbd641a67341069dc5d627e/testAsynPortDriverApp/src/testAsynPortDriver.cpp*L374__;Iw!!G_uCfscf7eWS!fE_LD5q32_jjj9Y2BpELUbcw3yXiB5OnxyWCR4yUcD48lMAvhT1_A34lEQ5JZaBnQaPIH8NUbIHoKoZgjJ-VnvkyVf8$>
>
>
> Been there...
> The problem is that these are synchronous (blocking) calls. If you have
> many devices and/or devices that are handled asynchronously, this is
> likely to screw up your IOC startup.
>
> I think the most reasonable way to handle the situation is a bit more
> complex:
>
> * from the driver, do the requests to the devices as early as possible
> after the devices are up (and do the requests in parallel),
> * when the responses come in, queue them,
> * start the worker thread(s) for the queues (that push the values into
> the database) when the IOC is fully up, through the interruptAccept
> initHook.
>
> That will work no matter if the IOC becomes ready before, during or
> after the initial device readout is finished.
> Queueing incoming responses is always a good idea that helps with bursts
> or high-load-on-the-IOC-host situations.
>
> Cheers,
> ~Ralph
|