diff --git a/pvAccessApp/client/pvAccess.h b/pvAccessApp/client/pvAccess.h index 640ac31..c6ce53f 100644 --- a/pvAccessApp/client/pvAccess.h +++ b/pvAccessApp/client/pvAccess.h @@ -27,15 +27,66 @@ namespace epics { namespace pvAccess { }; + /** + * + */ + class Lockable + { + public: + POINTER_DEFINITIONS(Lockable); + + virtual void lock() = 0; + virtual void unlock() = 0; + }; + + /** + * Scope lock. + */ + class ScopedLock : private epics::pvData::NoDefaultMethods { + public: + + explicit ScopedLock(Lockable::shared_pointer const & li) + : lockable(li), locked(true) { + lockable->lock(); + } + + ~ScopedLock() { + unlock(); + } + + void lock() { + if(!locked) { + lockable->lock(); + locked = true; + } + } + + void unlock() { + if(locked) { + lockable->unlock(); + locked=false; + } + } + + bool ownsLock() const { + return locked; + } + + private: + + Lockable::shared_pointer const lockable; + bool locked; + }; + + class Channel; class ChannelProvider; - /** * Base interface for all channel requests. * @author mse */ - class ChannelRequest : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods { + class ChannelRequest : public epics::pvData::Destroyable, public Lockable, private epics::pvData::NoDefaultMethods { public: POINTER_DEFINITIONS(ChannelRequest); }; @@ -253,9 +304,9 @@ namespace epics { namespace pvAccess { * Get the current data. */ virtual void get() = 0; + }; - - + /** * epics::pvData::Requester for ChannelPut. * @author mrk diff --git a/pvAccessApp/remote/remote.h b/pvAccessApp/remote/remote.h index a1381d1..ac3b8ce 100644 --- a/pvAccessApp/remote/remote.h +++ b/pvAccessApp/remote/remote.h @@ -23,6 +23,9 @@ #include #include +/// TODO only here because of the Lockable +#include + namespace epics { namespace pvAccess { @@ -114,7 +117,7 @@ namespace epics { /** * Interface defining transport sender (instance sending data over transport). */ - class TransportSender { + class TransportSender : public Lockable { public: typedef std::tr1::shared_ptr shared_pointer; typedef std::tr1::shared_ptr const_shared_pointer; @@ -130,9 +133,6 @@ namespace epics { * NOTE: these limitations allows efficient implementation. */ virtual void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) = 0; - - virtual void lock() = 0; - virtual void unlock() = 0; }; /** diff --git a/pvAccessApp/remoteClient/clientContextImpl.cpp b/pvAccessApp/remoteClient/clientContextImpl.cpp index 178ab12..28b64b8 100644 --- a/pvAccessApp/remoteClient/clientContextImpl.cpp +++ b/pvAccessApp/remoteClient/clientContextImpl.cpp @@ -100,31 +100,31 @@ namespace epics { Requester::shared_pointer m_requester; - bool m_destroyed; - bool m_initialized; - /* negative... */ static const int NULL_REQUEST = -1; static const int PURE_DESTROY_REQUEST = -2; - int32 m_pendingRequest; - pvAccessID m_ioid; + int32 m_pendingRequest; + Mutex m_mutex; // used to hold ownership until create is called (to support complete async usage) ResponseRequest::shared_pointer m_thisPointer; + bool m_destroyed; + bool m_initialized; + virtual ~BaseRequestImpl() {}; BaseRequestImpl(ChannelImpl::shared_pointer const & channel, Requester::shared_pointer requester) : m_channel(channel), m_requester(requester), - m_destroyed(false), - m_initialized(false), + m_ioid(INVALID_IOID), m_pendingRequest(NULL_REQUEST), - m_ioid(INVALID_IOID) + m_destroyed(false), + m_initialized(false) { } @@ -271,10 +271,6 @@ namespace epics { // default is noop } - virtual void lock() { - // noop - } - virtual void send(ByteBuffer* buffer, TransportSendControl* control) { int8 qos = getPendingRequest(); if (qos == -1) @@ -288,10 +284,6 @@ namespace epics { stopRequest(); } - virtual void unlock() { - // noop - } - }; @@ -437,6 +429,14 @@ namespace epics { { BaseRequestImpl::destroy(); } + + virtual void lock() { + // noop + } + + virtual void unlock() { + // noop + } }; @@ -458,6 +458,8 @@ namespace epics { PVStructure::shared_pointer m_data; BitSet::shared_pointer m_bitSet; + + Mutex m_dataMutex; ChannelGetImpl(ChannelImpl::shared_pointer const & channel, ChannelGetRequester::shared_pointer const & channelGetRequester, PVStructure::shared_pointer const & pvRequest) : BaseRequestImpl(channel, static_pointer_cast(channelGetRequester)), @@ -608,6 +610,16 @@ namespace epics { { BaseRequestImpl::destroy(); } + + virtual void lock() + { + m_dataMutex.lock(); + } + + virtual void unlock() + { + m_dataMutex.unlock(); + } }; @@ -632,6 +644,8 @@ namespace epics { PVStructure::shared_pointer m_data; BitSet::shared_pointer m_bitSet; + Mutex m_dataMutex; + ChannelPutImpl(ChannelImpl::shared_pointer const & channel, ChannelPutRequester::shared_pointer const & channelPutRequester, PVStructure::shared_pointer const & pvRequest) : BaseRequestImpl(channel, static_pointer_cast(channelPutRequester)), m_channelPutRequester(channelPutRequester), m_pvRequest(pvRequest) @@ -821,6 +835,16 @@ namespace epics { { BaseRequestImpl::destroy(); } + + virtual void lock() + { + m_dataMutex.lock(); + } + + virtual void unlock() + { + m_dataMutex.unlock(); + } }; @@ -842,6 +866,8 @@ namespace epics { PVStructure::shared_pointer m_putData; PVStructure::shared_pointer m_getData; + Mutex m_dataMutex; + ChannelPutGetImpl(ChannelImpl::shared_pointer const & channel, ChannelPutGetRequester::shared_pointer const & channelPutGetRequester, PVStructure::shared_pointer const & pvRequest) : BaseRequestImpl(channel, static_pointer_cast(channelPutGetRequester)), m_channelPutGetRequester(channelPutGetRequester), m_pvRequest(pvRequest) @@ -1079,6 +1105,17 @@ namespace epics { { BaseRequestImpl::destroy(); } + + virtual void lock() + { + m_dataMutex.lock(); + } + + virtual void unlock() + { + m_dataMutex.unlock(); + } + }; @@ -1101,6 +1138,8 @@ namespace epics { PVStructure::shared_pointer m_data; BitSet::shared_pointer m_bitSet; + + Mutex m_dataMutex; ChannelRPCImpl(ChannelImpl::shared_pointer const & channel, ChannelRPCRequester::shared_pointer const & channelRPCRequester, PVStructure::shared_pointer const & pvRequest) : BaseRequestImpl(channel, static_pointer_cast(channelRPCRequester)), @@ -1259,6 +1298,16 @@ namespace epics { { BaseRequestImpl::destroy(); } + + virtual void lock() + { + m_dataMutex.lock(); + } + + virtual void unlock() + { + m_dataMutex.unlock(); + } }; @@ -1285,6 +1334,8 @@ namespace epics { int32 m_length; int32 m_capacity; + + Mutex m_dataMutex; ChannelArrayImpl(ChannelImpl::shared_pointer const & channel, ChannelArrayRequester::shared_pointer const & channelArrayRequester, PVStructure::shared_pointer const & pvRequest) : BaseRequestImpl(channel, static_pointer_cast(channelArrayRequester)), @@ -1522,6 +1573,16 @@ namespace epics { { BaseRequestImpl::destroy(); } + + virtual void lock() + { + m_dataMutex.lock(); + } + + virtual void unlock() + { + m_dataMutex.unlock(); + } }; @@ -2242,6 +2303,16 @@ namespace epics { m_monitorStrategy->release(monitorElement); } + virtual void lock() + { + // noop + } + + virtual void unlock() + { + // noop + } + }; diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index 04f265a..5e6f874 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -152,9 +152,17 @@ class MockChannelProcess : virtual void destroy() { - + } + + virtual void lock() + { + // TODO !!! } + virtual void unlock() + { + // TODO !!! + } }; @@ -212,6 +220,15 @@ class MockChannelGet : public ChannelGet { } + virtual void lock() + { + // TODO !!! + } + + virtual void unlock() + { + // TODO !!! + } }; @@ -266,6 +283,15 @@ class MockChannelPut : public ChannelPut { } + virtual void lock() + { + // TODO !!! + } + + virtual void unlock() + { + // TODO !!! + } }; @@ -322,6 +348,15 @@ class MockChannelPutGet : public ChannelPutGet { } + virtual void lock() + { + // TODO !!! + } + + virtual void unlock() + { + // TODO !!! + } }; @@ -371,6 +406,15 @@ class MockChannelRPC : public ChannelRPC { } + virtual void lock() + { + // TODO !!! + } + + virtual void unlock() + { + // TODO !!! + } }; @@ -442,6 +486,15 @@ class MockChannelArray : public ChannelArray { } + virtual void lock() + { + // TODO !!! + } + + virtual void unlock() + { + // TODO !!! + } }; @@ -541,6 +594,16 @@ class MockMonitor : public Monitor, public MonitorElement, public std::tr1::enab stop(); } + virtual void lock() + { + // TODO !!! + } + + virtual void unlock() + { + // TODO !!! + } + // ============ MonitorElement ============ virtual PVStructure::shared_pointer const & getPVStructure()