EPICS Home

Experimental Physics and Industrial Control System


 
2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: C++ question
From: Mark Rivers via Core-talk <core-talk at aps.anl.gov>
To: "core-talk at aps.anl.gov" <core-talk at aps.anl.gov>
Date: Fri, 20 Mar 2020 14:52:16 +0000

Folks,

 

I am having a problem with the areaDetector ADSpinnaker driver.  I am quite sure the problem is that I am doing something wrong in my C++ callback code.

 

The code in question is quite simple.

 

The following is a class that implements callbacks from the vendor library when a new image is available.  It inherits from the vendor’s ImageEvent class, and implments a method they define called OnImageEvent.  That method is passed a smart pointer of type ImagePtr.  I made a copy of that smart pointer and pass its address on an epicsMessageQueue.  The copy is deleted in the receiving function.

 

***************************************

class ImageEventHandler : public ImageEvent

{

public:

 

    ImageEventHandler(epicsMessageQueue *pMsgQ)

     : pMsgQ_(pMsgQ)

    {}

    ~ImageEventHandler() {}

 

    void OnImageEvent(ImagePtr image) {

        ImagePtr *imagePtrAddr = new ImagePtr(image);

 

        if (pMsgQ_->send(&imagePtrAddr, sizeof(imagePtrAddr)) != 0) {

            printf("OnImageEvent error calling pMsgQ_->send()\n");

        }

    }

 

private:

    epicsMessageQueue *pMsgQ_;

 

};

***************************************

 

This is the receiving function.

 

***************************************

asynStatus ADSpinnaker::grabImage()

{

    asynStatus status = asynSuccess;

    size_t nRows, nCols;

    NDDataType_t dataType;

    NDColorMode_t colorMode;

    int timeStampMode;

    int uniqueIdMode;

    int convertPixelFormat;

    bool imageConverted = false;

    int numColors;

    size_t dims[3];

    ImageStatus imageStatus;

    PixelFormatEnums pixelFormat;

    int pixelSize;

    size_t dataSize, dataSizePG;

    void *pData;

    int nDims;

    ImagePtr pImage;

    ImagePtr *imagePtrAddr=0;

    static const char *functionName = "grabImage";

 

    try {

        while(1) {

            unlock();

            int recvSize = pCallbackMsgQ_->receive(&imagePtrAddr, sizeof(imagePtrAddr), 0.1);

            lock();

            if (recvSize == sizeof(imagePtrAddr)) {

                break;

            } else if (recvSize == -1) {

                // Timeout

                int acquire;

                getIntegerParam(ADAcquire, &acquire);

                if (acquire == 0) {

                    return asynError;

                } else {

                    continue;

                }

            } else {

                asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,

                        "%s::%s error receiving from message queue\n",

                        driverName, functionName);

                return asynError;

            }

        }

        pImage = *imagePtrAddr;

        // Delete the ImagePtr that was passed to us

        delete imagePtrAddr;

Finishing processing pImage …

***************************************

 

Note that I have a timeout of 0.1 second on the msgQ->receive() call.  if the call times out it tries again if it is still acquiring.  This allows the function to return quickly if acquisition is stopped after it is called.

 

This code generally works fine when the time between images is 0.1 second or less, or 0.12 seconds or more.  However, if the time between images is 0.115 seconds, for example, I “lose” about 2-3% of the images.  There are no error messages.  If I increase the 0.1 second timeout to 0.2 seconds, then images are lost if the time between images is about 0.215 seconds. 

 

It seems to me that the problem must be that another callback happens before the previous image has been processed.  I thought that making a copy of the smart pointer on the stack would prevent this, but I must be doing something wrong.  Perhaps I am deleting the smart pointer too soon, or perhaps the whole approach I am using is unsafe?

 

Any advice is much appreciated!

 

Thanks,

Mark

 


Replies:
RE: C++ question Mark Rivers via Core-talk

Navigate by Date:
Prev: Re: IOC build fails after removing an iocBoot dir from Git Ralph Lange via Core-talk
Next: RE: C++ question Mark Rivers via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024 
Navigate by Thread:
Prev: Re: IOC build fails after removing an iocBoot dir from Git Ralph Lange via Core-talk
Next: RE: C++ question Mark Rivers via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  <20202021  2022  2023  2024