Open
Conversation
This was referenced Feb 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a followup to epics-modules/asyn#171. It adds
support to the
asynNDArrayDriverandNDPluginDriverbase classes, andNDPluginROI. No changes toADDriverare needed.The core idea is that destructability is opt-in to maintain compatiblity with
derived classes that have not been updated yet, and may only be opted in by the
leaf class. And because one doesn't know whether any particular class is a leaf
class as it's always possible to create a derived class, destructability should
in practice be declared in the iocsh command that instantiates a driver. This is
how it was done for
NDPluginROI.To maintain compatibility with older versions of asyn, use of new symbols is
gated by
#ifdef ASYN_DESTRUCTIBLEwhere needed. It needs to be pointed outthat
virtual void shutdownPortDriver()does not need to be gated becausethere's no issue with adding it even with older versions of asyn as long as you
don't use the C++11
overridekeyword. Only the call into the baseasynPortDriver::shutdownPortDriver()needs to be gated.Note that I did not change the existing destruction in any way, only moved
things around. I seems to me that
~asynNDArrayDriver()is incomplete, but thatis a job for another time.
The recipe for making a driver destructible is as follows:
If the driver does not need to be compatible with older versions of asyn
(i.e., R44 or earlier), and is not (yet) further subclassed:
ASYN_DESTRUCTIBLEflag to the base constructor (i.e.,NDPluginDriveror
ADDriver).shutdownPortDriver()and put there code that needs to beexecuted with the driver intact. This is a good place to stop threads, for
example.
shutdownPortDriver()is a virtual function, so don't forget tocall the base implementation.
are actually called now, which didn't use to be the case; make use of it.
Note that
shutdownPortDriver()will only be called when the IOC shutsdown, so, if the driver could be used outside an IOC (e.g. in unit tests),
you should call
shutdownPortDriver()from the destructor. To determine ifit has already been run, call
shutdownNeeded()which will returnfalseif the shutdown has already happened.
If the driver needs to be backwards compatible:
The constructor should not add
ASYN_DESTRUCTIBLEto the flags. Instead,it should accept flags as an argument, and
ASYN_DESTRUCTIBLEshould beput there by the iocsh command that instantiates the driver. This allows
the driver to be subclassed when the derived class is not destructible.
Use of
ASYN_DESTRUCTIBLEneeds to be gated with an#ifdef.Override
shutdownPortDriver()and put there code that needs to run onIOC shutdown.
shutdownPortDriver()is a virtual function, so don'tforget to call the base implementation.
Implement the destructor. Note that newer versions of asyn will call it,
but older versions will not. So, use it to release memory and such,
but anything that needs to happen in order to disconnect from the device
must go into
shutdownPortDriver().Note that
shutdownPortDriver()will only be called when the IOC shutsdown, so, if the driver could be used outside an IOC (e.g. in unit tests),
you should call
shutdownPortDriver()from the destructor. To determine ifit has already been run, you will need to set a variable in
shudownPortDriver()yourself because theshutdownNeeded()function is onlyavailable in newer asyn versions.