diff --git a/testApp/remote/eget.cpp b/testApp/remote/eget.cpp index 5f7fa0b..c528f20 100644 --- a/testApp/remote/eget.cpp +++ b/testApp/remote/eget.cpp @@ -1049,7 +1049,6 @@ private: String m_channelName; bool m_printValue; - ChannelGet::shared_pointer m_channelGet; PVStructure::shared_pointer m_pvStructure; BitSet::shared_pointer m_bitSet; Mutex m_pointerMutex; @@ -1076,9 +1075,9 @@ public: std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } - virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet, - epics::pvData::PVStructure::shared_pointer const & pvStructure, - epics::pvData::BitSet::shared_pointer const & bitSet) + virtual void channelGetConnect(const epics::pvData::Status& status, + ChannelGet::shared_pointer const & channelGet, + epics::pvData::Structure::const_shared_pointer const & /*structure*/) { if (status.isSuccess()) { @@ -1088,15 +1087,8 @@ public: std::cerr << "[" << m_channelName << "] channel get create: " << status << std::endl; } - // assign smart pointers - { - Lock lock(m_pointerMutex); - m_channelGet = channelGet; - m_pvStructure = pvStructure; - m_bitSet = bitSet; - } - - channelGet->get(true); + channelGet->lastRequest(); + channelGet->get(); } else { @@ -1105,7 +1097,10 @@ public: } } - virtual void getDone(const epics::pvData::Status& status) + virtual void getDone(const epics::pvData::Status& status, + ChannelGet::shared_pointer const & /*channelGet*/, + epics::pvData::PVStructure::shared_pointer const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet) { if (status.isSuccess()) { @@ -1118,30 +1113,19 @@ public: // access smart pointers { Lock lock(m_pointerMutex); + m_pvStructure = pvStructure; + m_bitSet = bitSet; + m_done = true; + + if (m_printValue) { - m_done = true; - - if (m_printValue) - { - // needed since we access the data - ScopedLock dataLock(m_channelGet); - - printValue(m_channelName, m_pvStructure); - } + printValue(m_channelName, m_pvStructure); } - - // this is OK since callee holds also owns it - m_channelGet.reset(); } } else { std::cerr << "[" << m_channelName << "] failed to get: " << status << std::endl; - { - Lock lock(m_pointerMutex); - // this is OK since caller holds also owns it - m_channelGet.reset(); - } } m_event.signal(); @@ -1171,10 +1155,10 @@ public: class ChannelRPCRequesterImpl : public ChannelRPCRequester { private: - ChannelRPC::shared_pointer m_channelRPC; Mutex m_pointerMutex; Event m_event; Event m_connectionEvent; + bool m_successfullyConnected; String m_channelName; PVStructure::shared_pointer m_lastResponse; @@ -1182,7 +1166,12 @@ private: public: - ChannelRPCRequesterImpl(String channelName) : m_channelName(channelName), m_done(false) {} + ChannelRPCRequesterImpl(String channelName) : + m_successfullyConnected(false), + m_channelName(channelName), + m_done(false) + { + } virtual String getRequesterName() { @@ -1194,7 +1183,7 @@ public: std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } - virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC::shared_pointer const & channelRPC) + virtual void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC::shared_pointer const & /*channelRPC*/) { if (status.isSuccess()) { @@ -1204,10 +1193,9 @@ public: std::cerr << "[" << m_channelName << "] channel RPC create: " << status << std::endl; } - // assign smart pointers - { + { Lock lock(m_pointerMutex); - m_channelRPC = channelRPC; + m_successfullyConnected = status.isSuccess(); } m_connectionEvent.signal(); @@ -1219,7 +1207,9 @@ public: } } - virtual void requestDone (const epics::pvData::Status &status, epics::pvData::PVStructure::shared_pointer const &pvResponse) + virtual void requestDone (const epics::pvData::Status &status, + ChannelRPC::shared_pointer const & /*channelRPC*/, + epics::pvData::PVStructure::shared_pointer const &pvResponse) { if (status.isSuccess()) { @@ -1240,19 +1230,11 @@ public: formatNT(std::cout, pvResponse); std::cout << std::endl; */ - - // this is OK since calle holds also owns it - m_channelRPC.reset(); } } else { std::cerr << "[" << m_channelName << "] failed to RPC: " << status << std::endl; - { - Lock lock(m_pointerMutex); - // this is OK since caller holds also owns it - m_channelRPC.reset(); - } } m_event.signal(); @@ -1294,12 +1276,8 @@ public: return false; } - bool connected; - { - Lock lock(m_pointerMutex); - connected = (m_channelRPC.get() != 0); - } - return connected ? true : false; + Lock lock(m_pointerMutex); + return m_successfullyConnected; } }; @@ -2051,7 +2029,8 @@ int main (int argc, char *argv[]) if (rpcRequesterImpl->waitUntilConnected(timeOut)) { - channelRPC->request(arg, true); + channelRPC->lastRequest(); + channelRPC->request(arg); allOK &= rpcRequesterImpl->waitUntilRPC(timeOut); if (allOK) { diff --git a/testApp/remote/pvget.cpp b/testApp/remote/pvget.cpp index fdaf450..06ce127 100644 --- a/testApp/remote/pvget.cpp +++ b/testApp/remote/pvget.cpp @@ -102,7 +102,6 @@ void printValue(String const & channelName, PVStructure::shared_pointer const & class ChannelGetRequesterImpl : public ChannelGetRequester { private: - ChannelGet::shared_pointer m_channelGet; PVStructure::shared_pointer m_pvStructure; BitSet::shared_pointer m_bitSet; Mutex m_pointerMutex; @@ -125,9 +124,8 @@ class ChannelGetRequesterImpl : public ChannelGetRequester std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } - virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet, - epics::pvData::PVStructure::shared_pointer const & pvStructure, - epics::pvData::BitSet::shared_pointer const & bitSet) + virtual void channelGetConnect(const epics::pvData::Status& status, ChannelGet::shared_pointer const & channelGet, + epics::pvData::Structure::const_shared_pointer const & /*structure*/) { if (status.isSuccess()) { @@ -137,15 +135,8 @@ class ChannelGetRequesterImpl : public ChannelGetRequester std::cerr << "[" << m_channelName << "] channel get create: " << status << std::endl; } - // assign smart pointers - { - Lock lock(m_pointerMutex); - m_channelGet = channelGet; - m_pvStructure = pvStructure; - m_bitSet = bitSet; - } - - channelGet->get(true); + channelGet->lastRequest(); + channelGet->get(); } else { @@ -154,7 +145,10 @@ class ChannelGetRequesterImpl : public ChannelGetRequester } } - virtual void getDone(const epics::pvData::Status& status) + virtual void getDone(const epics::pvData::Status& status, + ChannelGet::shared_pointer const & /*channelGet*/, + epics::pvData::PVStructure::shared_pointer const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet) { if (status.isSuccess()) { @@ -167,30 +161,17 @@ class ChannelGetRequesterImpl : public ChannelGetRequester // access smart pointers { Lock lock(m_pointerMutex); + + m_pvStructure = pvStructure; + m_bitSet = bitSet; m_done = true; - /* - { - // needed since we access the data - ScopedLock dataLock(m_channelGet); - - printValue(m_channelName, m_pvStructure); - - } - */ - // this is OK since callee holds also owns it - m_channelGet.reset(); } } else { std::cerr << "[" << m_channelName << "] failed to get: " << status << std::endl; - { - Lock lock(m_pointerMutex); - // this is OK since caller holds also owns it - m_channelGet.reset(); - } } m_event.signal(); diff --git a/testApp/remote/pvput.cpp b/testApp/remote/pvput.cpp index ebb0e2e..5d484c3 100644 --- a/testApp/remote/pvput.cpp +++ b/testApp/remote/pvput.cpp @@ -251,7 +251,6 @@ class AtomicBoolean class ChannelPutRequesterImpl : public ChannelPutRequester { private: - ChannelPut::shared_pointer m_channelPut; PVStructure::shared_pointer m_pvStructure; BitSet::shared_pointer m_bitSet; Mutex m_pointerMutex; @@ -279,8 +278,7 @@ class ChannelPutRequesterImpl : public ChannelPutRequester virtual void channelPutConnect(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut, - epics::pvData::PVStructure::shared_pointer const & pvStructure, - epics::pvData::BitSet::shared_pointer const & bitSet) + epics::pvData::Structure::const_shared_pointer const & /*structure*/) { if (status.isSuccess()) { @@ -290,14 +288,6 @@ class ChannelPutRequesterImpl : public ChannelPutRequester std::cerr << "[" << m_channelName << "] channel put create: " << status << std::endl; } - // assign smart pointers - { - Lock lock(m_pointerMutex); - m_channelPut = channelPut; - m_pvStructure = pvStructure; - m_bitSet = bitSet; - } - // we always put all m_bitSet->set(0); @@ -311,7 +301,9 @@ class ChannelPutRequesterImpl : public ChannelPutRequester } } - virtual void getDone(const epics::pvData::Status& status) + virtual void getDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & /*channelPut*/, + epics::pvData::PVStructure::shared_pointer const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet) { if (status.isSuccess()) { @@ -323,21 +315,11 @@ class ChannelPutRequesterImpl : public ChannelPutRequester m_done.set(); - /* - // access smart pointers - // do not print old value in terseMode - if (!m_supressGetValue.get()) { Lock lock(m_pointerMutex); - { - - // needed since we access the data - ScopedLock dataLock(m_channelPut); - - printValue(m_channelName, m_pvStructure); - } + m_pvStructure = pvStructure; + m_bitSet = bitSet; } - */ } else @@ -348,7 +330,7 @@ class ChannelPutRequesterImpl : public ChannelPutRequester m_event->signal(); } - virtual void putDone(const epics::pvData::Status& status) + virtual void putDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & /*channelPut*/) { if (status.isSuccess()) { @@ -374,6 +356,12 @@ class ChannelPutRequesterImpl : public ChannelPutRequester return m_pvStructure; } + BitSet::shared_pointer getBitSet() + { + Lock lock(m_pointerMutex); + return m_bitSet; + } + void resetEvent() { Lock lock(m_eventMutex); @@ -587,7 +575,8 @@ int main (int argc, char *argv[]) // we do a put putRequesterImpl->resetEvent(); - channelPut->put(false); + // note on bitSet: we get all, we set all + channelPut->put(putRequesterImpl->getStructure(), putRequesterImpl->getBitSet()); allOK &= putRequesterImpl->waitUntilDone(timeOut); if (allOK) diff --git a/testApp/remote/testGetPerformance.cpp b/testApp/remote/testGetPerformance.cpp index 81b8f44..fbd3929 100644 --- a/testApp/remote/testGetPerformance.cpp +++ b/testApp/remote/testGetPerformance.cpp @@ -114,7 +114,7 @@ void get_all() for (vector::const_iterator i = channelGetList.begin(); i != channelGetList.end(); i++) - (*i)->get(false); + (*i)->get(); // we assume all channels are from the same provider if (bulkMode) provider->flush(); @@ -125,9 +125,6 @@ void get_all() class ChannelGetRequesterImpl : public ChannelGetRequester { private: - ChannelGet::shared_pointer m_channelGet; - PVStructure::shared_pointer m_pvStructure; - BitSet::shared_pointer m_bitSet; Event m_event; Event m_connectionEvent; String m_channelName; @@ -153,9 +150,8 @@ public: } virtual void channelGetConnect(const epics::pvData::Status& status, - ChannelGet::shared_pointer const & channelGet, - epics::pvData::PVStructure::shared_pointer const & pvStructure, - epics::pvData::BitSet::shared_pointer const & bitSet) + ChannelGet::shared_pointer const & /*channelGet*/, + epics::pvData::Structure::const_shared_pointer const & /*structure*/) { if (status.isSuccess()) { @@ -165,10 +161,6 @@ public: std::cout << "[" << m_channelName << "] channel get create: " << status.toString() << std::endl; } - m_channelGet = channelGet; - m_pvStructure = pvStructure; - m_bitSet = bitSet; - m_connectionEvent.signal(); } else @@ -177,7 +169,10 @@ public: } } - virtual void getDone(const epics::pvData::Status& status) + virtual void getDone(const epics::pvData::Status& status, + ChannelGet::shared_pointer const & /*channelGet*/, + epics::pvData::PVStructure::shared_pointer const & /*pvStructure*/, + epics::pvData::BitSet::shared_pointer const & /*bitSet*/) { if (status.isSuccess()) { diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index 66fe170..b0b8fed 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -138,7 +138,7 @@ public: iter++) { try { - (*iter)->process(false); + (*iter)->process(); } catch (std::exception &ex) { std::cerr << "Unhandled exception caught in ProcessAction::run(): " << ex.what() << std::endl; } catch (...) { @@ -700,7 +700,8 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester //m_channelProcess = channelProcess; } - virtual void processDone(const epics::pvData::Status& /*status*/) + virtual void processDone(const epics::pvData::Status& /*status*/, + ChannelProcess::shared_pointer const &) { //std::cout << "processDone(" << status.toString() << ")" << std::endl; } @@ -714,16 +715,17 @@ class MockChannelProcess : public std::tr1::enable_shared_from_this { private: - String m_channelName; + Channel::shared_pointer m_channel; ChannelProcessRequester::shared_pointer m_channelProcessRequester; PVStructure::shared_pointer m_pvStructure; PVScalarPtr m_valueField; PVTimeStamp m_timeStamp; + AtomicBoolean m_lastRequest; protected: - MockChannelProcess(String const & channelName, ChannelProcessRequester::shared_pointer const & channelProcessRequester, + MockChannelProcess(Channel::shared_pointer const & channel, ChannelProcessRequester::shared_pointer const & channelProcessRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & /*pvRequest*/) : - m_channelName(channelName), m_channelProcessRequester(channelProcessRequester), m_pvStructure(pvStructure) + m_channel(channel), m_channelProcessRequester(channelProcessRequester), m_pvStructure(pvStructure) { PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(mockChannelProcess); @@ -755,11 +757,11 @@ protected: public: static ChannelProcess::shared_pointer create( - String const & channelName, + Channel::shared_pointer const & channel, ChannelProcessRequester::shared_pointer const & channelProcessRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) { - ChannelProcess::shared_pointer thisPtr(new MockChannelProcess(channelName, channelProcessRequester, pvStructure, pvRequest)); + ChannelProcess::shared_pointer thisPtr(new MockChannelProcess(channel, channelProcessRequester, pvStructure, pvRequest)); // TODO pvRequest channelProcessRequester->channelProcessConnect(Status::Ok, thisPtr); @@ -773,7 +775,7 @@ public: } - virtual void process(bool lastRequest) + virtual void process() { { ScopedLock lock(shared_from_this()); @@ -877,14 +879,24 @@ public: m_timeStamp.set(current); } - m_channelProcessRequester->processDone(Status::Ok); + m_channelProcessRequester->processDone(Status::Ok, shared_from_this()); - notifyStructureChanged(m_channelName); + notifyStructureChanged(m_channel->getChannelName()); - if (lastRequest) + if (m_lastRequest.get()) destroy(); } + virtual void lastRequest() + { + m_lastRequest.set(); + } + + virtual Channel::shared_pointer getChannel() + { + return m_channel; + } + virtual void cancel() { } @@ -932,19 +944,20 @@ class MockChannelGet : public std::tr1::enable_shared_from_this { private: - String m_channelName; + Channel::shared_pointer m_channel; ChannelGetRequester::shared_pointer m_channelGetRequester; PVStructure::shared_pointer m_pvStructure; BitSet::shared_pointer m_bitSet; ChannelProcess::shared_pointer m_channelProcess; AtomicBoolean m_changed; + AtomicBoolean m_lastRequest; protected: MockChannelGet(Channel::shared_pointer const & channel, ChannelGetRequester::shared_pointer const & channelGetRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) : - m_channelName(channel->getChannelName()), + m_channel(channel), m_channelGetRequester(channelGetRequester), m_pvStructure(getRequestedStructure(pvStructure, pvRequest)), m_bitSet(new BitSet(m_pvStructure->getNumberFields())), @@ -967,8 +980,7 @@ public: structureChangedListeners[channel->getChannelName()].push_back(std::tr1::dynamic_pointer_cast(thisPtr)); channelGetRequester->channelGetConnect(Status::Ok, thisPtr, - static_cast(thisPtr.get())->m_pvStructure, - static_cast(thisPtr.get())->m_bitSet); + static_cast(thisPtr.get())->m_pvStructure->getStructure()); return thisPtr; } @@ -977,10 +989,10 @@ public: PVACCESS_REFCOUNT_MONITOR_DESTRUCT(mockChannelGet); } - virtual void get(bool lastRequest) + virtual void get() { if (m_channelProcess) - m_channelProcess->process(false); + m_channelProcess->process(); // TODO far from being thread-safe if (m_changed.get()) @@ -991,9 +1003,9 @@ public: else m_bitSet->clear(0); - m_channelGetRequester->getDone(Status::Ok); + m_channelGetRequester->getDone(Status::Ok, shared_from_this(), m_pvStructure, m_bitSet); - if (lastRequest) + if (m_lastRequest.get()) destroy(); } @@ -1002,6 +1014,16 @@ public: m_changed.set(); } + virtual void lastRequest() + { + m_lastRequest.set(); + } + + virtual Channel::shared_pointer getChannel() + { + return m_channel; + } + virtual void cancel() { } @@ -1012,9 +1034,9 @@ public: m_channelProcess->destroy(); // remove itself from listeners table - if (structureChangedListeners.count(m_channelName)) + if (structureChangedListeners.count(m_channel->getChannelName())) { - vector &vec = structureChangedListeners[m_channelName]; + vector &vec = structureChangedListeners[m_channel->getChannelName()]; for (vector::iterator i = vec.begin(); i != vec.end(); i++) { @@ -1043,21 +1065,24 @@ public: PVACCESS_REFCOUNT_MONITOR_DEFINE(mockChannelPut); -class MockChannelPut : public ChannelPut +class MockChannelPut : + public ChannelPut, + public std::tr1::enable_shared_from_this { private: - String m_channelName; + Channel::shared_pointer m_channel; ChannelPutRequester::shared_pointer m_channelPutRequester; PVStructure::shared_pointer m_pvStructure; BitSet::shared_pointer m_bitSet; ChannelProcess::shared_pointer m_channelProcess; - + AtomicBoolean m_lastRequest; + protected: MockChannelPut(Channel::shared_pointer const & channel, ChannelPutRequester::shared_pointer const & channelPutRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) : - m_channelName(channel->getChannelName()), + m_channel(channel), m_channelPutRequester(channelPutRequester), m_pvStructure(getRequestedStructure(pvStructure, pvRequest)), m_bitSet(new BitSet(m_pvStructure->getNumberFields())), @@ -1075,9 +1100,7 @@ public: { ChannelPut::shared_pointer thisPtr(new MockChannelPut(channel, channelPutRequester, pvStructure, pvRequest)); channelPutRequester->channelPutConnect(Status::Ok, thisPtr, - static_cast(thisPtr.get())->m_pvStructure, - static_cast(thisPtr.get())->m_bitSet); - + static_cast(thisPtr.get())->m_pvStructure->getStructure()); return thisPtr; } @@ -1087,28 +1110,43 @@ public: } - virtual void put(bool lastRequest) + virtual void put(PVStructure::shared_pointer const & pvPutStructure, BitSet::shared_pointer const & putBitSet) { + // TODO data - do an actual put !!! + if (m_channelProcess) - m_channelProcess->process(false); + m_channelProcess->process(); - m_channelPutRequester->putDone(Status::Ok); + m_channelPutRequester->putDone(Status::Ok, shared_from_this()); - notifyStructureChanged(m_channelName); + notifyStructureChanged(m_channel->getChannelName()); - if (lastRequest) + if (m_lastRequest.get()) destroy(); } virtual void get() { - m_channelPutRequester->getDone(Status::Ok); + m_channelPutRequester->getDone(Status::Ok, shared_from_this(), m_pvStructure, m_bitSet); + + if (m_lastRequest.get()) + destroy(); } virtual void cancel() { } + virtual void lastRequest() + { + m_lastRequest.set(); + } + + virtual Channel::shared_pointer getChannel() + { + return m_channel; + } + virtual void destroy() { if (m_channelProcess) @@ -1131,28 +1169,38 @@ public: PVACCESS_REFCOUNT_MONITOR_DEFINE(mockChannelPutGet); -class MockChannelPutGet : public ChannelPutGet +class MockChannelPutGet : + public ChannelPutGet, + public std::tr1::enable_shared_from_this { private: - String m_channelName; + Channel::shared_pointer m_channel; ChannelPutGetRequester::shared_pointer m_channelPutGetRequester; PVStructure::shared_pointer m_getStructure; + BitSet::shared_pointer m_getBitSet; PVStructure::shared_pointer m_putStructure; + BitSet::shared_pointer m_putBitSet; ChannelProcess::shared_pointer m_channelProcess; + AtomicBoolean m_lastRequest; protected: MockChannelPutGet(Channel::shared_pointer const & channel, ChannelPutGetRequester::shared_pointer const & channelPutGetRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) : - m_channelName(channel->getChannelName()), + m_channel(channel), m_channelPutGetRequester(channelPutGetRequester), m_getStructure(getRequestedStructure(pvStructure, pvRequest, "getField")), + m_getBitSet(new BitSet(m_getStructure->getNumberFields())), m_putStructure(getRequestedStructure(pvStructure, pvRequest, "putField")), + m_putBitSet(new BitSet(m_putStructure->getNumberFields())), m_channelProcess(getChannelProcess(channel, pvRequest)) { PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(mockChannelPutGet); + + // always all + m_getBitSet->set(0); } public: @@ -1165,8 +1213,8 @@ public: ChannelPutGet::shared_pointer thisPtr(new MockChannelPutGet(channel, channelPutGetRequester, pvStructure, pvRequest)); channelPutGetRequester->channelPutGetConnect(Status::Ok, thisPtr, - static_cast(thisPtr.get())->m_putStructure, - static_cast(thisPtr.get())->m_getStructure); + static_cast(thisPtr.get())->m_putStructure->getStructure(), + static_cast(thisPtr.get())->m_getStructure->getStructure()); return thisPtr; } @@ -1176,27 +1224,49 @@ public: PVACCESS_REFCOUNT_MONITOR_DESTRUCT(mockChannelPutGet); } - virtual void putGet(bool lastRequest) + virtual void putGet(PVStructure::shared_pointer const & pvPutStructure, BitSet::shared_pointer const & putBitSet) { + // TODO !!! copy what was put... + if (m_channelProcess) - m_channelProcess->process(false); + m_channelProcess->process(); - m_channelPutGetRequester->putGetDone(Status::Ok); + m_channelPutGetRequester->putGetDone(Status::Ok, shared_from_this(), m_getStructure, m_getBitSet); - notifyStructureChanged(m_channelName); + notifyStructureChanged(m_channel->getChannelName()); - if (lastRequest) + if (m_lastRequest.get()) destroy(); } virtual void getGet() { - m_channelPutGetRequester->getGetDone(Status::Ok); + m_channelPutGetRequester->getGetDone(Status::Ok, shared_from_this(), m_getStructure, m_getBitSet); + + if (m_lastRequest.get()) + destroy(); } virtual void getPut() { - m_channelPutGetRequester->getPutDone(Status::Ok); + // putGet might mess with bitSet + m_putBitSet->clear(); + m_putBitSet->set(0); + + m_channelPutGetRequester->getPutDone(Status::Ok, shared_from_this(), m_putStructure, m_putBitSet); + + if (m_lastRequest.get()) + destroy(); + } + + virtual void lastRequest() + { + m_lastRequest.set(); + } + + virtual Channel::shared_pointer getChannel() + { + return m_channel; } virtual void cancel() @@ -1224,6 +1294,7 @@ public: static bool handleHelp( epics::pvData::PVStructure::shared_pointer const & args, + ChannelRPC::shared_pointer const & channelRPC, ChannelRPCRequester::shared_pointer const & channelRPCRequester, String const & helpText ) @@ -1244,7 +1315,7 @@ static bool handleHelp( ); static_pointer_cast(result->getStringField("value"))->put(helpText); - channelRPCRequester->requestDone(Status::Ok, result); + channelRPCRequester->requestDone(Status::Ok, channelRPC, result); return true; } else @@ -1256,26 +1327,31 @@ static bool handleHelp( PVACCESS_REFCOUNT_MONITOR_DEFINE(mockChannelRPC); -class MockChannelRPC : public ChannelRPC +class MockChannelRPC : + public ChannelRPC, + public std::tr1::enable_shared_from_this { private: ChannelRPCRequester::shared_pointer m_channelRPCRequester; - String m_channelName; + Channel::shared_pointer m_channel; PVStructure::shared_pointer m_pvStructure; + AtomicBoolean m_lastRequest; protected: MockChannelRPC(ChannelRPCRequester::shared_pointer const & channelRPCRequester, - String const & channelName, PVStructure::shared_pointer const & pvStructure, + Channel::shared_pointer const & channel, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & /*pvRequest*/) : - m_channelRPCRequester(channelRPCRequester), m_channelName(channelName), m_pvStructure(pvStructure) + m_channelRPCRequester(channelRPCRequester), m_channel(channel), m_pvStructure(pvStructure) { PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(mockChannelRPC); } public: - static ChannelRPC::shared_pointer create(ChannelRPCRequester::shared_pointer const & channelRPCRequester, String const & channelName, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) + static ChannelRPC::shared_pointer create(ChannelRPCRequester::shared_pointer const & channelRPCRequester, + Channel::shared_pointer const & channel, + PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) { - ChannelRPC::shared_pointer thisPtr(new MockChannelRPC(channelRPCRequester, channelName, pvStructure, pvRequest)); + ChannelRPC::shared_pointer thisPtr(new MockChannelRPC(channelRPCRequester, channel, pvStructure, pvRequest)); // TODO pvRequest channelRPCRequester->channelRPCConnect(Status::Ok, thisPtr); return thisPtr; @@ -1286,9 +1362,10 @@ public: PVACCESS_REFCOUNT_MONITOR_DESTRUCT(mockChannelRPC); } - virtual void request(epics::pvData::PVStructure::shared_pointer const & pvArgument, bool lastRequest) + virtual void request(epics::pvData::PVStructure::shared_pointer const & pvArgument) { - if (m_channelName == "testNTTable") + String channelName = m_channel->getChannelName(); + if (channelName == "testNTTable") { PVStructure::shared_pointer args( (pvArgument->getStructure()->getID() == "uri:ev4:nt/2012/pwd:NTURI") ? @@ -1300,7 +1377,7 @@ public: "Generates a NTTable structure response with 10 rows and a specified number of columns.\n" "Columns are labeled 'column' and values are ' + random [0..1)'.\n" "Arguments:\n\tstring columns\tnumber of table columns\n"; - if (handleHelp(args, m_channelRPCRequester, helpText)) + if (handleHelp(args, shared_from_this(), m_channelRPCRequester, helpText)) return; PVStringPtr columns = dynamic_pointer_cast(args->getSubField("columns")); @@ -1308,17 +1385,17 @@ public: { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "no string 'columns' argument specified"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } else { int columnsCount = atoi(columns->get().c_str()); PVStructure::shared_pointer result = createNTTable(columnsCount); generateNTTableDoubleValues(result); - m_channelRPCRequester->requestDone(Status::Ok, result); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result); } } - else if (m_channelName == "testNTNameValue") + else if (channelName == "testNTNameValue") { PVStructure::shared_pointer args( (pvArgument->getStructure()->getID() == "uri:ev4:nt/2012/pwd:NTURI") ? @@ -1330,7 +1407,7 @@ public: "Generates a NTNameValue structure response with a specified number of columns.\n" "Columns are labeled 'name' and values are ' + random [0..1)'.\n" "Arguments:\n\tstring columns\tnumber of columns\n"; - if (handleHelp(args, m_channelRPCRequester, helpText)) + if (handleHelp(args, shared_from_this(), m_channelRPCRequester, helpText)) return; PVStringPtr columns = dynamic_pointer_cast(args->getSubField("columns")); @@ -1338,7 +1415,7 @@ public: { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "no string 'columns' argument specified"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } else { @@ -1374,10 +1451,10 @@ public: mv[r] = rand()/((double)RAND_MAX+1) + (int)(r); result->getSubField("value")->replace(freeze(mv)); - m_channelRPCRequester->requestDone(Status::Ok, result); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result); } } - else if (m_channelName == "testNTMatrix") + else if (channelName == "testNTMatrix") { PVStructure::shared_pointer args( (pvArgument->getStructure()->getID() == "uri:ev4:nt/2012/pwd:NTURI") ? @@ -1392,7 +1469,7 @@ public: "\tstring rows\tnumber of matrix rows\n" "\tstring columns\tnumber of matrix columns\n" "\t[string bycolumns\torder matrix values in a column-major order]\n"; - if (handleHelp(args, m_channelRPCRequester, helpText)) + if (handleHelp(args, shared_from_this(), m_channelRPCRequester, helpText)) return; PVStringPtr rows = dynamic_pointer_cast(args->getSubField("rows")); @@ -1401,7 +1478,7 @@ public: { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "no string 'rows' and 'columns' arguments specified"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } else { @@ -1439,10 +1516,10 @@ public: mv[r] = rand()/((double)RAND_MAX+1) + (int)(r/colsVal); result->getSubField("value")->replace(freeze(mv)); - m_channelRPCRequester->requestDone(Status::Ok, result); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result); } } - else if (m_channelName.find("testImage") == 0) + else if (channelName.find("testImage") == 0) { PVStructure::shared_pointer args( (pvArgument->getStructure()->getID() == "uri:ev4:nt/2012/pwd:NTURI") ? @@ -1461,7 +1538,7 @@ public: "\t\t\t\tconvert my_image.png my_image.rgb\n" "\tstring w\timage width\n" "\tstring h\timage height\n"; - if (handleHelp(args, m_channelRPCRequester, helpText)) + if (handleHelp(args, shared_from_this(), m_channelRPCRequester, helpText)) return; PVStringPtr file = dynamic_pointer_cast(args->getSubField("file")); @@ -1471,7 +1548,7 @@ public: { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "not all 'file', 'w' and 'h' arguments specified"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } else { @@ -1515,47 +1592,47 @@ public: in.readsome((char*)temp.data(), fileSize); value->replace(freeze(temp)); - m_channelRPCRequester->requestDone(Status::Ok, m_pvStructure); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), m_pvStructure); // for monitors - notifyStructureChanged(m_channelName); + notifyStructureChanged(channelName); } else { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "file size does not match given 'w' and 'h'"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } } else { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "failed to open image file specified"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } } } - else if (m_channelName == "testNTURI") + else if (channelName == "testNTURI") { const String helpText = "Returns the NTURI structure response identical the NTURI request.\n" "Arguments: (none)\n"; - if (handleHelp(pvArgument, m_channelRPCRequester, helpText)) + if (handleHelp(pvArgument, shared_from_this(), m_channelRPCRequester, helpText)) return; if (pvArgument->getStructure()->getID() != "uri:ev4:nt/2012/pwd:NTURI") { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "argument is not a NTURI structure"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); } else { // return argument as result - m_channelRPCRequester->requestDone(Status::Ok, pvArgument); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), pvArgument); } } - else if (m_channelName == "testSum") { + else if (channelName == "testSum") { PVStructure::shared_pointer args( (pvArgument->getStructure()->getID() == "uri:ev4:nt/2012/pwd:NTURI") ? @@ -1568,7 +1645,7 @@ public: "Arguments:\n" "\tint a\tfirst integer number\n" "\tint b\tsecond integer number\n"; - if (handleHelp(args, m_channelRPCRequester, helpText)) + if (handleHelp(args, shared_from_this(), m_channelRPCRequester, helpText)) return; PVInt::shared_pointer pa = args->getSubField("a"); @@ -1577,7 +1654,7 @@ public: { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "int a and int b arguments are required"); - m_channelRPCRequester->requestDone(errorStatus, nullPtr); + m_channelRPCRequester->requestDone(errorStatus, shared_from_this(), nullPtr); return; } @@ -1595,13 +1672,13 @@ public: PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); result->getIntField("c")->put(a+b); - m_channelRPCRequester->requestDone(Status::Ok, result); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result); } - else if (m_channelName.find("testServerShutdown") == 0) + else if (channelName.find("testServerShutdown") == 0) { PVStructure::shared_pointer nullPtr; - m_channelRPCRequester->requestDone(Status::Ok, nullPtr); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), nullPtr); testServerShutdown(); } else @@ -1611,13 +1688,23 @@ public: pvArgument->toString(&s); std::cout << "RPC" << std::endl << s << std::endl; */ - m_channelRPCRequester->requestDone(Status::Ok, m_pvStructure); + m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), m_pvStructure); } - if (lastRequest) + if (m_lastRequest.get()) destroy(); } + virtual void lastRequest() + { + m_lastRequest.set(); + } + + virtual Channel::shared_pointer getChannel() + { + return m_channel; + } + virtual void cancel() { } @@ -1643,22 +1730,24 @@ public: - - - PVACCESS_REFCOUNT_MONITOR_DEFINE(mockChannelArray); -class MockChannelArray : public ChannelArray +class MockChannelArray : + public ChannelArray, + public std::tr1::enable_shared_from_this { private: + Channel::shared_pointer m_channel; ChannelArrayRequester::shared_pointer m_channelArrayRequester; PVArray::shared_pointer m_pvArray; PVArray::shared_pointer m_pvStructureArray; + AtomicBoolean m_lastRequest; protected: - MockChannelArray(ChannelArrayRequester::shared_pointer const & channelArrayRequester, + MockChannelArray(Channel::shared_pointer const & channel, + ChannelArrayRequester::shared_pointer const & channelArrayRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & /*pvRequest*/) : - m_channelArrayRequester(channelArrayRequester) + m_channel(channel), m_channelArrayRequester(channelArrayRequester) { PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(mockChannelArray); @@ -1669,17 +1758,19 @@ protected: } public: - static ChannelArray::shared_pointer create(ChannelArrayRequester::shared_pointer const & channelArrayRequester, PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) + static ChannelArray::shared_pointer create(Channel::shared_pointer const & channel, + ChannelArrayRequester::shared_pointer const & channelArrayRequester, + PVStructure::shared_pointer const & pvStructure, PVStructure::shared_pointer const & pvRequest) { - ChannelArray::shared_pointer thisPtr(new MockChannelArray(channelArrayRequester, pvStructure, pvRequest)); + ChannelArray::shared_pointer thisPtr(new MockChannelArray(channel, channelArrayRequester, pvStructure, pvRequest)); PVArray::shared_pointer array(static_cast(thisPtr.get())->m_pvArray); if (array.get()) - channelArrayRequester->channelArrayConnect(Status::Ok, thisPtr, array); + channelArrayRequester->channelArrayConnect(Status::Ok, thisPtr, array->getArray()); else { Status errorStatus(Status::STATUSTYPE_ERROR, "no 'value' subfield of array type"); - channelArrayRequester->channelArrayConnect(errorStatus, thisPtr, array); + channelArrayRequester->channelArrayConnect(errorStatus, thisPtr, Array::const_shared_pointer()); } return thisPtr; @@ -1713,39 +1804,42 @@ public: to->replace(freeze(temp)); } - virtual void putArray(bool lastRequest, size_t offset, size_t count) + virtual void putArray(PVArray::shared_pointer const & pvArray, size_t offset, size_t count, size_t stride) { + // TODO stride support !!! + size_t o = offset; - if (count == 0) count = m_pvArray->getLength(); + if (count == 0) count = pvArray->getLength(); size_t c = count; - Field::const_shared_pointer field = m_pvArray->getField(); + Field::const_shared_pointer field = pvArray->getField(); Type type = field->getType(); if (type == scalarArray) { switch (std::tr1::static_pointer_cast(field)->getElementType()) { - case pvBoolean: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvByte: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvShort: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvInt: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvLong: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvUByte: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvUShort: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvUInt: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvULong: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvFloat: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvDouble: put(m_pvArray, m_pvStructureArray, o, c); break; - case pvString: put(m_pvArray, m_pvStructureArray, o, c); break; + case pvBoolean: put(pvArray, m_pvStructureArray, o, c); break; + case pvByte: put(pvArray, m_pvStructureArray, o, c); break; + case pvShort: put(pvArray, m_pvStructureArray, o, c); break; + case pvInt: put(pvArray, m_pvStructureArray, o, c); break; + case pvLong: put(pvArray, m_pvStructureArray, o, c); break; + case pvUByte: put(pvArray, m_pvStructureArray, o, c); break; + case pvUShort: put(pvArray, m_pvStructureArray, o, c); break; + case pvUInt: put(pvArray, m_pvStructureArray, o, c); break; + case pvULong: put(pvArray, m_pvStructureArray, o, c); break; + case pvFloat: put(pvArray, m_pvStructureArray, o, c); break; + case pvDouble: put(pvArray, m_pvStructureArray, o, c); break; + case pvString: put(pvArray, m_pvStructureArray, o, c); break; } } else if (type == structureArray) - put(m_pvArray, m_pvStructureArray, o, c); + put(pvArray, m_pvStructureArray, o, c); else if (type == unionArray) - put(m_pvArray, m_pvStructureArray, o, c); + put(pvArray, m_pvStructureArray, o, c); - m_channelArrayRequester->putArrayDone(Status::Ok); - if (lastRequest) + m_channelArrayRequester->putArrayDone(Status::Ok, shared_from_this()); + + if (m_lastRequest.get()) destroy(); } @@ -1765,8 +1859,10 @@ public: } - virtual void getArray(bool lastRequest, size_t offset, size_t count) + virtual void getArray(size_t offset, size_t count, size_t stride) { + // TODO stride support !!! + size_t o = offset; if (count == 0) count = m_pvStructureArray->getLength(); size_t c = count; @@ -1796,12 +1892,13 @@ public: else if (type == unionArray) get(m_pvStructureArray, m_pvArray, o, c); - m_channelArrayRequester->getArrayDone(Status::Ok); - if (lastRequest) + m_channelArrayRequester->getArrayDone(Status::Ok, shared_from_this(), m_pvArray); + + if (m_lastRequest.get()) destroy(); } - virtual void setLength(bool lastRequest, size_t length, size_t capacity) + virtual void setLength(size_t length, size_t capacity) { if (capacity > 0) { m_pvStructureArray->setCapacity(capacity); @@ -1809,11 +1906,32 @@ public: m_pvStructureArray->setLength(length); - m_channelArrayRequester->setLengthDone(Status::Ok); - if (lastRequest) + m_channelArrayRequester->setLengthDone(Status::Ok, shared_from_this()); + + if (m_lastRequest.get()) destroy(); } + virtual void getLength() + { + + m_channelArrayRequester->getLengthDone(Status::Ok, shared_from_this(), + m_pvStructureArray->getLength(), m_pvStructureArray->getCapacity()); + + if (m_lastRequest.get()) + destroy(); + } + + virtual void lastRequest() + { + m_lastRequest.set(); + } + + virtual Channel::shared_pointer getChannel() + { + return m_channel; + } + virtual void cancel() { } @@ -2274,7 +2392,7 @@ public: ChannelProcessRequester::shared_pointer const & channelProcessRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { - return MockChannelProcess::create(m_name, channelProcessRequester, m_pvStructure, pvRequest); + return MockChannelProcess::create(shared_from_this(), channelProcessRequester, m_pvStructure, pvRequest); } virtual ChannelGet::shared_pointer createChannelGet( @@ -2301,7 +2419,7 @@ public: virtual ChannelRPC::shared_pointer createChannelRPC(ChannelRPCRequester::shared_pointer const & channelRPCRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { - return MockChannelRPC::create(channelRPCRequester, m_name, m_pvStructure, pvRequest); + return MockChannelRPC::create(channelRPCRequester, shared_from_this(), m_pvStructure, pvRequest); } virtual epics::pvData::Monitor::shared_pointer createMonitor( @@ -2315,7 +2433,7 @@ public: ChannelArrayRequester::shared_pointer const & channelArrayRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { - return MockChannelArray::create(channelArrayRequester, m_pvStructure, pvRequest); + return MockChannelArray::create(shared_from_this(), channelArrayRequester, m_pvStructure, pvRequest); } virtual void printInfo() { @@ -2578,8 +2696,7 @@ void testServer(int timeToRun) //ServerContextImpl::shared_pointer ctx = ServerContextImpl::create(); ctx = ServerContextImpl::create(); - ChannelAccess::shared_pointer channelAccess = getChannelProviderRegistry(); - ctx->initialize(channelAccess); + ctx->initialize(getChannelProviderRegistry()); ctx->printInfo();