diff --git a/example/createdestroy/createdestroy.cpp b/example/createdestroy/createdestroy.cpp index c4f47be..c432f34 100644 --- a/example/createdestroy/createdestroy.cpp +++ b/example/createdestroy/createdestroy.cpp @@ -93,28 +93,38 @@ int main (int argc, char** argv) unsigned loopctr = 0; unsigned pausectr = 0; bool allowExit = false; - int opt; - while((opt = getopt(argc, argv, "v:ah")) != -1) { - switch(opt) { - case 'v': - verbose = std::stoi(optarg); - break; - case 'a' : - allowExit = true; - break; - case 'h': - std::cout << " -v level -a -h \n"; + bool callRecord = false; + bool callDatabase = false; + int opt; + while((opt = getopt(argc, argv, "v:ardh")) != -1) { + switch(opt) { + case 'v': + verbose = std::stoi(optarg); + break; + case 'a' : + allowExit = true; + break; + case 'r' : + callRecord = true; + break; + case 'd' : + callDatabase = true; + break; + case 'h': + std::cout << " -v level -a -r -d -h \n"; + std::cout << "-r call pvRecord->remove -d call master->removeRecord\n"; std::cout << "default\n"; std::cout << "-v " << verbose << " -a false" + << " -d" << "\n"; - return 0; - default: - std::cerr<<"Unknown argument: "< mymonitor = MyMonitor::create(channel); unsigned valuectr = loopctr; std::cout << startset << loopctr << "\n"; - for (int ind=0; ind<10; ind++) { + for (int ind=0; ind<100; ind++) { channel->put().set("value",valuectr++).exec(); mymonitor->getData(); } pausectr++; - if(allowExit && pausectr>500) { + if(allowExit && pausectr>10) { pausectr = 0; std::cout << "Type exit to stop: \n"; int c = std::cin.peek(); // peek character @@ -156,8 +166,14 @@ int main (int argc, char** argv) std::getline(std::cin,str); if(str.compare("exit")==0) break; } - pvrecord->remove(); -// master->removeRecord(pvrecord); + if(callRecord) { +std::cout << "callRecord\n"; + pvrecord->remove(); + } + if(callDatabase) { +std::cout << "callDatabase\n"; + master->removeRecord(pvrecord); + } } return (0); } diff --git a/src/database/pvDatabase.cpp b/src/database/pvDatabase.cpp index a74119c..a73a3fe 100644 --- a/src/database/pvDatabase.cpp +++ b/src/database/pvDatabase.cpp @@ -92,18 +92,28 @@ bool PVDatabase::addRecord(PVRecordPtr const & record) return true; } -bool PVDatabase::removeRecord(PVRecordPtr const & record,bool callRemove) +PVRecordWPtr PVDatabase::removeFromMap(PVRecordPtr const & record) { - if(record->getTraceLevel()>0) { - cout << "PVDatabase::removeRecord " << record->getRecordName() << endl; - } epicsGuard guard(mutex); string recordName = record->getRecordName(); PVRecordMap::iterator iter = recordMap.find(recordName); if(iter!=recordMap.end()) { PVRecordPtr pvRecord = (*iter).second; - if(callRemove) pvRecord->remove(false); recordMap.erase(iter); + return pvRecord->shared_from_this(); + } + return PVRecordWPtr(); +} + +bool PVDatabase::removeRecord(PVRecordPtr const & record) +{ + if(record->getTraceLevel()>0) { + cout << "PVDatabase::removeRecord " << record->getRecordName() << endl; + } + epicsGuard guard(mutex); + PVRecordWPtr pvRecord = removeFromMap(record); + if(pvRecord.use_count()!=0) { + pvRecord.lock()->unlistenClients(); return true; } return false; diff --git a/src/database/pvRecord.cpp b/src/database/pvRecord.cpp index ba08eb0..2701da4 100644 --- a/src/database/pvRecord.cpp +++ b/src/database/pvRecord.cpp @@ -65,17 +65,9 @@ PVRecord::~PVRecord() } } -void PVRecord::remove(bool callpvDatabaseRemoveRecord) +void PVRecord::unlistenClients() { - if(traceLevel>0) { - cout << "PVRecord::remove() " << recordName << endl; - } - epicsGuard guard(mutex); - if(callpvDatabaseRemoveRecord) { - PVDatabasePtr pvDatabase(PVDatabase::getMaster()); - if(pvDatabase) pvDatabase->removeRecord(shared_from_this(),false); - } - pvTimeStamp.detach(); + epicsGuard guard(mutex); for(std::list::iterator iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) @@ -102,6 +94,19 @@ void PVRecord::remove(bool callpvDatabaseRemoveRecord) clientList.clear(); } + +void PVRecord::remove() +{ + if(traceLevel>0) { + cout << "PVRecord::remove() " << recordName << endl; + } + unlistenClients(); + epicsGuard guard(mutex); + PVDatabasePtr pvDatabase(PVDatabase::getMaster()); + if(pvDatabase) pvDatabase->removeFromMap(shared_from_this()); + pvTimeStamp.detach(); +} + void PVRecord::initPVRecord() { PVRecordStructurePtr parent; diff --git a/src/pv/pvDatabase.h b/src/pv/pvDatabase.h index 4b6ba28..a445dc2 100644 --- a/src/pv/pvDatabase.h +++ b/src/pv/pvDatabase.h @@ -97,10 +97,8 @@ public: * get rid of listeners and requesters. * If derived class overrides this then it must call PVRecord::remove() * after it has destroyed any resorces it uses. - * @param callpvDatabaseRemoveRecord Should pvDatabase.removeRecord be called. - * Normally this is only set false by PVDatabase::removeRecord. */ - virtual void remove(bool callpvDatabaseRemoveRecord = true); + virtual void remove(); /** * @brief Optional method for derived class. * @@ -254,6 +252,9 @@ protected: */ void initPVRecord(); private: + friend class PVDatabase; + void unlistenClients(); + PVRecordFieldPtr findPVRecordField( PVRecordStructurePtr const & pvrs, epics::pvData::PVFieldPtr const & pvField); @@ -500,17 +501,19 @@ public: /** * @brief Remove a record. * @param record The record to remove. - * @param callRemove Call pvRecord->remove() - * Normally this is only set false by pvRecord.remove() + * * @return true if record was removed. */ - bool removeRecord(PVRecordPtr const & record,bool callRemove = true); + bool removeRecord(PVRecordPtr const & record); /** * @brief Get the names of all the records in the database. * @return The names. */ epics::pvData::PVStringArrayPtr getRecordNames(); private: + friend class PVRecord; + + PVRecordWPtr removeFromMap(PVRecordPtr const & record); PVDatabase(); void lock(); void unlock();