use weak pointer for callbacks

This commit is contained in:
mrkraimer
2016-01-07 07:44:08 -05:00
parent ca3573291a
commit 4ac867ec0f
8 changed files with 188 additions and 96 deletions

View File

@ -23,6 +23,7 @@ using namespace epics::pvData;
using namespace epics::pvDatabase;
using std::tr1::static_pointer_cast;
using std::string;
using namespace std;
namespace epics { namespace exampleRPC {
@ -31,6 +32,7 @@ PVStructurePtr ExampleRPCService::request(
PVStructure::shared_pointer const & args
) throw (epics::pvAccess::RPCRequestException)
{
bool haveControl = pvRecord->takeControl();
if (!haveControl)
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
@ -40,22 +42,28 @@ PVStructurePtr ExampleRPCService::request(
PVDataCreatePtr pvDataCreate = getPVDataCreate();
PVStructureArrayPtr valueField = args->getSubField<PVStructureArray>("value");
if (valueField.get() == 0)
if (valueField.get() == 0) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"No structure array value field");
}
StructureConstPtr valueFieldStructure = valueField->
getStructureArray()->getStructure();
ScalarConstPtr xField = valueFieldStructure->getField<Scalar>("x");
if (xField.get() == 0 || xField->getScalarType() != pvDouble)
if (xField.get() == 0 || xField->getScalarType() != pvDouble) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field x");
}
ScalarConstPtr yField = valueFieldStructure->getField<Scalar>("y");
if (xField.get() == 0 || xField->getScalarType() != pvDouble)
if (xField.get() == 0 || xField->getScalarType() != pvDouble) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field y");
}
PVStructureArray::const_svector vals = valueField->view();
@ -89,22 +97,28 @@ void ExampleRPCServiceAsync::request(
PVDataCreatePtr pvDataCreate = getPVDataCreate();
PVStructureArrayPtr valueField = args->getSubField<PVStructureArray>("value");
if (valueField.get() == 0)
if (valueField.get() == 0) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"No structure array value field");
}
StructureConstPtr valueFieldStructure = valueField->
getStructureArray()->getStructure();
ScalarConstPtr xField = valueFieldStructure->getField<Scalar>("x");
if (xField.get() == 0 || xField->getScalarType() != pvDouble)
if (xField.get() == 0 || xField->getScalarType() != pvDouble) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field x");
}
ScalarConstPtr yField = valueFieldStructure->getField<Scalar>("y");
if (yField.get() == 0 || yField->getScalarType() != pvDouble)
if (yField.get() == 0 || yField->getScalarType() != pvDouble) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field y");
}
PVStructureArray::const_svector vals = valueField->view();

View File

@ -13,6 +13,7 @@
#include <iostream>
using namespace epics::pvData;
using namespace std;
static StructureConstPtr makeDeviceStructure()
@ -81,6 +82,14 @@ int main (int argc, char *argv[])
usage();
return 1;
}
if(argc<2)
{
std::cerr << APP_NAME << " requires at least 2 arguments."
<< std::endl;
usage();
return 1;
}
// Start the pvAccess client side.
epics::pvAccess::ClientFactory::start();

View File

@ -49,9 +49,11 @@ typedef std::tr1::shared_ptr<PVRecordStructure> PVRecordStructurePtr;
class PVRecordClient;
typedef std::tr1::shared_ptr<PVRecordClient> PVRecordClientPtr;
typedef std::tr1::weak_ptr<PVRecordClient> PVRecordClientWPtr;
class PVListener;
typedef std::tr1::shared_ptr<PVListener> PVListenerPtr;
typedef std::tr1::weak_ptr<PVListener> PVListenerWPtr;
class PVDatabase;
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
@ -249,8 +251,8 @@ private:
std::string recordName;
epics::pvData::PVStructurePtr pvStructure;
PVRecordStructurePtr pvRecordStructure;
std::list<PVListenerPtr> pvListenerList;
std::list<PVRecordClientPtr> pvRecordClientList;
std::list<PVListenerWPtr> pvListenerList;
std::list<PVRecordClientWPtr> pvRecordClientList;
epics::pvData::Mutex mutex;
std::size_t depthGroupPut;
int traceLevel;
@ -261,7 +263,7 @@ private:
// following only valid while addListener or removeListener is active.
bool isAddListener;
PVListenerPtr pvListener;
PVListenerWPtr pvListener;
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVRecord& record);
@ -339,7 +341,7 @@ private:
virtual void removeListener(PVListenerPtr const & pvListener);
void callListener();
std::list<PVListenerPtr> pvListenerList;
std::list<PVListenerWPtr> pvListenerList;
epics::pvData::PVFieldPtr pvField;
bool isStructure;
PVRecordStructurePtr parent;

View File

@ -77,22 +77,28 @@ void PVRecord::destroy()
isDestroyed = true;
pvTimeStamp.detach();
std::list<PVRecordClientPtr>::iterator clientIter;
std::list<PVRecordClientWPtr>::iterator clientIter;
while(true) {
clientIter = pvRecordClientList.begin();
if(clientIter==pvRecordClientList.end()) break;
PVRecordClientPtr client = clientIter->lock();
if(client.get()) {
unlock();
client->detach(getPtrSelf());
lock();
}
pvRecordClientList.erase(clientIter);
unlock();
(*clientIter)->detach(getPtrSelf());
lock();
}
std::list<PVListenerPtr>::iterator listenerIter;
std::list<PVListenerWPtr>::iterator listenerIter;
while(true) {
listenerIter = pvListenerList.begin();
if(listenerIter==pvListenerList.end()) break;
unlock();
(*listenerIter)->unlisten(getPtrSelf());
lock();
PVListenerPtr listener = listenerIter->lock();
if(listener.get()) {
unlock();
listener->unlisten(getPtrSelf());
lock();
}
pvListenerList.erase(listenerIter);
}
@ -200,12 +206,14 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
unlock();
return false;
}
std::list<PVRecordClientPtr>::iterator iter;
std::list<PVRecordClientWPtr>::iterator iter;
for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end();
iter++ )
{
if((*iter).get()==pvRecordClient.get()) {
PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
if(client.get()==pvRecordClient.get()) {
unlock();
return false;
}
@ -230,12 +238,14 @@ bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
unlock();
return false;
}
std::list<PVRecordClientPtr>::iterator iter;
std::list<PVRecordClientWPtr>::iterator iter;
for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end();
iter++ )
{
if((*iter).get()==pvRecordClient.get()) {
PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
if(client.get()==pvRecordClient.get()) {
pvRecordClientList.erase(iter);
unlock();
return true;
@ -260,13 +270,15 @@ void PVRecord::detachClients()
unlock();
return;
}
std::list<PVRecordClientPtr>::iterator iter;
std::list<PVRecordClientWPtr>::iterator iter;
for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end();
iter++ )
{
PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
unlock();
(*iter)->detach(getPtrSelf());
client->detach(getPtrSelf());
lock();
}
pvRecordClientList.clear();
@ -290,10 +302,12 @@ bool PVRecord::addListener(
unlock();
return false;
}
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ )
{
if((*iter).get()==pvListener.get()) {
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
if(listener.get()==pvListener.get()) {
unlock();
return false;
}
@ -314,10 +328,12 @@ bool PVRecord::addListener(
void PVRecord::nextMasterPVField(PVFieldPtr const & pvField)
{
PVRecordFieldPtr pvRecordField = findPVRecordField(pvField);
if(isAddListener) {
pvRecordField->addListener(pvListener);
PVListenerPtr listener = pvListener.lock();
if(!listener.get()) return;
if(isAddListener) {
pvRecordField->addListener(listener);
} else {
pvRecordField->removeListener(pvListener);
pvRecordField->removeListener(listener);
}
}
@ -334,15 +350,17 @@ bool PVRecord::removeListener(
unlock();
return false;
}
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ )
{
if((*iter).get()==pvListener.get()) {
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
if(listener.get()==pvListener.get()) {
pvListenerList.erase(iter);
this->pvListener = pvListener;
isAddListener = false;
pvCopy->traverseMaster(getPtrSelf());
this->pvListener = PVListenerPtr();;
this->pvListener = PVListenerPtr();
unlock();
return true;
}
@ -361,10 +379,12 @@ void PVRecord::beginGroupPut()
if(traceLevel>2) {
cout << "PVRecord::beginGroupPut() " << recordName << endl;
}
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
{
(*iter).get()->beginGroupPut(getPtrSelf());
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
listener->beginGroupPut(getPtrSelf());
}
}
@ -374,10 +394,12 @@ void PVRecord::endGroupPut()
if(traceLevel>2) {
cout << "PVRecord::endGroupPut() " << recordName << endl;
}
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
{
(*iter).get()->endGroupPut(getPtrSelf());
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
listener->endGroupPut(getPtrSelf());
}
}
@ -449,9 +471,11 @@ bool PVRecordField::addListener(PVListenerPtr const & pvListener)
if(pvRecord->getTraceLevel()>1) {
cout << "PVRecordField::addListener() " << getFullName() << endl;
}
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
if((*iter).get()==pvListener.get()) {
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
if(listener.get()==pvListener.get()) {
return false;
}
}
@ -464,9 +488,11 @@ void PVRecordField::removeListener(PVListenerPtr const & pvListener)
if(pvRecord->getTraceLevel()>1) {
cout << "PVRecordField::removeListener() " << getFullName() << endl;
}
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
if((*iter).get()==pvListener.get()) {
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
if(listener.get()==pvListener.get()) {
pvListenerList.erase(iter);
return;
}
@ -484,10 +510,12 @@ void PVRecordField::postPut()
void PVRecordField::postParent(PVRecordFieldPtr const & subField)
{
PVRecordStructurePtr pvrs = static_pointer_cast<PVRecordStructure>(getPtrSelf());
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for(iter = pvListenerList.begin(); iter != pvListenerList.end(); ++iter)
{
(*iter)->dataPut(pvrs,subField);
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
listener->dataPut(pvrs,subField);
}
if(parent) parent->postParent(subField);
}
@ -507,9 +535,11 @@ void PVRecordField::postSubField()
void PVRecordField::callListener()
{
std::list<PVListenerPtr>::iterator iter;
std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
(*iter)->dataPut(getPtrSelf());
PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
listener->dataPut(getPtrSelf());
}
}

View File

@ -129,7 +129,7 @@ private:
}
bool isDestroyed;
ChannelLocalPtr channelLocal;
ChannelProcessRequester::shared_pointer channelProcessRequester;
ChannelProcessRequester::weak_pointer channelProcessRequester;
PVRecordPtr pvRecord;
int nProcess;
Mutex mutex;
@ -192,8 +192,10 @@ void ChannelProcessLocal::destroy()
void ChannelProcessLocal::process()
{
ChannelProcessRequester::shared_pointer requester = channelProcessRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelProcessRequester->processDone(channelDestroyedStatus,getPtrSelf());
requester->processDone(channelDestroyedStatus,getPtrSelf());
return;
}
if(pvRecord->getTraceLevel()>1)
@ -213,7 +215,7 @@ void ChannelProcessLocal::process()
}
pvRecord->unlock();
}
channelProcessRequester->processDone(Status::Ok,getPtrSelf());
requester->processDone(Status::Ok,getPtrSelf());
}
class ChannelGetLocal :
@ -271,7 +273,7 @@ private:
bool isDestroyed;
bool callProcess;
ChannelLocalPtr channelLocal;
ChannelGetRequester::shared_pointer channelGetRequester;
ChannelGetRequester::weak_pointer channelGetRequester;
PVCopyPtr pvCopy;
PVStructurePtr pvStructure;
BitSetPtr bitSet;
@ -339,8 +341,10 @@ void ChannelGetLocal::destroy()
void ChannelGetLocal::get()
{
ChannelGetRequester::shared_pointer requester = channelGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelGetRequester->getDone(
requester->getDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
@ -363,7 +367,7 @@ void ChannelGetLocal::get()
bitSet->set(0);
firstTime = false;
}
channelGetRequester->getDone(
requester->getDone(
Status::Ok,
getPtrSelf(),
pvStructure,
@ -424,7 +428,7 @@ private:
bool isDestroyed;
bool callProcess;
ChannelLocalPtr channelLocal;
ChannelPutRequester::shared_pointer channelPutRequester;
ChannelPutRequester::weak_pointer channelPutRequester;
PVCopyPtr pvCopy;
PVRecordPtr pvRecord;
Mutex mutex;
@ -487,8 +491,10 @@ void ChannelPutLocal::destroy()
void ChannelPutLocal::get()
{
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelPutRequester->getDone(
requester->getDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
@ -504,7 +510,7 @@ void ChannelPutLocal::get()
throw;
}
pvRecord->unlock();
channelPutRequester->getDone(
requester->getDone(
Status::Ok,getPtrSelf(),pvStructure,bitSet);
if(pvRecord->getTraceLevel()>1)
{
@ -515,8 +521,10 @@ void ChannelPutLocal::get()
void ChannelPutLocal::put(
PVStructurePtr const &pvStructure,BitSetPtr const &bitSet)
{
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelPutRequester->putDone(channelDestroyedStatus,getPtrSelf());
requester->putDone(channelDestroyedStatus,getPtrSelf());
return;
}
pvRecord->lock();
@ -532,7 +540,7 @@ void ChannelPutLocal::put(
throw;
}
pvRecord->unlock();
channelPutRequester->putDone(Status::Ok,getPtrSelf());
requester->putDone(Status::Ok,getPtrSelf());
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelPutLocal::put" << endl;
@ -578,7 +586,7 @@ private:
ChannelPutGetLocal(
bool callProcess,
ChannelLocalPtr const &channelLocal,
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
ChannelPutGetRequester::weak_pointer const & channelPutGetRequester,
PVCopyPtr const &pvPutCopy,
PVCopyPtr const &pvGetCopy,
PVStructurePtr const&pvGetStructure,
@ -599,7 +607,7 @@ private:
bool isDestroyed;
bool callProcess;
ChannelLocalPtr channelLocal;
ChannelPutGetRequester::shared_pointer channelPutGetRequester;
ChannelPutGetRequester::weak_pointer channelPutGetRequester;
PVCopyPtr pvPutCopy;
PVCopyPtr pvGetCopy;
PVStructurePtr pvGetStructure;
@ -675,8 +683,10 @@ void ChannelPutGetLocal::destroy()
void ChannelPutGetLocal::putGet(
PVStructurePtr const &pvPutStructure,BitSetPtr const &putBitSet)
{
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelPutGetRequester->putGetDone(
requester->putGetDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
@ -693,7 +703,7 @@ void ChannelPutGetLocal::putGet(
throw;
}
pvRecord->unlock();
channelPutGetRequester->putGetDone(
requester->putGetDone(
Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
if(pvRecord->getTraceLevel()>1)
{
@ -703,8 +713,10 @@ void ChannelPutGetLocal::putGet(
void ChannelPutGetLocal::getPut()
{
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelPutGetRequester->getPutDone(
requester->getPutDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
@ -718,7 +730,7 @@ void ChannelPutGetLocal::getPut()
throw;
}
pvRecord->unlock();
channelPutGetRequester->getPutDone(
requester->getPutDone(
Status::Ok,getPtrSelf(),pvPutStructure,putBitSet);
if(pvRecord->getTraceLevel()>1)
{
@ -728,8 +740,10 @@ void ChannelPutGetLocal::getPut()
void ChannelPutGetLocal::getGet()
{
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelPutGetRequester->getGetDone(
requester->getGetDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
@ -742,7 +756,7 @@ void ChannelPutGetLocal::getGet()
throw;
}
pvRecord->unlock();
channelPutGetRequester->getGetDone(
requester->getGetDone(
Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
if(pvRecord->getTraceLevel()>1)
{
@ -793,7 +807,9 @@ public:
virtual void requestDone(Status const & status,
PVStructurePtr const & result)
{
channelRPCRequester->requestDone(status, getPtrSelf(), result);
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
if(!requester.get()) return;
requester->requestDone(status, getPtrSelf(), result);
if (isLastRequest.get())
destroy();
@ -831,7 +847,7 @@ private:
AtomicBoolean isDestroyed;
ChannelLocalPtr channelLocal;
ChannelRPCRequester::shared_pointer channelRPCRequester;
ChannelRPCRequester::weak_pointer channelRPCRequester;
Service::shared_pointer service;
PVRecordPtr pvRecord;
AtomicBoolean isLastRequest;
@ -901,8 +917,8 @@ void ChannelRPCLocal::processRequest(
{
status = Status(Status::STATUSTYPE_FATAL, "RPCService.request(PVStructure) returned null.");
}
channelRPCRequester->requestDone(status, getPtrSelf(), result);
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
if(requester.get()) requester->requestDone(status, getPtrSelf(), result);
if (isLastRequest.get())
destroy();
@ -920,9 +936,8 @@ void ChannelRPCLocal::processRequest(
{
// handle user unexpected errors
Status errorStatus(Status::STATUSTYPE_FATAL, ex.what());
channelRPCRequester->requestDone(errorStatus, getPtrSelf(), PVStructurePtr());
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
if(requester.get()) requester->requestDone(errorStatus, getPtrSelf(), PVStructurePtr());
if (isLastRequest.get())
destroy();
}
@ -931,8 +946,8 @@ void ChannelRPCLocal::processRequest(
// handle user unexpected errors
Status errorStatus(Status::STATUSTYPE_FATAL,
"Unexpected exception caught while calling RPCServiceAsync.request(PVStructure, RPCResponseCallback).");
channelRPCRequester->requestDone(errorStatus, shared_from_this(), PVStructurePtr());
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
if(requester.get()) requester->requestDone(errorStatus, shared_from_this(), PVStructurePtr());
if (isLastRequest.get())
destroy();
@ -1032,7 +1047,7 @@ private:
}
bool isDestroyed;
ChannelLocalPtr channelLocal;
ChannelArrayRequester::shared_pointer channelArrayRequester;
ChannelArrayRequester::weak_pointer channelArrayRequester;
PVArrayPtr pvArray;
PVArrayPtr pvCopy;
PVRecordPtr pvRecord;
@ -1141,8 +1156,10 @@ void ChannelArrayLocal::destroy()
void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
{
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelArrayRequester->getArrayDone(channelDestroyedStatus,getPtrSelf(),pvCopy);
requester->getArrayDone(channelDestroyedStatus,getPtrSelf(),pvCopy);
return;
}
if(pvRecord->getTraceLevel()>1)
@ -1150,11 +1167,11 @@ void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
cout << "ChannelArrayLocal::getArray" << endl;
}
if(offset<0) {
channelArrayRequester->getArrayDone(illegalOffsetStatus,getPtrSelf(),pvCopy);
requester->getArrayDone(illegalOffsetStatus,getPtrSelf(),pvCopy);
return;
}
if(stride<0) {
channelArrayRequester->getArrayDone(illegalStrideStatus,getPtrSelf(),pvCopy);
requester->getArrayDone(illegalStrideStatus,getPtrSelf(),pvCopy);
return;
}
const char *exceptionMessage = NULL;
@ -1186,14 +1203,16 @@ void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
}
channelArrayRequester->getArrayDone(status,getPtrSelf(),pvCopy);
requester->getArrayDone(status,getPtrSelf(),pvCopy);
}
void ChannelArrayLocal::putArray(
PVArrayPtr const & pvArray, size_t offset, size_t count, size_t stride)
{
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelArrayRequester->putArrayDone(channelDestroyedStatus,getPtrSelf());
requester->putArrayDone(channelDestroyedStatus,getPtrSelf());
return;
}
if(pvRecord->getTraceLevel()>1)
@ -1201,15 +1220,15 @@ void ChannelArrayLocal::putArray(
cout << "ChannelArrayLocal::putArray" << endl;
}
if(offset<0) {
channelArrayRequester->putArrayDone(illegalOffsetStatus,getPtrSelf());
requester->putArrayDone(illegalOffsetStatus,getPtrSelf());
return;
}
if(count<0) {
channelArrayRequester->putArrayDone(illegalCountStatus,getPtrSelf());
requester->putArrayDone(illegalCountStatus,getPtrSelf());
return;
}
if(stride<0) {
channelArrayRequester->putArrayDone(illegalStrideStatus,getPtrSelf());
requester->putArrayDone(illegalStrideStatus,getPtrSelf());
return;
}
size_t newLength = offset + count*stride;
@ -1226,11 +1245,13 @@ void ChannelArrayLocal::putArray(
if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
}
channelArrayRequester->putArrayDone(status,getPtrSelf());
requester->putArrayDone(status,getPtrSelf());
}
void ChannelArrayLocal::getLength()
{
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
size_t length = 0;
const char *exceptionMessage = NULL;
pvRecord->lock();
@ -1244,13 +1265,15 @@ void ChannelArrayLocal::getLength()
if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
}
channelArrayRequester->getLengthDone(status,getPtrSelf(),length);
requester->getLengthDone(status,getPtrSelf(),length);
}
void ChannelArrayLocal::setLength(size_t length)
{
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
if(isDestroyed) {
channelArrayRequester->setLengthDone(channelDestroyedStatus,getPtrSelf());
requester->setLengthDone(channelDestroyedStatus,getPtrSelf());
return;
}
if(pvRecord->getTraceLevel()>1)
@ -1267,7 +1290,7 @@ void ChannelArrayLocal::setLength(size_t length)
throw;
}
pvRecord->unlock();
channelArrayRequester->setLengthDone(Status::Ok,getPtrSelf());
requester->setLengthDone(Status::Ok,getPtrSelf());
}
@ -1315,14 +1338,18 @@ void ChannelLocal::detach(PVRecordPtr const & pvRecord)
string ChannelLocal::getRequesterName()
{
return requester->getRequesterName();
ChannelRequester::shared_pointer req = requester.lock();
if(!req.get()) return string();
return req->getRequesterName();
}
void ChannelLocal::message(
string const &message,
MessageType messageType)
{
requester->message(message,messageType);
ChannelRequester::shared_pointer req = requester.lock();
if(!req.get()) return;
req->message(message,messageType);
}
string ChannelLocal::getRemoteAddress()
@ -1344,7 +1371,7 @@ string ChannelLocal::getChannelName()
ChannelRequester::shared_pointer ChannelLocal::getChannelRequester()
{
return requester;
return requester.lock();
}
bool ChannelLocal::isConnected()

View File

@ -394,7 +394,7 @@ protected:
}
private:
ChannelProviderLocalPtr provider;
epics::pvAccess::ChannelRequester::shared_pointer requester;
epics::pvAccess::ChannelRequester::weak_pointer requester;
PVRecordPtr pvRecord;
bool beingDestroyed;
epics::pvData::Mutex mutex;

View File

@ -41,6 +41,7 @@ static Status notStartedStatus(Status::STATUSTYPE_ERROR,"not started");
typedef Queue<MonitorElement> MonitorElementQueue;
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
typedef std::tr1::shared_ptr<MonitorRequester> MonitorRequesterPtr;
@ -78,7 +79,7 @@ private:
{
return shared_from_this();
}
MonitorRequester::shared_pointer monitorRequester;
MonitorRequester::weak_pointer monitorRequester;
PVRecordPtr pvRecord;
MonitorState state;
PVCopyPtr pvCopy;
@ -221,7 +222,9 @@ void MonitorLocal::releaseActiveElement()
activeElement->changedBitSet->clear();
activeElement->overrunBitSet->clear();
}
monitorRequester->monitorEvent(getPtrSelf());
MonitorRequesterPtr requester = monitorRequester.lock();
if(!requester.get()) return;
requester->monitorEvent(getPtrSelf());
return;
}
@ -323,6 +326,8 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
PVFieldPtr pvField;
size_t queueSize = 2;
PVStructurePtr pvOptions = pvRequest->getSubField<PVStructure>("record._options");
MonitorRequesterPtr requester = monitorRequester.lock();
if(!requester.get()) return false;
if(pvOptions) {
PVStringPtr pvString = pvOptions->getSubField<PVString>("queueSize");
if(pvString) {
@ -333,7 +338,7 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
ss >> size;
queueSize = size;
} catch (...) {
monitorRequester->message("queueSize " +pvString->get() + " illegal",errorMessage);
requester->message("queueSize " +pvString->get() + " illegal",errorMessage);
return false;
}
}
@ -344,19 +349,19 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,"");
if(!pvCopy) {
monitorRequester->message("illegal pvRequest",errorMessage);
requester->message("illegal pvRequest",errorMessage);
return false;
}
} else {
if(pvField->getField()->getType()!=structure) {
monitorRequester->message("illegal pvRequest",errorMessage);
requester->message("illegal pvRequest",errorMessage);
return false;
}
pvCopy = PVCopy::create(
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,"field");
if(!pvCopy) {
monitorRequester->message("illegal pvRequest",errorMessage);
requester->message("illegal pvRequest",errorMessage);
return false;
}
}
@ -370,7 +375,7 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
monitorElementArray.push_back(monitorElement);
}
queue = MonitorElementQueuePtr(new MonitorElementQueue(monitorElementArray));
monitorRequester->monitorConnect(
requester->monitorConnect(
Status::Ok,
getPtrSelf(),
pvCopy->getStructure());

View File

@ -26,6 +26,7 @@
#include <epicsThread.h>
#include <iocsh.h>
#include <shareLib.h>
#include <epicsExit.h>
#include <pv/pvAccess.h>
#include <pv/serverContext.h>
@ -52,6 +53,9 @@ extern "C" void pvdbl(const iocshArgBuf *args)
for(size_t i=0; i<xxx.size(); ++i) cout<< xxx[i] << endl;
}
static void channelProviderLocalExitHandler(void* /*pPrivate*/) {
getChannelProviderLocal()->destroy();
}
static void registerChannelProviderLocal(void)
{
@ -60,6 +64,7 @@ static void registerChannelProviderLocal(void)
firstTime = 0;
iocshRegister(&pvdblFuncDef, pvdbl);
getChannelProviderLocal();
epicsAtExit(channelProviderLocalExitHandler, NULL);
}
}