merge branch release/4.0

This commit is contained in:
Marty Kraimer
2014-12-11 14:11:54 -05:00
41 changed files with 2712 additions and 1058 deletions

View File

@@ -24,6 +24,8 @@ namespace epics { namespace pvData {
typedef std::tr1::shared_ptr<BitSet> BitSetPtr;
/**
* @brief A vector of bits.
*
* This class implements a vector of bits that grows as needed. Each
* component of the bit set has a {@code bool} value. The
* bits of a {@code BitSet} are indexed by nonnegative integers.

View File

@@ -188,7 +188,8 @@ inline double swap(double val)
#endif
/**
* This class implements {@code Bytebuffer} that is like the {@code java.nio.ByteBuffer}.
* @brief This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
*
* <p>A {@code BitSet} is not safe for multithreaded use without
* external synchronization.
*

View File

@@ -18,7 +18,8 @@ namespace epics { namespace pvData {
/**
* Instance declaring destroy method.
* @brief Instance declaring destroy method.
*
* @author mse
*/
class epicsShareClass Destroyable {

View File

@@ -202,13 +202,26 @@ do { \
#define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0)
#endif // THROW_EXCEPTION_COMPAT
/**
* @brief Base for pvData exceptions.
*
*/
class epicsShareClass BaseException : public std::logic_error {
public:
/**
* Constructor.
*/
explicit BaseException(const std::string msg) : std::logic_error(msg) {}
/**
* Destructor.
*/
virtual ~BaseException() throw(){};
/**
*
* Reason for excepton.
*/
virtual const char* what() const throw();
private:

View File

@@ -35,14 +35,41 @@ namespace epics { namespace pvData {
class Event;
typedef std::tr1::shared_ptr<Event> EventPtr;
/**
* @brief C++ wrapper for epicsEvent from EPICS base.
*
*/
class epicsShareClass Event {
public:
POINTER_DEFINITIONS(Event);
/**
* Constructor
*/
explicit Event(bool = false);
/**
* Destructor.
*/
~Event();
/**
* Signal the event i.e. ensures that the next or current call to wait completes.
*/
void signal();
/**
* wait
* @return (false,true) if (some error, event signaled).
* The next wait or tryWait will clear signal.
*/
bool wait (); /* blocks until full */
/**
* wait for up to timeOut seconds.
* @param timeOut max number of seconds to wait
* @return (false, true) if (timeout or error, event signaled).
*/
bool wait ( double timeOut ); /* false if empty at time out */
/**
* See if a signal has been called.
* @return (false, true) if (timeout or error, event signaled).
*/
bool tryWait (); /* false if empty */
private:
epicsEventId id;

View File

@@ -27,22 +27,56 @@ class Executor;
typedef std::tr1::shared_ptr<Command> CommandPtr;
typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
/**
* @brief A command to be called by Executor
*
*/
class epicsShareClass Command {
public:
POINTER_DEFINITIONS(Command);
/**
*
* Destructor
*/
virtual ~Command(){}
/**
*
* The command that is executed.
*/
virtual void command() = 0;
private:
CommandPtr next;
friend class Executor;
};
/**
* @brief A class that executes commands.
*
*/
class epicsShareClass Executor : public Runnable{
public:
POINTER_DEFINITIONS(Executor);
/**
* Constructor
*
* @param threadName name for the executor thread.
* @param priority The thread priority.
*/
Executor(std::string const & threadName,ThreadPriority priority);
/**
* Destructor
*/
~Executor();
void execute(CommandPtr const &node);
/**
*
* Request to execute a command.
* @param command A shared pointer to the command instance.
*/
void execute(CommandPtr const &command);
/**
*
* The thread run method.
*/
virtual void run();
private:
CommandPtr head;

View File

@@ -38,12 +38,30 @@ namespace epics { namespace pvData {
typedef epicsMutex Mutex;
/**
* @brief A lock for multithreading
*
* This is based on item 14 of
* * Effective C++, Third Edition, Scott Meyers
*/
class epicsShareClass Lock : private NoDefaultMethods {
public:
/**
* Constructor
* @param m The mutex for the facility being locked.
*/
explicit Lock(Mutex &m)
: mutexPtr(m), locked(true)
{ mutexPtr.lock();}
/**
* Destructor
* Note that destructor does an automatic unlock.
*/
~Lock(){unlock();}
/**
* Take the lock
* Recursive locks are supported but each lock must be matched with an unlock.
*/
void lock()
{
if(!locked)
@@ -52,6 +70,9 @@ public:
locked = true;
}
}
/**
* release the lock.
*/
void unlock()
{
if(locked)
@@ -60,6 +81,10 @@ public:
locked=false;
}
}
/**
* If lock is not held take the lock.
* @return (false,true) if caller (does not have, has) the lock.
*/
bool tryLock()
{
if(locked) return true;
@@ -69,6 +94,10 @@ public:
}
return false;
}
/**
* See if caller has the lock,
* @return (false,true) if caller (does not have, has) the lock.
*/
bool ownsLock() const{return locked;}
private:
Mutex &mutexPtr;

View File

@@ -28,10 +28,26 @@ typedef std::tr1::shared_ptr<MessageNode> MessageNodePtr;
typedef std::vector<MessageNodePtr> MessageNodePtrArray;
typedef std::tr1::shared_ptr<MessageQueue> MessageQueuePtr;
/**
* @brief A node that can be put on a MessageQueue.
*
*/
class epicsShareClass MessageNode {
public:
/**
* Constructor
*/
MessageNode();
/**
*
* Get the message value.
* @return The message value.
*/
std::string getMessage() const;
/**
* Get the message type.
* @return The message type which is defined in Requester.
*/
MessageType getMessageType() const;
private:
std::string message;
@@ -39,19 +55,65 @@ private:
friend class MessageQueue;
};
/**
* @brief A bounded queue for messages.
*
*
*/
class epicsShareClass MessageQueue : public Queue<MessageNode> {
public:
POINTER_DEFINITIONS(MessageQueue);
/**
* Factory method to create a MessageQueue.
* @param size The number of MessageNodes in the queue.
* @return shared_ptr to MessageQueue.
*/
static MessageQueuePtr create(int size);
/**
* Constructor
* @param nodeArray an array of shared_ptr to MessageNodes,
*/
MessageQueue(MessageNodePtrArray &nodeArray);
/**
* Destructor
*/
virtual ~MessageQueue();
/**
* get the next MessageNode of the queue.
* @return A shared_ptr to the MessageNode.
* This will be a null pointer if queue is empty.
* If get is successful then release for this MessageNode
* must be called before another get can be issued.
*/
MessageNodePtr &get();
// must call release before next get
/**
* Release the MessageNode that was returned by the previous call to get.
*/
void release();
// return (false,true) if message (was not, was) put into queue
/**
*
* put a message into the message queue
* @param message The message string.
* @param messageType The message type as defined in Requester,
* @param replaceLast If true and queue is full then replace.
* @return (false,true) if a message (was not, was) put in queiue.
*/
bool put(std::string message,MessageType messageType,bool replaceLast);
/**
* Is queue empty?
* @return (false,true) if (is not, is) empty.
*/
bool isEmpty() ;
/**
* Is queue full?
* @return (false,true) if (is not, is) full.
*/
bool isFull() ;
/**
*
* Clear number of times queue was overrun and return the number
* of times the queue was overrun.
*/
int getClearOverrun();
private:
MessageNodePtr nullNode;

View File

@@ -17,17 +17,26 @@ namespace epics { namespace pvData {
* Effective C++, Third Edition, Scott Meyers
*/
class epicsShareClass NoDefaultMethods {
protected:
// allow by derived objects
/**
* @brief Base class for not allowing default methods.
*
* Note that copy constructor a copy methods are declared private.
*/
class epicsShareClass NoDefaultMethods {
protected:
/**
* Constructor
*/
NoDefaultMethods(){};
/**
* Destructor
*/
~NoDefaultMethods(){}
private:
// do not implment
NoDefaultMethods(const NoDefaultMethods&);
NoDefaultMethods & operator=(const NoDefaultMethods &);
};
};
}}
#endif /* NO_DEFAULT_METHODS_H */

View File

@@ -18,6 +18,12 @@
namespace epics { namespace pvData {
/**
* @brief Template class for a bounded queue.
*
* An instance can make a queueElement be any class desired
* but must create a std::vector of shared_ptr to queueElements.
*/
template <typename T>
class Queue
{
@@ -25,15 +31,58 @@ public:
POINTER_DEFINITIONS(Queue);
typedef std::tr1::shared_ptr<T> queueElementPtr;
typedef std::vector<queueElementPtr> queueElementPtrArray;
Queue(queueElementPtrArray &);
/**
* Constructor
* @param elementArray The vector of shared_ptr to queue elements.
*/
Queue(queueElementPtrArray & elementArray);
/**
* Destructor
*/
virtual ~Queue();
/**
* Clear the queue.
*/
void clear();
/**
* get the capacity of the queue, i. e. number of queue elements,
* @return The capacity.
*/
int capacity();
/**
* Get the number of free elements in the queue.
* @return The number.
*/
int getNumberFree();
/**
* Get the number of used elements in the queue.
* This is the number that have been setUsed but not released.
* @return The number.
*/
int getNumberUsed();
/**
* Get the next free element.
* @return a shared_ptr to the queue element.
* This is null if queue was full.
*/
queueElementPtr & getFree();
/**
* Set the element returned by getFree as used.
* Until this is called getUsed will not return it.
* @param element The element. It must be the element returned
* by the most recent call to getUsed.
*/
void setUsed(queueElementPtr const &element);
/**
* Get the oldest used element;
* @return a shared_ptr to the queue element.
* This is null if no used element is available.`
*/
queueElementPtr & getUsed();
/**
* Release the element obtained by the most recent call to getUsed.
* @param element The element.
*/
void releaseUsed(queueElementPtr const &element);
private:
queueElementPtr nullElement;

View File

@@ -28,11 +28,43 @@ enum MessageType {
epicsShareExtern std::string getMessageTypeName(MessageType messageType);
/**
* @brief Callback class for passing messages to a requester.
*
* This is used by many other classes and also extended by other classes.
* The request is passed a message and a messageType.
* A message is just a string and a messageType is:
@code
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
@endcode
*
*/
class epicsShareClass Requester {
public:
POINTER_DEFINITIONS(Requester);
/**
* Destructor
*/
virtual ~Requester(){}
/**
* The requester must have a name.
* @return The requester's name.
*/
virtual std::string getRequesterName() = 0;
/**
*
* A message for the requester.
* @param message The message.
* @param messageType The type of message:
@code
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
@endcode
*/
virtual void message(std::string const & message,MessageType messageType) = 0;
};

View File

@@ -25,52 +25,185 @@ namespace epics { namespace pvData {
class BitSet;
class Field;
/**
* @brief Callback class for serialization.
*
* This must be provided by code that calls serialize.
*/
class epicsShareClass SerializableControl {
public:
/**
* Destructor.
*/
virtual ~SerializableControl(){}
/**
* Done with this buffer. Flush it.
*/
virtual void flushSerializeBuffer() =0;
/**
* Make sure buffer has at least size bytes remaining.
* If not flush existing buffer and provide a new one.
* @param size The number of bytes.
*/
virtual void ensureBuffer(std::size_t size) =0;
/**
* Add pad bytes to buffer.
* @param alignment allignment required.
*/
virtual void alignBuffer(std::size_t alignment) =0;
virtual bool directSerialize(ByteBuffer *existingBuffer, const char* toSerialize,
std::size_t elementCount, std::size_t elementSize) = 0;
virtual void cachedSerialize(std::tr1::shared_ptr<const Field> const & field, ByteBuffer* buffer) = 0;
/**
* method for serializing array data.
* This should only be used for arrays of primitive types.
* i. e. boolean,byte,...,double.
* It can not be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param toSerialize location of data to be put into buffer.
* @param elementCount number of elements.
* @param elementSize element size.
*/
virtual bool directSerialize(
ByteBuffer *existingBuffer,
const char* toSerialize,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* serialize via cache
* @param field instance to be serialized
* @param buffer buffer to be serialized to
*/
virtual void cachedSerialize(
std::tr1::shared_ptr<const Field> const & field,
ByteBuffer* buffer) = 0;
};
/**
* @brief Callback class for deserialization.
*
* This must be provided by code that calls deserialize.
*/
class epicsShareClass DeserializableControl {
public:
/**
* Destructor.
*/
virtual ~DeserializableControl(){}
/**
* Helper method.
* Ensures specified size of bytes, provides it if necessary.
* @param size The number of bytes.
*/
virtual void ensureData(std::size_t size) =0;
/**
* Align buffer.
* Note that this takes care only current buffer alignment.
* If streaming protocol is used,
* care must be taken that entire stream is aligned.
* @param alignment size in bytes, must be power of two.
*/
virtual void alignData(std::size_t alignment) =0;
virtual bool directDeserialize(ByteBuffer *existingBuffer, char* deserializeTo,
std::size_t elementCount, std::size_t elementSize) = 0;
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(ByteBuffer* buffer) = 0;
/**
* method for deserializing array data.
* This should only be used for arrays of primitive types.
* i. e. boolean,byte,...,double.
* It can not be called for string, structure, or union arrays.
* @param existingBuffer the existing buffer from the caller.
* @param deserializeTo location of data.
* @param elementCount number of elements.
* @param elementSize element size.
*/
virtual bool directDeserialize(
ByteBuffer *existingBuffer,
char* deserializeTo,
std::size_t elementCount,
std::size_t elementSize) = 0;
/**
* deserialize via cache
* @param field instance to be deserialized
* @param buffer buffer to be deserialized from
*/
virtual std::tr1::shared_ptr<const Field> cachedDeserialize(
ByteBuffer* buffer) = 0;
};
/**
* @brief Base class for serialization.
*
*/
class epicsShareClass Serializable {
public:
/**
* Destructor.
*/
virtual ~Serializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher) = 0;
};
/**
* @brief Class for serializing bitSets.
*
*/
class epicsShareClass BitSetSerializable {
public:
/**
* Destructor.
*/
virtual ~BitSetSerializable(){}
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
* &param bitSet The bitSet to serialize.
*/
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher,BitSet *bitSet) const = 0;
/**
* Deserialize buffer.
* @param buffer serialization buffer.
* @param flusher deserialization control.
* &param bitSet The bitSet to deserialize.
*/
virtual void deserialize(ByteBuffer *buffer,
DeserializableControl *flusher,BitSet *bitSet) = 0;
};
/**
* @brief Class for serializing arrays.
*
*/
class epicsShareClass SerializableArray : public virtual Serializable {
public:
/**
* Destructor.
*/
virtual ~SerializableArray(){}
using Serializable::serialize;
virtual void serialize(ByteBuffer *buffer,
SerializableControl *flusher, std::size_t offset, std::size_t count) const = 0;
/**
* Serialize field into given buffer.
* @param buffer serialization buffer.
* @param flusher flush interface.
* &param offset offset in elements.
* @param count number of elements
*/
virtual void serialize(
ByteBuffer *buffer,
SerializableControl *flusher,
std::size_t offset,
std::size_t count) const = 0;
};
}}

View File

@@ -23,6 +23,10 @@
namespace epics {
namespace pvData {
/**
* @brief Serialization helper.
*
*/
class epicsShareClass SerializeHelper : public NoDefaultMethods {
public:

View File

@@ -527,9 +527,12 @@ public:
};
//! Specialization for storing untyped pointers
//! Does not allow access or iteration of contents
//! other than as void* or const void*
/**
* @brief Specialization for storing untyped pointers.
*
* Does not allow access or iteration of contents
* other than as void* or const void*
*/
template<typename E>
class shared_vector<E, typename meta::is_void<E>::type >
: public detail::shared_vector_base<E>

View File

@@ -21,7 +21,9 @@
namespace epics { namespace pvData {
/**
* Status.
* @brief Status.
*
* This is a class for returning status to clients.
* @author mse
*/
class epicsShareClass Status : public epics::pvData::Serializable {

View File

@@ -47,9 +47,28 @@ typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
typedef epicsThreadRunable Runnable;
/**
* @brief C++ wrapper for epicsThread from EPICS base.
*
*/
class epicsShareClass Thread : public epicsThread, private NoDefaultMethods {
public:
/**
*
* Constructor
* @param name thread name.
* @param priority priority is one of:
@code
enum ThreadPriority {
lowestPriority, lowerPriority, lowPriority,
middlePriority,
highPriority, higherPriority, highestPriority
};
@endcode
* @param runnable this is a c function
* @param stkcls stack size as specified by epicsThreadStackSizeClass
*/
Thread(std::string name,
ThreadPriority priority,
Runnable *runnable,
@@ -62,6 +81,21 @@ public:
this->start();
}
/**
*
* Constructor
* @param runnable this is a c function
* @name thread name.
* @param stkcls stack size as specified by epicsThreadStackSizeClass
* @param priority priority is one of:
@code
enum ThreadPriority {
lowestPriority, lowerPriority, lowPriority,
middlePriority,
highPriority, higherPriority, highestPriority
};
@endcode
*/
Thread(Runnable &runnable,
std::string name,
unsigned int stksize,
@@ -74,6 +108,9 @@ public:
this->start();
}
/**
* Destructor
*/
~Thread()
{
this->exitWait();

View File

@@ -21,19 +21,46 @@ class TimeFunction;
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
/**
* @brief Class that must be implemented by timeFunction requester.
*
*/
class epicsShareClass TimeFunctionRequester {
public:
POINTER_DEFINITIONS(TimeFunctionRequester);
/**
* Destructor
*/
virtual ~TimeFunctionRequester(){}
/**
* function to be timed.
* It will get called multiple times.
*/
virtual void function() = 0;
};
/**
* @brief Class for measuring time it takes to execute a function.
*
*/
class epicsShareClass TimeFunction {
public:
POINTER_DEFINITIONS(TimeFunction);
/**
* Constructor
* @param requester The class that has a function method.
*/
TimeFunction(TimeFunctionRequesterPtr const & requester);
/**
* Destructor
*/
~TimeFunction();
/**
* Time the function.
* @return the time in seconds to execute the function.
* Note that the function may be called many times.
*/
double timeCall();
private:
TimeFunctionRequesterPtr requester;

View File

@@ -32,12 +32,28 @@ class Timer;
typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
typedef std::tr1::shared_ptr<Timer> TimerPtr;
/**
* @brief Class that must be implemented by code that makes Timer requests.
*
*/
class epicsShareClass TimerCallback {
public:
POINTER_DEFINITIONS(TimerCallback);
/**
* Constructor
*/
TimerCallback();
/**
* Destructor
*/
virtual ~TimerCallback(){}
/**
* The method that is called when a timer expires.
*/
virtual void callback() = 0;
/**
* The timer has stopped.
*/
virtual void timerStopped() = 0;
private:
TimerCallbackPtr next;
@@ -47,22 +63,60 @@ private:
friend class Timer;
};
/**
* @brief Support for delayed or periodic callback execution.
*
*/
class epicsShareClass Timer : public Runnable {
public:
POINTER_DEFINITIONS(Timer);
/**
* Contructor
* @param threadName name for the timer thread.
* @param priority thread priority
*/
Timer(std::string threadName, ThreadPriority priority);
/**
* Destructor
*/
virtual ~Timer();
/**
* The thead run method. This is called automatically.
*/
virtual void run();
/**
* schedule a callback after a delay.
* @param timerCallback the timerCallback instance.
* @param delay number of seconds before calling callback.
*/
void scheduleAfterDelay(
TimerCallbackPtr const &timerCallback,
double delay);
/**
* schedule a periodic callback.`
* @param timerCallback the timerCallback instance.
* @param delay number of seconds before first callback.
* @param period time in seconds between each callback.
*/
void schedulePeriodic(
TimerCallbackPtr const &timerCallback,
double delay,
double period);
/**
* cancel a callback.
* @param timerCallback the timerCallback to cancel.
*/
void cancel(TimerCallbackPtr const &timerCallback);
/**
* Is the callback scheduled to be called?
* @param timerCallback the timerCallback.
* @return (false,true) if (not, is) scheduled.
*/
bool isScheduled(TimerCallbackPtr const &timerCallback);
/**
* show the elements in the timer queue.
* @parm o The output stream for the output
*/
void dump(std::ostream& o);
private: