This should provide a significant performance boost when creating
many thousands of CA channels. The only time it is necessary to
traverse the list is in the CAChannelProvider's destructor; when
individual channels are added or destroyed they can insert or
remove themselves from the list without having to do a search.
Each instance of the caContext class represents a separate CA context,
so each CAChannelProvider creates one and keeps a shared_ptr to it,
making that available to its channels and channel operations. These
also take their own shared_ptr to it as well so the context cannot be
destroyed while it might be needed.
A related caContext Attach object is intended to be short-lived, and
to be allocated on the stack. When created it saves the current CA
context for the thread, replacing it from the caContext given to its
constructor. CA operations will now use the attached context. When the
Attach destructor runs it detaches the thread from the current context
(checking still has the expected value) and re-attaches the thread to
any context that was saved by the constructor.
Channel connection notifications are now handled by connectNotifier,
getDone, putDone and monitor events handled by resultNotifier.
A notifierConveyor is generic, and contains a queue and a thread.
You pass a Notification pointing to a NotifierClient to a Conveyor's
notifyClient() method, and the thread will call the client's
notifyClient() method once it reaches the front of the queue.
The conveyor threads stop when the caProvider is destroyed.
The queue stores weak pointers, so queued notifications won't prevent
client objects from being destroyed.
epicsAtExit is no longer used to call ca_context_destroy.
It is now called from the destructor for CAChannelProvider.
Several changes were made for handling errors.