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
+20 -6
View File
@@ -23,6 +23,7 @@ using namespace epics::pvData;
using namespace epics::pvDatabase; using namespace epics::pvDatabase;
using std::tr1::static_pointer_cast; using std::tr1::static_pointer_cast;
using std::string; using std::string;
using namespace std;
namespace epics { namespace exampleRPC { namespace epics { namespace exampleRPC {
@@ -31,6 +32,7 @@ PVStructurePtr ExampleRPCService::request(
PVStructure::shared_pointer const & args PVStructure::shared_pointer const & args
) throw (epics::pvAccess::RPCRequestException) ) throw (epics::pvAccess::RPCRequestException)
{ {
bool haveControl = pvRecord->takeControl(); bool haveControl = pvRecord->takeControl();
if (!haveControl) if (!haveControl)
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
@@ -40,22 +42,28 @@ PVStructurePtr ExampleRPCService::request(
PVDataCreatePtr pvDataCreate = getPVDataCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate();
PVStructureArrayPtr valueField = args->getSubField<PVStructureArray>("value"); PVStructureArrayPtr valueField = args->getSubField<PVStructureArray>("value");
if (valueField.get() == 0) if (valueField.get() == 0) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"No structure array value field"); "No structure array value field");
}
StructureConstPtr valueFieldStructure = valueField-> StructureConstPtr valueFieldStructure = valueField->
getStructureArray()->getStructure(); getStructureArray()->getStructure();
ScalarConstPtr xField = valueFieldStructure->getField<Scalar>("x"); 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, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field x"); "value field's structure has no double field x");
}
ScalarConstPtr yField = valueFieldStructure->getField<Scalar>("y"); 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, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field y"); "value field's structure has no double field y");
}
PVStructureArray::const_svector vals = valueField->view(); PVStructureArray::const_svector vals = valueField->view();
@@ -89,22 +97,28 @@ void ExampleRPCServiceAsync::request(
PVDataCreatePtr pvDataCreate = getPVDataCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate();
PVStructureArrayPtr valueField = args->getSubField<PVStructureArray>("value"); PVStructureArrayPtr valueField = args->getSubField<PVStructureArray>("value");
if (valueField.get() == 0) if (valueField.get() == 0) {
pvRecord->releaseControl();
throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"No structure array value field"); "No structure array value field");
}
StructureConstPtr valueFieldStructure = valueField-> StructureConstPtr valueFieldStructure = valueField->
getStructureArray()->getStructure(); getStructureArray()->getStructure();
ScalarConstPtr xField = valueFieldStructure->getField<Scalar>("x"); 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, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field x"); "value field's structure has no double field x");
}
ScalarConstPtr yField = valueFieldStructure->getField<Scalar>("y"); 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, throw pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR,
"value field's structure has no double field y"); "value field's structure has no double field y");
}
PVStructureArray::const_svector vals = valueField->view(); PVStructureArray::const_svector vals = valueField->view();
+9
View File
@@ -13,6 +13,7 @@
#include <iostream> #include <iostream>
using namespace epics::pvData; using namespace epics::pvData;
using namespace std;
static StructureConstPtr makeDeviceStructure() static StructureConstPtr makeDeviceStructure()
@@ -81,6 +82,14 @@ int main (int argc, char *argv[])
usage(); usage();
return 1; return 1;
} }
if(argc<2)
{
std::cerr << APP_NAME << " requires at least 2 arguments."
<< std::endl;
usage();
return 1;
}
// Start the pvAccess client side. // Start the pvAccess client side.
epics::pvAccess::ClientFactory::start(); epics::pvAccess::ClientFactory::start();
+6 -4
View File
@@ -49,9 +49,11 @@ typedef std::tr1::shared_ptr<PVRecordStructure> PVRecordStructurePtr;
class PVRecordClient; class PVRecordClient;
typedef std::tr1::shared_ptr<PVRecordClient> PVRecordClientPtr; typedef std::tr1::shared_ptr<PVRecordClient> PVRecordClientPtr;
typedef std::tr1::weak_ptr<PVRecordClient> PVRecordClientWPtr;
class PVListener; class PVListener;
typedef std::tr1::shared_ptr<PVListener> PVListenerPtr; typedef std::tr1::shared_ptr<PVListener> PVListenerPtr;
typedef std::tr1::weak_ptr<PVListener> PVListenerWPtr;
class PVDatabase; class PVDatabase;
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr; typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
@@ -249,8 +251,8 @@ private:
std::string recordName; std::string recordName;
epics::pvData::PVStructurePtr pvStructure; epics::pvData::PVStructurePtr pvStructure;
PVRecordStructurePtr pvRecordStructure; PVRecordStructurePtr pvRecordStructure;
std::list<PVListenerPtr> pvListenerList; std::list<PVListenerWPtr> pvListenerList;
std::list<PVRecordClientPtr> pvRecordClientList; std::list<PVRecordClientWPtr> pvRecordClientList;
epics::pvData::Mutex mutex; epics::pvData::Mutex mutex;
std::size_t depthGroupPut; std::size_t depthGroupPut;
int traceLevel; int traceLevel;
@@ -261,7 +263,7 @@ private:
// following only valid while addListener or removeListener is active. // following only valid while addListener or removeListener is active.
bool isAddListener; bool isAddListener;
PVListenerPtr pvListener; PVListenerWPtr pvListener;
}; };
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVRecord& record); epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVRecord& record);
@@ -339,7 +341,7 @@ private:
virtual void removeListener(PVListenerPtr const & pvListener); virtual void removeListener(PVListenerPtr const & pvListener);
void callListener(); void callListener();
std::list<PVListenerPtr> pvListenerList; std::list<PVListenerWPtr> pvListenerList;
epics::pvData::PVFieldPtr pvField; epics::pvData::PVFieldPtr pvField;
bool isStructure; bool isStructure;
PVRecordStructurePtr parent; PVRecordStructurePtr parent;
+63 -33
View File
@@ -77,22 +77,28 @@ void PVRecord::destroy()
isDestroyed = true; isDestroyed = true;
pvTimeStamp.detach(); pvTimeStamp.detach();
std::list<PVRecordClientPtr>::iterator clientIter; std::list<PVRecordClientWPtr>::iterator clientIter;
while(true) { while(true) {
clientIter = pvRecordClientList.begin(); clientIter = pvRecordClientList.begin();
if(clientIter==pvRecordClientList.end()) break; if(clientIter==pvRecordClientList.end()) break;
PVRecordClientPtr client = clientIter->lock();
if(client.get()) {
unlock();
client->detach(getPtrSelf());
lock();
}
pvRecordClientList.erase(clientIter); pvRecordClientList.erase(clientIter);
unlock();
(*clientIter)->detach(getPtrSelf());
lock();
} }
std::list<PVListenerPtr>::iterator listenerIter; std::list<PVListenerWPtr>::iterator listenerIter;
while(true) { while(true) {
listenerIter = pvListenerList.begin(); listenerIter = pvListenerList.begin();
if(listenerIter==pvListenerList.end()) break; if(listenerIter==pvListenerList.end()) break;
unlock(); PVListenerPtr listener = listenerIter->lock();
(*listenerIter)->unlisten(getPtrSelf()); if(listener.get()) {
lock(); unlock();
listener->unlisten(getPtrSelf());
lock();
}
pvListenerList.erase(listenerIter); pvListenerList.erase(listenerIter);
} }
@@ -200,12 +206,14 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
unlock(); unlock();
return false; return false;
} }
std::list<PVRecordClientPtr>::iterator iter; std::list<PVRecordClientWPtr>::iterator iter;
for (iter = pvRecordClientList.begin(); for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end(); iter!=pvRecordClientList.end();
iter++ ) iter++ )
{ {
if((*iter).get()==pvRecordClient.get()) { PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
if(client.get()==pvRecordClient.get()) {
unlock(); unlock();
return false; return false;
} }
@@ -230,12 +238,14 @@ bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
unlock(); unlock();
return false; return false;
} }
std::list<PVRecordClientPtr>::iterator iter; std::list<PVRecordClientWPtr>::iterator iter;
for (iter = pvRecordClientList.begin(); for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end(); iter!=pvRecordClientList.end();
iter++ ) iter++ )
{ {
if((*iter).get()==pvRecordClient.get()) { PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
if(client.get()==pvRecordClient.get()) {
pvRecordClientList.erase(iter); pvRecordClientList.erase(iter);
unlock(); unlock();
return true; return true;
@@ -260,13 +270,15 @@ void PVRecord::detachClients()
unlock(); unlock();
return; return;
} }
std::list<PVRecordClientPtr>::iterator iter; std::list<PVRecordClientWPtr>::iterator iter;
for (iter = pvRecordClientList.begin(); for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end(); iter!=pvRecordClientList.end();
iter++ ) iter++ )
{ {
PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
unlock(); unlock();
(*iter)->detach(getPtrSelf()); client->detach(getPtrSelf());
lock(); lock();
} }
pvRecordClientList.clear(); pvRecordClientList.clear();
@@ -290,10 +302,12 @@ bool PVRecord::addListener(
unlock(); unlock();
return false; return false;
} }
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); 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(); unlock();
return false; return false;
} }
@@ -314,10 +328,12 @@ bool PVRecord::addListener(
void PVRecord::nextMasterPVField(PVFieldPtr const & pvField) void PVRecord::nextMasterPVField(PVFieldPtr const & pvField)
{ {
PVRecordFieldPtr pvRecordField = findPVRecordField(pvField); PVRecordFieldPtr pvRecordField = findPVRecordField(pvField);
PVListenerPtr listener = pvListener.lock();
if(!listener.get()) return;
if(isAddListener) { if(isAddListener) {
pvRecordField->addListener(pvListener); pvRecordField->addListener(listener);
} else { } else {
pvRecordField->removeListener(pvListener); pvRecordField->removeListener(listener);
} }
} }
@@ -334,15 +350,17 @@ bool PVRecord::removeListener(
unlock(); unlock();
return false; return false;
} }
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); 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); pvListenerList.erase(iter);
this->pvListener = pvListener; this->pvListener = pvListener;
isAddListener = false; isAddListener = false;
pvCopy->traverseMaster(getPtrSelf()); pvCopy->traverseMaster(getPtrSelf());
this->pvListener = PVListenerPtr();; this->pvListener = PVListenerPtr();
unlock(); unlock();
return true; return true;
} }
@@ -361,10 +379,12 @@ void PVRecord::beginGroupPut()
if(traceLevel>2) { if(traceLevel>2) {
cout << "PVRecord::beginGroupPut() " << recordName << endl; cout << "PVRecord::beginGroupPut() " << recordName << endl;
} }
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); 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) { if(traceLevel>2) {
cout << "PVRecord::endGroupPut() " << recordName << endl; cout << "PVRecord::endGroupPut() " << recordName << endl;
} }
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); 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) { if(pvRecord->getTraceLevel()>1) {
cout << "PVRecordField::addListener() " << getFullName() << endl; cout << "PVRecordField::addListener() " << getFullName() << endl;
} }
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); 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; return false;
} }
} }
@@ -464,9 +488,11 @@ void PVRecordField::removeListener(PVListenerPtr const & pvListener)
if(pvRecord->getTraceLevel()>1) { if(pvRecord->getTraceLevel()>1) {
cout << "PVRecordField::removeListener() " << getFullName() << endl; cout << "PVRecordField::removeListener() " << getFullName() << endl;
} }
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); 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); pvListenerList.erase(iter);
return; return;
} }
@@ -484,10 +510,12 @@ void PVRecordField::postPut()
void PVRecordField::postParent(PVRecordFieldPtr const & subField) void PVRecordField::postParent(PVRecordFieldPtr const & subField)
{ {
PVRecordStructurePtr pvrs = static_pointer_cast<PVRecordStructure>(getPtrSelf()); 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) 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); if(parent) parent->postParent(subField);
} }
@@ -507,9 +535,11 @@ void PVRecordField::postSubField()
void PVRecordField::callListener() void PVRecordField::callListener()
{ {
std::list<PVListenerPtr>::iterator iter; std::list<PVListenerWPtr>::iterator iter;
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) { for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
(*iter)->dataPut(getPtrSelf()); PVListenerPtr listener = iter->lock();
if(!listener.get()) continue;
listener->dataPut(getPtrSelf());
} }
} }
+71 -44
View File
@@ -129,7 +129,7 @@ private:
} }
bool isDestroyed; bool isDestroyed;
ChannelLocalPtr channelLocal; ChannelLocalPtr channelLocal;
ChannelProcessRequester::shared_pointer channelProcessRequester; ChannelProcessRequester::weak_pointer channelProcessRequester;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
int nProcess; int nProcess;
Mutex mutex; Mutex mutex;
@@ -192,8 +192,10 @@ void ChannelProcessLocal::destroy()
void ChannelProcessLocal::process() void ChannelProcessLocal::process()
{ {
ChannelProcessRequester::shared_pointer requester = channelProcessRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelProcessRequester->processDone(channelDestroyedStatus,getPtrSelf()); requester->processDone(channelDestroyedStatus,getPtrSelf());
return; return;
} }
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
@@ -213,7 +215,7 @@ void ChannelProcessLocal::process()
} }
pvRecord->unlock(); pvRecord->unlock();
} }
channelProcessRequester->processDone(Status::Ok,getPtrSelf()); requester->processDone(Status::Ok,getPtrSelf());
} }
class ChannelGetLocal : class ChannelGetLocal :
@@ -271,7 +273,7 @@ private:
bool isDestroyed; bool isDestroyed;
bool callProcess; bool callProcess;
ChannelLocalPtr channelLocal; ChannelLocalPtr channelLocal;
ChannelGetRequester::shared_pointer channelGetRequester; ChannelGetRequester::weak_pointer channelGetRequester;
PVCopyPtr pvCopy; PVCopyPtr pvCopy;
PVStructurePtr pvStructure; PVStructurePtr pvStructure;
BitSetPtr bitSet; BitSetPtr bitSet;
@@ -339,8 +341,10 @@ void ChannelGetLocal::destroy()
void ChannelGetLocal::get() void ChannelGetLocal::get()
{ {
ChannelGetRequester::shared_pointer requester = channelGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelGetRequester->getDone( requester->getDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet); channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return; return;
} }
@@ -363,7 +367,7 @@ void ChannelGetLocal::get()
bitSet->set(0); bitSet->set(0);
firstTime = false; firstTime = false;
} }
channelGetRequester->getDone( requester->getDone(
Status::Ok, Status::Ok,
getPtrSelf(), getPtrSelf(),
pvStructure, pvStructure,
@@ -424,7 +428,7 @@ private:
bool isDestroyed; bool isDestroyed;
bool callProcess; bool callProcess;
ChannelLocalPtr channelLocal; ChannelLocalPtr channelLocal;
ChannelPutRequester::shared_pointer channelPutRequester; ChannelPutRequester::weak_pointer channelPutRequester;
PVCopyPtr pvCopy; PVCopyPtr pvCopy;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
Mutex mutex; Mutex mutex;
@@ -487,8 +491,10 @@ void ChannelPutLocal::destroy()
void ChannelPutLocal::get() void ChannelPutLocal::get()
{ {
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelPutRequester->getDone( requester->getDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet); channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return; return;
} }
@@ -504,7 +510,7 @@ void ChannelPutLocal::get()
throw; throw;
} }
pvRecord->unlock(); pvRecord->unlock();
channelPutRequester->getDone( requester->getDone(
Status::Ok,getPtrSelf(),pvStructure,bitSet); Status::Ok,getPtrSelf(),pvStructure,bitSet);
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
@@ -515,8 +521,10 @@ void ChannelPutLocal::get()
void ChannelPutLocal::put( void ChannelPutLocal::put(
PVStructurePtr const &pvStructure,BitSetPtr const &bitSet) PVStructurePtr const &pvStructure,BitSetPtr const &bitSet)
{ {
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelPutRequester->putDone(channelDestroyedStatus,getPtrSelf()); requester->putDone(channelDestroyedStatus,getPtrSelf());
return; return;
} }
pvRecord->lock(); pvRecord->lock();
@@ -532,7 +540,7 @@ void ChannelPutLocal::put(
throw; throw;
} }
pvRecord->unlock(); pvRecord->unlock();
channelPutRequester->putDone(Status::Ok,getPtrSelf()); requester->putDone(Status::Ok,getPtrSelf());
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "ChannelPutLocal::put" << endl; cout << "ChannelPutLocal::put" << endl;
@@ -578,7 +586,7 @@ private:
ChannelPutGetLocal( ChannelPutGetLocal(
bool callProcess, bool callProcess,
ChannelLocalPtr const &channelLocal, ChannelLocalPtr const &channelLocal,
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester, ChannelPutGetRequester::weak_pointer const & channelPutGetRequester,
PVCopyPtr const &pvPutCopy, PVCopyPtr const &pvPutCopy,
PVCopyPtr const &pvGetCopy, PVCopyPtr const &pvGetCopy,
PVStructurePtr const&pvGetStructure, PVStructurePtr const&pvGetStructure,
@@ -599,7 +607,7 @@ private:
bool isDestroyed; bool isDestroyed;
bool callProcess; bool callProcess;
ChannelLocalPtr channelLocal; ChannelLocalPtr channelLocal;
ChannelPutGetRequester::shared_pointer channelPutGetRequester; ChannelPutGetRequester::weak_pointer channelPutGetRequester;
PVCopyPtr pvPutCopy; PVCopyPtr pvPutCopy;
PVCopyPtr pvGetCopy; PVCopyPtr pvGetCopy;
PVStructurePtr pvGetStructure; PVStructurePtr pvGetStructure;
@@ -675,8 +683,10 @@ void ChannelPutGetLocal::destroy()
void ChannelPutGetLocal::putGet( void ChannelPutGetLocal::putGet(
PVStructurePtr const &pvPutStructure,BitSetPtr const &putBitSet) PVStructurePtr const &pvPutStructure,BitSetPtr const &putBitSet)
{ {
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelPutGetRequester->putGetDone( requester->putGetDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet); channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return; return;
} }
@@ -693,7 +703,7 @@ void ChannelPutGetLocal::putGet(
throw; throw;
} }
pvRecord->unlock(); pvRecord->unlock();
channelPutGetRequester->putGetDone( requester->putGetDone(
Status::Ok,getPtrSelf(),pvGetStructure,getBitSet); Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
@@ -703,8 +713,10 @@ void ChannelPutGetLocal::putGet(
void ChannelPutGetLocal::getPut() void ChannelPutGetLocal::getPut()
{ {
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelPutGetRequester->getPutDone( requester->getPutDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet); channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return; return;
} }
@@ -718,7 +730,7 @@ void ChannelPutGetLocal::getPut()
throw; throw;
} }
pvRecord->unlock(); pvRecord->unlock();
channelPutGetRequester->getPutDone( requester->getPutDone(
Status::Ok,getPtrSelf(),pvPutStructure,putBitSet); Status::Ok,getPtrSelf(),pvPutStructure,putBitSet);
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
@@ -728,8 +740,10 @@ void ChannelPutGetLocal::getPut()
void ChannelPutGetLocal::getGet() void ChannelPutGetLocal::getGet()
{ {
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelPutGetRequester->getGetDone( requester->getGetDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet); channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return; return;
} }
@@ -742,7 +756,7 @@ void ChannelPutGetLocal::getGet()
throw; throw;
} }
pvRecord->unlock(); pvRecord->unlock();
channelPutGetRequester->getGetDone( requester->getGetDone(
Status::Ok,getPtrSelf(),pvGetStructure,getBitSet); Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
@@ -793,7 +807,9 @@ public:
virtual void requestDone(Status const & status, virtual void requestDone(Status const & status,
PVStructurePtr const & result) 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()) if (isLastRequest.get())
destroy(); destroy();
@@ -831,7 +847,7 @@ private:
AtomicBoolean isDestroyed; AtomicBoolean isDestroyed;
ChannelLocalPtr channelLocal; ChannelLocalPtr channelLocal;
ChannelRPCRequester::shared_pointer channelRPCRequester; ChannelRPCRequester::weak_pointer channelRPCRequester;
Service::shared_pointer service; Service::shared_pointer service;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
AtomicBoolean isLastRequest; AtomicBoolean isLastRequest;
@@ -901,8 +917,8 @@ void ChannelRPCLocal::processRequest(
{ {
status = Status(Status::STATUSTYPE_FATAL, "RPCService.request(PVStructure) returned null."); status = Status(Status::STATUSTYPE_FATAL, "RPCService.request(PVStructure) returned null.");
} }
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
channelRPCRequester->requestDone(status, getPtrSelf(), result); if(requester.get()) requester->requestDone(status, getPtrSelf(), result);
if (isLastRequest.get()) if (isLastRequest.get())
destroy(); destroy();
@@ -920,9 +936,8 @@ void ChannelRPCLocal::processRequest(
{ {
// handle user unexpected errors // handle user unexpected errors
Status errorStatus(Status::STATUSTYPE_FATAL, ex.what()); Status errorStatus(Status::STATUSTYPE_FATAL, ex.what());
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
channelRPCRequester->requestDone(errorStatus, getPtrSelf(), PVStructurePtr()); if(requester.get()) requester->requestDone(errorStatus, getPtrSelf(), PVStructurePtr());
if (isLastRequest.get()) if (isLastRequest.get())
destroy(); destroy();
} }
@@ -931,8 +946,8 @@ void ChannelRPCLocal::processRequest(
// handle user unexpected errors // handle user unexpected errors
Status errorStatus(Status::STATUSTYPE_FATAL, Status errorStatus(Status::STATUSTYPE_FATAL,
"Unexpected exception caught while calling RPCServiceAsync.request(PVStructure, RPCResponseCallback)."); "Unexpected exception caught while calling RPCServiceAsync.request(PVStructure, RPCResponseCallback).");
ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
channelRPCRequester->requestDone(errorStatus, shared_from_this(), PVStructurePtr()); if(requester.get()) requester->requestDone(errorStatus, shared_from_this(), PVStructurePtr());
if (isLastRequest.get()) if (isLastRequest.get())
destroy(); destroy();
@@ -1032,7 +1047,7 @@ private:
} }
bool isDestroyed; bool isDestroyed;
ChannelLocalPtr channelLocal; ChannelLocalPtr channelLocal;
ChannelArrayRequester::shared_pointer channelArrayRequester; ChannelArrayRequester::weak_pointer channelArrayRequester;
PVArrayPtr pvArray; PVArrayPtr pvArray;
PVArrayPtr pvCopy; PVArrayPtr pvCopy;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
@@ -1141,8 +1156,10 @@ void ChannelArrayLocal::destroy()
void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride) void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
{ {
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelArrayRequester->getArrayDone(channelDestroyedStatus,getPtrSelf(),pvCopy); requester->getArrayDone(channelDestroyedStatus,getPtrSelf(),pvCopy);
return; return;
} }
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
@@ -1150,11 +1167,11 @@ void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
cout << "ChannelArrayLocal::getArray" << endl; cout << "ChannelArrayLocal::getArray" << endl;
} }
if(offset<0) { if(offset<0) {
channelArrayRequester->getArrayDone(illegalOffsetStatus,getPtrSelf(),pvCopy); requester->getArrayDone(illegalOffsetStatus,getPtrSelf(),pvCopy);
return; return;
} }
if(stride<0) { if(stride<0) {
channelArrayRequester->getArrayDone(illegalStrideStatus,getPtrSelf(),pvCopy); requester->getArrayDone(illegalStrideStatus,getPtrSelf(),pvCopy);
return; return;
} }
const char *exceptionMessage = NULL; const char *exceptionMessage = NULL;
@@ -1186,14 +1203,16 @@ void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
if(exceptionMessage!=NULL) { if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage); status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
} }
channelArrayRequester->getArrayDone(status,getPtrSelf(),pvCopy); requester->getArrayDone(status,getPtrSelf(),pvCopy);
} }
void ChannelArrayLocal::putArray( void ChannelArrayLocal::putArray(
PVArrayPtr const & pvArray, size_t offset, size_t count, size_t stride) PVArrayPtr const & pvArray, size_t offset, size_t count, size_t stride)
{ {
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelArrayRequester->putArrayDone(channelDestroyedStatus,getPtrSelf()); requester->putArrayDone(channelDestroyedStatus,getPtrSelf());
return; return;
} }
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
@@ -1201,15 +1220,15 @@ void ChannelArrayLocal::putArray(
cout << "ChannelArrayLocal::putArray" << endl; cout << "ChannelArrayLocal::putArray" << endl;
} }
if(offset<0) { if(offset<0) {
channelArrayRequester->putArrayDone(illegalOffsetStatus,getPtrSelf()); requester->putArrayDone(illegalOffsetStatus,getPtrSelf());
return; return;
} }
if(count<0) { if(count<0) {
channelArrayRequester->putArrayDone(illegalCountStatus,getPtrSelf()); requester->putArrayDone(illegalCountStatus,getPtrSelf());
return; return;
} }
if(stride<0) { if(stride<0) {
channelArrayRequester->putArrayDone(illegalStrideStatus,getPtrSelf()); requester->putArrayDone(illegalStrideStatus,getPtrSelf());
return; return;
} }
size_t newLength = offset + count*stride; size_t newLength = offset + count*stride;
@@ -1226,11 +1245,13 @@ void ChannelArrayLocal::putArray(
if(exceptionMessage!=NULL) { if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage); status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
} }
channelArrayRequester->putArrayDone(status,getPtrSelf()); requester->putArrayDone(status,getPtrSelf());
} }
void ChannelArrayLocal::getLength() void ChannelArrayLocal::getLength()
{ {
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
size_t length = 0; size_t length = 0;
const char *exceptionMessage = NULL; const char *exceptionMessage = NULL;
pvRecord->lock(); pvRecord->lock();
@@ -1244,13 +1265,15 @@ void ChannelArrayLocal::getLength()
if(exceptionMessage!=NULL) { if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage); status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
} }
channelArrayRequester->getLengthDone(status,getPtrSelf(),length); requester->getLengthDone(status,getPtrSelf(),length);
} }
void ChannelArrayLocal::setLength(size_t length) void ChannelArrayLocal::setLength(size_t length)
{ {
ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
if(!requester.get()) return;
if(isDestroyed) { if(isDestroyed) {
channelArrayRequester->setLengthDone(channelDestroyedStatus,getPtrSelf()); requester->setLengthDone(channelDestroyedStatus,getPtrSelf());
return; return;
} }
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
@@ -1267,7 +1290,7 @@ void ChannelArrayLocal::setLength(size_t length)
throw; throw;
} }
pvRecord->unlock(); 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() string ChannelLocal::getRequesterName()
{ {
return requester->getRequesterName(); ChannelRequester::shared_pointer req = requester.lock();
if(!req.get()) return string();
return req->getRequesterName();
} }
void ChannelLocal::message( void ChannelLocal::message(
string const &message, string const &message,
MessageType messageType) MessageType messageType)
{ {
requester->message(message,messageType); ChannelRequester::shared_pointer req = requester.lock();
if(!req.get()) return;
req->message(message,messageType);
} }
string ChannelLocal::getRemoteAddress() string ChannelLocal::getRemoteAddress()
@@ -1344,7 +1371,7 @@ string ChannelLocal::getChannelName()
ChannelRequester::shared_pointer ChannelLocal::getChannelRequester() ChannelRequester::shared_pointer ChannelLocal::getChannelRequester()
{ {
return requester; return requester.lock();
} }
bool ChannelLocal::isConnected() bool ChannelLocal::isConnected()
+1 -1
View File
@@ -394,7 +394,7 @@ protected:
} }
private: private:
ChannelProviderLocalPtr provider; ChannelProviderLocalPtr provider;
epics::pvAccess::ChannelRequester::shared_pointer requester; epics::pvAccess::ChannelRequester::weak_pointer requester;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
bool beingDestroyed; bool beingDestroyed;
epics::pvData::Mutex mutex; epics::pvData::Mutex mutex;
+12 -7
View File
@@ -41,6 +41,7 @@ static Status notStartedStatus(Status::STATUSTYPE_ERROR,"not started");
typedef Queue<MonitorElement> MonitorElementQueue; typedef Queue<MonitorElement> MonitorElementQueue;
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr; typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
typedef std::tr1::shared_ptr<MonitorRequester> MonitorRequesterPtr;
@@ -78,7 +79,7 @@ private:
{ {
return shared_from_this(); return shared_from_this();
} }
MonitorRequester::shared_pointer monitorRequester; MonitorRequester::weak_pointer monitorRequester;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
MonitorState state; MonitorState state;
PVCopyPtr pvCopy; PVCopyPtr pvCopy;
@@ -221,7 +222,9 @@ void MonitorLocal::releaseActiveElement()
activeElement->changedBitSet->clear(); activeElement->changedBitSet->clear();
activeElement->overrunBitSet->clear(); activeElement->overrunBitSet->clear();
} }
monitorRequester->monitorEvent(getPtrSelf()); MonitorRequesterPtr requester = monitorRequester.lock();
if(!requester.get()) return;
requester->monitorEvent(getPtrSelf());
return; return;
} }
@@ -323,6 +326,8 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
PVFieldPtr pvField; PVFieldPtr pvField;
size_t queueSize = 2; size_t queueSize = 2;
PVStructurePtr pvOptions = pvRequest->getSubField<PVStructure>("record._options"); PVStructurePtr pvOptions = pvRequest->getSubField<PVStructure>("record._options");
MonitorRequesterPtr requester = monitorRequester.lock();
if(!requester.get()) return false;
if(pvOptions) { if(pvOptions) {
PVStringPtr pvString = pvOptions->getSubField<PVString>("queueSize"); PVStringPtr pvString = pvOptions->getSubField<PVString>("queueSize");
if(pvString) { if(pvString) {
@@ -333,7 +338,7 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
ss >> size; ss >> size;
queueSize = size; queueSize = size;
} catch (...) { } catch (...) {
monitorRequester->message("queueSize " +pvString->get() + " illegal",errorMessage); requester->message("queueSize " +pvString->get() + " illegal",errorMessage);
return false; return false;
} }
} }
@@ -344,19 +349,19 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
pvRecord->getPVRecordStructure()->getPVStructure(), pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,""); pvRequest,"");
if(!pvCopy) { if(!pvCopy) {
monitorRequester->message("illegal pvRequest",errorMessage); requester->message("illegal pvRequest",errorMessage);
return false; return false;
} }
} else { } else {
if(pvField->getField()->getType()!=structure) { if(pvField->getField()->getType()!=structure) {
monitorRequester->message("illegal pvRequest",errorMessage); requester->message("illegal pvRequest",errorMessage);
return false; return false;
} }
pvCopy = PVCopy::create( pvCopy = PVCopy::create(
pvRecord->getPVRecordStructure()->getPVStructure(), pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,"field"); pvRequest,"field");
if(!pvCopy) { if(!pvCopy) {
monitorRequester->message("illegal pvRequest",errorMessage); requester->message("illegal pvRequest",errorMessage);
return false; return false;
} }
} }
@@ -370,7 +375,7 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
monitorElementArray.push_back(monitorElement); monitorElementArray.push_back(monitorElement);
} }
queue = MonitorElementQueuePtr(new MonitorElementQueue(monitorElementArray)); queue = MonitorElementQueuePtr(new MonitorElementQueue(monitorElementArray));
monitorRequester->monitorConnect( requester->monitorConnect(
Status::Ok, Status::Ok,
getPtrSelf(), getPtrSelf(),
pvCopy->getStructure()); pvCopy->getStructure());
@@ -26,6 +26,7 @@
#include <epicsThread.h> #include <epicsThread.h>
#include <iocsh.h> #include <iocsh.h>
#include <shareLib.h> #include <shareLib.h>
#include <epicsExit.h>
#include <pv/pvAccess.h> #include <pv/pvAccess.h>
#include <pv/serverContext.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; for(size_t i=0; i<xxx.size(); ++i) cout<< xxx[i] << endl;
} }
static void channelProviderLocalExitHandler(void* /*pPrivate*/) {
getChannelProviderLocal()->destroy();
}
static void registerChannelProviderLocal(void) static void registerChannelProviderLocal(void)
{ {
@@ -60,6 +64,7 @@ static void registerChannelProviderLocal(void)
firstTime = 0; firstTime = 0;
iocshRegister(&pvdblFuncDef, pvdbl); iocshRegister(&pvdblFuncDef, pvdbl);
getChannelProviderLocal(); getChannelProviderLocal();
epicsAtExit(channelProviderLocalExitHandler, NULL);
} }
} }