diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index 54de4b1..854d305 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -41,7 +41,6 @@ LIBSRCS += timer.cpp LIBSRCS += queueVoid.cpp LIBSRCS += messageQueue.cpp LIBSRCS += status.cpp -LIBSRCS += StatusCreateFactory.cpp SRC_DIRS += $(PVDATA)/pv diff --git a/pvDataApp/factory/DefaultPVStructureArray.cpp b/pvDataApp/factory/DefaultPVStructureArray.cpp index e81a9a0..f28cf1d 100644 --- a/pvDataApp/factory/DefaultPVStructureArray.cpp +++ b/pvDataApp/factory/DefaultPVStructureArray.cpp @@ -32,11 +32,11 @@ namespace epics { namespace pvData { virtual bool operator!=(PVField &pv); virtual void shareData( PVStructurePtrArray value,int capacity,int length); virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher); + SerializableControl *pflusher) const; virtual void deserialize(ByteBuffer *buffer, DeserializableControl *pflusher); virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count); + SerializableControl *pflusher, int offset, int count) const; private: StructureArrayConstPtr structureArray; StructureArrayData *structureArrayData; @@ -213,7 +213,7 @@ namespace epics { namespace pvData { } void BasePVStructureArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) { + SerializableControl *pflusher) const { serialize(pbuffer, pflusher, 0, getLength()); } @@ -247,7 +247,7 @@ namespace epics { namespace pvData { } void BasePVStructureArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) { + SerializableControl *pflusher, int offset, int count) const { // cache int length = getLength(); diff --git a/pvDataApp/factory/PVArray.cpp b/pvDataApp/factory/PVArray.cpp index ed4bd36..cdbb98e 100644 --- a/pvDataApp/factory/PVArray.cpp +++ b/pvDataApp/factory/PVArray.cpp @@ -32,9 +32,9 @@ namespace epics { namespace pvData { delete pImpl; } - int PVArray::getLength() {return pImpl->length;} + int PVArray::getLength() const {return pImpl->length;} - int PVArray::getCapacity() {return pImpl->capacity;} + int PVArray::getCapacity() const {return pImpl->capacity;} static String fieldImmutable("field is immutable"); diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index afb3721..6f92353 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -40,7 +40,7 @@ public: virtual T get(); virtual void put(T val); virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher); + SerializableControl *pflusher) const; virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher); virtual bool operator==(PVField& pv) ; @@ -66,7 +66,7 @@ void BasePVScalar::put(T val){value = val;} template void BasePVScalar::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) { + SerializableControl *pflusher) const { pflusher->ensureBuffer(1); pbuffer->put(value); } @@ -100,7 +100,7 @@ BasePVScalar::BasePVScalar(PVStructure *parent,ScalarConstPtr scalar) template<> void BasePVScalar::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) { + SerializableControl *pflusher) const { SerializeHelper::serializeString(value, pbuffer, pflusher); } @@ -137,10 +137,10 @@ public: int fromOffset); virtual void shareData(pointer value,int capacity,int length); // from Serializable - virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) ; + virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const; virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher); virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) ; + SerializableControl *pflusher, int offset, int count) const; virtual bool operator==(PVField& pv) ; virtual bool operator!=(PVField& pv) ; private: @@ -231,7 +231,7 @@ void DefaultPVArray::shareData(pointer shareValue,int capacity,int length) template void DefaultPVArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) { + SerializableControl *pflusher) const { serialize(pbuffer, pflusher, 0, this->getLength()); } @@ -262,7 +262,7 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, template void DefaultPVArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) { + SerializableControl *pflusher, int offset, int count) const { // cache int length = this->getLength(); @@ -324,7 +324,7 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, template<> void DefaultPVArray::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, int offset, int count) { + SerializableControl *pflusher, int offset, int count) const { int length = getLength(); // check bounds diff --git a/pvDataApp/factory/PVStructure.cpp b/pvDataApp/factory/PVStructure.cpp index 540785f..6026559 100644 --- a/pvDataApp/factory/PVStructure.cpp +++ b/pvDataApp/factory/PVStructure.cpp @@ -432,7 +432,7 @@ namespace epics { namespace pvData { } void PVStructure::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) { + SerializableControl *pflusher) const { for(int i = 0; inumberFields; i++) pImpl->pvFields[i]->serialize(pbuffer, pflusher); } @@ -445,9 +445,9 @@ namespace epics { namespace pvData { } void PVStructure::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, BitSet *pbitSet) { - int offset = getFieldOffset(); - int numberFields = getNumberFields(); + SerializableControl *pflusher, BitSet *pbitSet) const { + int offset = const_cast(this)->getFieldOffset(); + int numberFields = const_cast(this)->getNumberFields(); int next = pbitSet->nextSetBit(offset); // no more changes or no changes in this structure diff --git a/pvDataApp/misc/StatusCreateFactory.cpp b/pvDataApp/misc/StatusCreateFactory.cpp deleted file mode 100644 index 0645e28..0000000 --- a/pvDataApp/misc/StatusCreateFactory.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/*StatusCreateFactory.cpp*/ -/** - * Copyright - See the COPYRIGHT that is included with this distribution. - * EPICS pvDataCPP is distributed subject to a Software License Agreement found - * in file LICENSE that is included with this distribution. - */ -#include -#include -#include -#include -#include "lock.h" -#include "factory.h" -#include "byteBuffer.h" -#include "CDRMonitor.h" -#include "status.h" -#include "serializeHelper.h" - -#include - -namespace epics { namespace pvData { - -// TODO disabled due to problem with static initialization (order) -//PVDATA_REFCOUNT_MONITOR_DEFINE(status); - -class StatusImpl : public Status -{ - public: - - StatusImpl(StatusType type, String message) : - m_type(type), m_message(message) - { - // PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status); - } - - StatusImpl(StatusType type, String message, String stackDump) : - m_type(type), m_message(message), m_stackDump(stackDump) - { - //PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status); - } - - virtual ~StatusImpl() { - //PVDATA_REFCOUNT_MONITOR_DESTRUCT(status); - } - - virtual StatusType getType() - { - return m_type; - } - - - virtual epics::pvData::String getMessage() - { - return m_message; - } - - virtual epics::pvData::String getStackDump() - { - return m_stackDump; - } - - virtual bool isOK() - { - return (m_type == STATUSTYPE_OK); - } - - virtual bool isSuccess() - { - return (m_type == STATUSTYPE_OK || m_type == STATUSTYPE_WARNING); - } - - virtual void serialize(ByteBuffer *buffer, SerializableControl *flusher) - { - flusher->ensureBuffer(1); - if (this == getStatusCreate()->getStatusOK()) - { - // special code for okStatus (optimization) - buffer->putByte((int8)-1); - } - else - { - buffer->putByte((int8)m_type); - SerializeHelper::serializeString(m_message, buffer, flusher); - SerializeHelper::serializeString(m_stackDump, buffer, flusher); - } - } - - virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) - { - throw new std::runtime_error("use getStatusCreate()->deserialize()"); - } - - virtual String toString() - { - String str; - toString(&str, 0); - return str; - } - - virtual void toString(StringBuilder buffer, int indentLevel) - { - *buffer += "StatusImpl [type="; - *buffer += StatusTypeName[m_type]; - if (!m_message.empty()) - { - *buffer += ", message="; - *buffer += m_message; - } - if (!m_stackDump.empty()) - { - *buffer += ", stackDump="; - *buffer += '\n'; - *buffer += m_stackDump; - } - *buffer += ']'; - } - - private: - - StatusType m_type; - String m_message; - String m_stackDump; - -}; - - - -static epicsThreadOnceId statusFactoryInit = EPICS_THREAD_ONCE_INIT; - - -class StatusCreateImpl : public StatusCreate { - public: - - StatusCreateImpl() - { - m_ok = createStatus(STATUSTYPE_OK, "OK", 0); - } - - ~StatusCreateImpl() - { - delete m_ok; - } - - virtual Status* getStatusOK() { - return m_ok; - } - - virtual Status* createStatus(StatusType type, String message, BaseException* cause) { - if (cause == 0) - return new StatusImpl(type, message); - else - { - return new StatusImpl(type, message, cause->what()); - } - } - - virtual Status* deserializeStatus(ByteBuffer* buffer, DeserializableControl* control) { - control->ensureData(1); - int8 typeCode = buffer->getByte(); - if (typeCode == (int8)-1) - return m_ok; - else { - String message = SerializeHelper::deserializeString(buffer, control); - String stackDump = SerializeHelper::deserializeString(buffer, control); - return new StatusImpl((StatusType)typeCode, message, stackDump); - } - } - - static StatusCreateImpl* getInstance() - { - epicsThreadOnce(&statusFactoryInit, &StatusCreateImpl::init, 0); - assert(singleton); - return singleton; - } - - private: - - Status* m_ok; - - static StatusCreateImpl *singleton; - - static void init(void*) { - singleton = new StatusCreateImpl(); - } - -}; - - - - -StatusCreateImpl* StatusCreateImpl::singleton = 0; - -StatusCreate* getStatusCreate() { - return StatusCreateImpl::getInstance(); -} - -}} diff --git a/pvDataApp/misc/bitSet.cpp b/pvDataApp/misc/bitSet.cpp index 353b42b..ef94f46 100644 --- a/pvDataApp/misc/bitSet.cpp +++ b/pvDataApp/misc/bitSet.cpp @@ -341,7 +341,7 @@ namespace epics { namespace pvData { *buffer += '}'; } - void BitSet::serialize(ByteBuffer* buffer, SerializableControl* flusher) { + void BitSet::serialize(ByteBuffer* buffer, SerializableControl* flusher) const { uint32 n = wordsInUse; if (n == 0) { diff --git a/pvDataApp/misc/bitSet.h b/pvDataApp/misc/bitSet.h index 525e111..89f0af0 100644 --- a/pvDataApp/misc/bitSet.h +++ b/pvDataApp/misc/bitSet.h @@ -217,7 +217,7 @@ namespace epics { namespace pvData { void toString(StringBuilder buffer, int indentLevel = 0) const; virtual void serialize(ByteBuffer *buffer, - SerializableControl *flusher); + SerializableControl *flusher) const; virtual void deserialize(ByteBuffer *buffer, DeserializableControl *flusher); diff --git a/pvDataApp/misc/serialize.h b/pvDataApp/misc/serialize.h index 7fa7559..cdbe224 100644 --- a/pvDataApp/misc/serialize.h +++ b/pvDataApp/misc/serialize.h @@ -30,7 +30,7 @@ namespace epics { namespace pvData { class Serializable { public: virtual void serialize(ByteBuffer *buffer, - SerializableControl *flusher) = 0; + SerializableControl *flusher) const = 0; virtual void deserialize(ByteBuffer *buffer, DeserializableControl *flusher) = 0; }; @@ -38,7 +38,7 @@ namespace epics { namespace pvData { class BitSetSerializable { public: virtual void serialize(ByteBuffer *buffer, - SerializableControl *flusher,BitSet *bitSet) = 0; + SerializableControl *flusher,BitSet *bitSet) const = 0; virtual void deserialize(ByteBuffer *buffer, DeserializableControl *flusher,BitSet *bitSet) = 0; }; @@ -47,7 +47,7 @@ namespace epics { namespace pvData { class SerializableArray : virtual public Serializable { public: virtual void serialize(ByteBuffer *buffer, - SerializableControl *flusher, int offset, int count) = 0; + SerializableControl *flusher, int offset, int count) const = 0; }; }} diff --git a/pvDataApp/misc/status.cpp b/pvDataApp/misc/status.cpp index ba6a532..61a341d 100644 --- a/pvDataApp/misc/status.cpp +++ b/pvDataApp/misc/status.cpp @@ -4,10 +4,132 @@ * EPICS pvDataCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ -#include +#include "status.h" +#include "epicsException.h" +#include "serializeHelper.h" namespace epics { namespace pvData { -const char* StatusTypeName[] = { "OK", "WARNING", "ERROR", "FATAL" }; +const char* Status::StatusTypeName[] = { "OK", "WARNING", "ERROR", "FATAL" }; +epics::pvData::String Status::m_emptyString; + +Status Status::OK; + +//PVDATA_REFCOUNT_MONITOR_DEFINE(status); + +Status::Status() : + m_type(STATUSTYPE_OK), m_message(m_emptyString), m_stackDump(m_emptyString) +{ +} + +Status::Status(StatusType type, String message) : + m_type(type), m_message(message), m_stackDump(m_emptyString) +{ + if (type == STATUSTYPE_OK) + throw std::invalid_argument("type == STATUSTYPE_OK"); + + //PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status); +} + +Status::Status(StatusType type, String message, String stackDump) : + m_type(type), m_message(message), m_stackDump(stackDump) +{ + if (type == STATUSTYPE_OK) + throw std::invalid_argument("type == STATUSTYPE_OK"); + + //PVDATA_REFCOUNT_MONITOR_CONSTRUCT(status); +} + +Status::~Status() { + //PVDATA_REFCOUNT_MONITOR_DESTRUCT(status); +} + +Status::StatusType Status::getType() const +{ + return m_type; +} + + +epics::pvData::String Status::getMessage() const +{ + return m_message; +} + +epics::pvData::String Status::getStackDump() const +{ + return m_stackDump; +} + +bool Status::isOK() const +{ + return (m_type == STATUSTYPE_OK); +} + +bool Status::isSuccess() const +{ + return (m_type == STATUSTYPE_OK || m_type == STATUSTYPE_WARNING); +} + +void Status::serialize(ByteBuffer *buffer, SerializableControl *flusher) const +{ + flusher->ensureBuffer(1); + if (m_type == STATUSTYPE_OK) + { + // special code for okStatus (optimization) + buffer->putByte((int8)-1); + } + else + { + buffer->putByte((int8)m_type); + SerializeHelper::serializeString(m_message, buffer, flusher); + SerializeHelper::serializeString(m_stackDump, buffer, flusher); + } +} + +void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher) +{ + flusher->ensureData(1); + int8 typeCode = buffer->getByte(); + if (typeCode == (int8)-1) + { + // in most of the cases status will be OK, we statistically optimize + if (m_type != STATUSTYPE_OK) + { + m_type = STATUSTYPE_OK; + m_message = m_stackDump = m_emptyString; + } + } + else + { + m_type = (StatusType)typeCode; + m_message = SerializeHelper::deserializeString(buffer, flusher); + m_stackDump = SerializeHelper::deserializeString(buffer, flusher); + } +} + +String Status::toString() const +{ + String str; + toString(&str, 0); + return str; +} + +void Status::toString(StringBuilder buffer, int indentLevel) const +{ + *buffer += "Status [type="; + *buffer += StatusTypeName[m_type]; + if (!m_message.empty()) + { + *buffer += ", message="; + *buffer += m_message; + } + if (!m_stackDump.empty()) + { + *buffer += ", stackDump="; + *buffer += '\n'; + *buffer += m_stackDump; + } + *buffer += ']'; +} }} \ No newline at end of file diff --git a/pvDataApp/misc/status.h b/pvDataApp/misc/status.h index e4a5bf6..75d4957 100644 --- a/pvDataApp/misc/status.h +++ b/pvDataApp/misc/status.h @@ -8,53 +8,69 @@ #define STATUS_H #include "serialize.h" -#include "epicsException.h" #include "byteBuffer.h" -#include "noDefaultMethods.h" namespace epics { namespace pvData { - /** - * Status type enum. - */ - enum StatusType { - /** Operation completed successfully. */ - STATUSTYPE_OK, - /** Operation completed successfully, but there is a warning message. */ - STATUSTYPE_WARNING, - /** Operation failed due to an error. */ - STATUSTYPE_ERROR, - /** Operation failed due to an unexpected error. */ - STATUSTYPE_FATAL - }; - - extern const char* StatusTypeName[]; - /** - * Status interface. + * Status. * @author mse */ class Status : public epics::pvData::Serializable { public: - virtual ~Status() {}; + + /** + * Status type enum. + */ + enum StatusType { + /** Operation completed successfully. */ + STATUSTYPE_OK, + /** Operation completed successfully, but there is a warning message. */ + STATUSTYPE_WARNING, + /** Operation failed due to an error. */ + STATUSTYPE_ERROR, + /** Operation failed due to an unexpected error. */ + STATUSTYPE_FATAL + }; + + static const char* StatusTypeName[]; + + static Status OK; + + /** + * Creates OK status; STATUSTYPE_OK, empty message and stackDump. + */ + Status(); + + /** + * Create non-OK status. + */ + Status(StatusType type, epics::pvData::String message); + + /** + * Create non-OK status. + */ + Status(StatusType type, epics::pvData::String message, epics::pvData::String stackDump); + + ~Status(); /** * Get status type. * @return status type, non-null. */ - virtual StatusType getType() = 0; + StatusType getType() const; /** * Get error message describing an error. Required if error status. * @return error message. */ - virtual epics::pvData::String getMessage() = 0; + epics::pvData::String getMessage() const; /** * Get stack dump where error (exception) happened. Optional. * @return stack dump. */ - virtual epics::pvData::String getStackDump() = 0; + epics::pvData::String getStackDump() const; /** * Convenient OK test. Same as (getType() == StatusType.OK). @@ -63,54 +79,28 @@ namespace epics { namespace pvData { * @return OK status. * @see #isSuccess() */ - virtual bool isOK() = 0; + bool isOK() const; /** * Check if operation succeeded. * @return operation success status. */ - virtual bool isSuccess() = 0; + bool isSuccess() const; - virtual String toString() = 0; - virtual void toString(StringBuilder buffer, int indentLevel = 0) = 0; + String toString() const; + void toString(StringBuilder buffer, int indentLevel = 0) const; + void serialize(ByteBuffer *buffer, SerializableControl *flusher) const; + void deserialize(ByteBuffer *buffer, DeserializableControl *flusher); + + private: + + static epics::pvData::String m_emptyString; + + StatusType m_type; + String m_message; + String m_stackDump; }; - - /** - * Interface for creating status. - * @author mse - */ - class StatusCreate : private epics::pvData::NoDefaultMethods { - public: - /** - * Get OK status. Static instance should be returned. - * @return OK Status instance. - */ - virtual Status* getStatusOK() = 0; - - /** - * Create status. - * @param type status type, non-null. - * @param message message describing an error, non-null. - * NOTE: Do NOT use throwable.getMessage() as message, since it will be supplied with the cause. - * @param cause exception that caused an error. Optional. - * @return status instance. - */ - virtual Status* createStatus(StatusType type, String message, BaseException* cause = 0) = 0; - - /** - * Deserialize status. - * NOTE: use this method instead of Status.deserialize(), since this allows OK status optimization. - * @param buffer deserialization buffer. - * @param control deserialization control. - * @return status instance. - */ - virtual Status* deserializeStatus(ByteBuffer* buffer, DeserializableControl* control) = 0; - }; - - extern StatusCreate* getStatusCreate(); - - }} #endif /* STATUS_H */ diff --git a/pvDataApp/monitor/monitor.h b/pvDataApp/monitor/monitor.h index d2fc0f6..a5cf4eb 100644 --- a/pvDataApp/monitor/monitor.h +++ b/pvDataApp/monitor/monitor.h @@ -46,12 +46,12 @@ namespace epics { namespace pvData { * Start monitoring. * @return completion status. */ - virtual Status* start() = 0; + virtual Status start() = 0; /** * Stop Monitoring. * @return completion status. */ - virtual Status* stop() = 0; + virtual Status stop() = 0; /** * If monitor has occurred return data. * @return monitorElement for modified data on null if no monitors have occurred. @@ -77,7 +77,7 @@ namespace epics { namespace pvData { * @param monitor The monitor * @param structure The structure defining the data. */ - virtual void monitorConnect(Status* status, Monitor* monitor, Structure* structure) = 0; + virtual void monitorConnect(const Status &status, Monitor* monitor, Structure* structure) = 0; /** * A monitor event has occurred. The requester must call Monitor.poll to get data. * @param monitor The monitor. diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index 639cbc8..fc8fbf0 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -126,10 +126,10 @@ typedef PVScalarValue PVString; class PVArray : public PVField, public SerializableArray { public: virtual ~PVArray(); - int getLength() ; + int getLength() const; void setLength(int length); - int getCapacity() ; - bool isCapacityMutable() ; + int getCapacity() const; + bool isCapacityMutable(); void setCapacityMutable(bool isMutable); virtual void setCapacity(int capacity) = 0; @@ -212,11 +212,11 @@ public: virtual bool operator==(PVField &pv) ; virtual bool operator!=(PVField &pv) ; virtual void serialize( - ByteBuffer *pbuffer,SerializableControl *pflusher) ; + ByteBuffer *pbuffer,SerializableControl *pflusher) const; virtual void deserialize( ByteBuffer *pbuffer,DeserializableControl *pflusher); virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher,BitSet *pbitSet) ; + SerializableControl *pflusher,BitSet *pbitSet) const; virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl*pflusher,BitSet *pbitSet); protected: