more shared_pointer everywhere

This commit is contained in:
Marty Kraimer
2012-07-17 09:23:53 -04:00
parent 32790674d6
commit 5dcd864c58
25 changed files with 399 additions and 1507 deletions

View File

@@ -16,9 +16,6 @@ INC += serializeHelper.h
INC += event.h
INC += thread.h
INC += executor.h
INC += linkedList.h
INC += linkedListVoid.h
INC += CDRMonitor.h
INC += timeFunction.h
INC += timer.h
INC += queue.h
@@ -27,13 +24,11 @@ INC += destroyable.h
INC += status.h
INC += sharedPtr.h
LIBSRCS += CDRMonitor.cpp
LIBSRCS += byteBuffer.cpp
LIBSRCS += bitSet.cpp
LIBSRCS += epicsException.cpp
LIBSRCS += requester.cpp
LIBSRCS += serializeHelper.cpp
LIBSRCS += linkedListVoid.cpp
LIBSRCS += event.cpp
LIBSRCS += executor.cpp
LIBSRCS += timeFunction.cpp

View File

@@ -3316,9 +3316,6 @@ size_t copyNumericArray(PVScalarArray *from, size_t offset, PVScalarArray *to, s
}
return ncopy;
}
#ifdef XXXXXXXXX
#endif ///MARTY REMOVE THIS XXXXXXX
ConvertPtr Convert::getConvert()
{

View File

@@ -1,160 +0,0 @@
/* CDRMonitor.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 <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdexcept>
#include <epicsThread.h>
#include <pv/noDefaultMethods.h>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/linkedList.h>
#include <pv/CDRMonitor.h>
#ifdef _WIN32
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
namespace epics { namespace pvData {
static
epicsThreadOnceId monitorInit = EPICS_THREAD_ONCE_INIT;
// Must use a pointer w/ lazy init due to lack of
// initialization order guarantees
CDRMonitor* CDRMonitor::theone = 0;
CDRMonitor&
CDRMonitor::get()
{
epicsThreadOnce(&monitorInit, &CDRMonitor::init, 0);
assert(theone);
return *theone;
}
void
CDRMonitor::init(void *)
{
//BUG: No idea how to handle allocation failure at this stage.
theone=new CDRMonitor;
}
void
CDRMonitor::destroy()
{
if (theone)
{
CDRNode *node = theone->first();
while (node)
{
CDRNode* tmp = node;
node = node->next();
delete tmp;
}
delete theone;
theone = 0;
}
}
CDRMonitor::CDRMonitor()
:firstNode(0)
{}
CDRCount
CDRMonitor::current()
{
CDRCount total;
for(CDRNode *cur=first(); !!cur; cur=cur->next())
{
total+=cur->get();
}
return total;
}
void
CDRMonitor::show(FILE *fd, bool destroy)
{
for(CDRNode *cur=first(); !!cur; cur=cur->next())
{
cur->show(fd);
}
if (destroy)
CDRMonitor::destroy();
}
void
CDRMonitor::show(std::ostream& out, bool destroy) const
{
for(CDRNode *cur=first(); !!cur; cur=cur->next())
{
cur->show(out);
}
if (destroy)
CDRMonitor::destroy();
}
void
CDRNode::show(FILE *fd)
{
Lock x(guard);
if(!current.cons && !current.dtys && !current.refs)
return;
fprintf(fd,"%s: totalConstruct %lu totalDestruct %lu",
nodeName.c_str(), (unsigned long)current.cons,
(unsigned long)current.dtys);
ssize_t alive=current.cons;
alive-=current.dtys;
if(current.refs)
fprintf(fd," totalReference %ld", current.refs);
if(alive)
fprintf(fd," ACTIVE %ld\n", (long)alive);
else
fprintf(fd,"\n");
}
void
CDRNode::show(std::ostream& out) const
{
Lock x(guard);
if(!current.cons && !current.dtys && !current.refs)
return;
out<<nodeName<<" totalConstruct "<<current.cons
<<" totalDestruct "<<current.dtys;
ssize_t alive=current.cons;
alive-=current.dtys;
if(current.refs)
out<<" totalReference "<<current.refs;
if(alive)
out<<" ACTIVE "<<alive;
out<<"\n";
}
void
onceNode(void* raw)
{
CDRNodeInstance* inst=static_cast<CDRNodeInstance*>(raw);
inst->node=new CDRNode(inst->name);
}
}} // namespace epics::pvData
std::ostream& operator<<(std::ostream& out,const epics::pvData::CDRMonitor& mon)
{
mon.show(out);
return out;
}
std::ostream& operator<<(std::ostream& out,const epics::pvData::CDRNode& node)
{
node.show(out);
return out;
}

View File

@@ -1,140 +0,0 @@
/* CDRMonitor.h */
/**
* 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.
*/
#ifndef CDRMONITOR_H
#define CDRMONITOR_H
#include <ostream>
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <epicsThread.h>
#include <pv/noDefaultMethods.h>
#include <pv/lock.h>
#include <pv/pvType.h>
namespace epics { namespace pvData {
//! Used to pass around snapshots
struct CDRCount { // default copy and assignment are ok
size_t cons, dtys;
long refs;
CDRCount():cons(0),dtys(0),refs(0){}
CDRCount& operator+=(const CDRCount& o)
{cons+=o.cons; dtys+=o.dtys; refs+=o.refs; return *this;}
CDRCount& operator=(size_t count) // reset counters
{cons=count; dtys=count; refs=count; return *this;}
};
class CDRNode;
//! @brief Global registrar for CDRNodes
class CDRMonitor : private NoDefaultMethods {
public:
static CDRMonitor& get();
static void destroy();
CDRNode* addNode(CDRNode& next)
{
CDRNode *ret=firstNode;
firstNode=&next;
return ret;
}
CDRCount current(); //!< current global count
CDRNode* first() const{return firstNode;}
void show(FILE*, bool destroy = false);
void show(std::ostream&, bool destroy = false) const;
private:
// Private ctor for singleton
CDRMonitor();
CDRNode *firstNode;
static CDRMonitor *theone;
static void init(void*);
};
//! Counters for Construction, Destruction, and References of one class
class CDRNode : private NoDefaultMethods {
public:
CDRNode(const String& name)
:nodeName(name)
,current()
,guard()
,nextNode(CDRMonitor::get().addNode(*this))
{}
void construct(){Lock x(guard); current.cons++;}
void destruct(){Lock x(guard); current.dtys++;}
void incRef(){Lock x(guard); current.refs++;}
void decRef(){Lock x(guard); current.refs--;}
CDRNode* next() const{return nextNode;}
CDRCount get() const{Lock x(guard); return current;}
void show(FILE*);
void show(std::ostream&) const;
private:
const String nodeName;
CDRCount current;
mutable Mutex guard;
CDRNode * const nextNode;
};
struct CDRNodeInstance
{
CDRNode *node;
epicsThreadOnceId once;
const char* const name;
};
void onceNode(void* raw);
static inline
CDRNode*
getNode(CDRNodeInstance *inst)
{
epicsThreadOnce(&inst->once,&onceNode,
static_cast<void*>(inst));
return inst->node;
}
#ifndef NDEBUG
#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME) \
static CDRNodeInstance NAME ## _node={0,EPICS_THREAD_ONCE_INIT,#NAME}
#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME) \
getNode(&NAME ## _node)->destruct()
#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME) \
getNode(&NAME ## _node)->construct()
#define PVDATA_REFCOUNT_MONITOR_INCREF(NAME) \
getNode(&NAME ## _node)->incRef()
#define PVDATA_REFCOUNT_MONITOR_DECREF(NAME) \
getNode(&NAME ## _node)->decRef()
#else
#define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME)
#define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME)
#define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME)
#define PVDATA_REFCOUNT_MONITOR_INCREF(NAME)
#define PVDATA_REFCOUNT_MONITOR_DECREF(NAME)
#endif
}}
std::ostream& operator<<(std::ostream&,const epics::pvData::CDRMonitor&);
std::ostream& operator<<(std::ostream&,const epics::pvData::CDRNode&);
#endif /* CDRMONITOR_H */

View File

@@ -8,12 +8,10 @@
#include "stdio.h"
#include <pv/bitSet.h>
#include <pv/lock.h>
#include <pv/CDRMonitor.h>
#include <pv/serializeHelper.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(bitSet);
BitSet::shared_pointer BitSet::create(uint32 nbits)
{
return BitSet::shared_pointer(new BitSet(nbits));
@@ -22,19 +20,15 @@ namespace epics { namespace pvData {
BitSet::BitSet() : words(0), wordsLength(0), wordsInUse(0) {
initWords(BITS_PER_WORD);
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(bitSet);
}
BitSet::BitSet(uint32 nbits) : words(0), wordsLength(0), wordsInUse(0) {
initWords(nbits);
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(bitSet);
}
BitSet::~BitSet() {
delete[] words;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(bitSet);
}
void BitSet::initWords(uint32 nbits) {

View File

@@ -20,24 +20,20 @@
#include <pv/pvType.h>
#include <pv/lock.h>
#include <pv/event.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(event);
static String alreadyOn("already on list");
Event::~Event() {
epicsEventDestroy(id);
id = 0;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(event);
}
Event::Event(bool full)
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(event);
}
void Event::signal()

View File

@@ -9,13 +9,17 @@
#include <memory>
#include <vector>
#include <epicsEvent.h>
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
class Event : private NoDefaultMethods {
class Event;
typedef std::tr1::shared_ptr<Event> EventPtr;
class Event {
public:
POINTER_DEFINITIONS(Event);
explicit Event(bool = false);
~Event();
void signal();

View File

@@ -10,109 +10,55 @@
#include <string>
#include <cstdio>
#include <memory>
#include <vector>
#include <pv/linkedList.h>
#include <pv/lock.h>
#include <pv/thread.h>
#include <pv/event.h>
#include <pv/executor.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
// special instance to stop the executor thread
static
class ExecutorShutdown : public Command {
virtual void command(){};
} executorShutdown;
virtual void command();
};
void ExecutorShutdown::command()
{
}
static
Command *shutdown=&executorShutdown;
std::tr1::shared_ptr<Command> shutdown(new ExecutorShutdown());
PVDATA_REFCOUNT_MONITOR_DEFINE(executor);
typedef LinkedListNode<ExecutorNode> ExecutorListNode;
typedef LinkedList<ExecutorNode> ExecutorList;
class ExecutorNode {
public:
ExecutorNode(Command *command);
Command *command;
ExecutorListNode node;
ExecutorListNode runNode;
};
ExecutorNode::ExecutorNode(Command *command)
: command(command),
node(*this),
runNode(*this)
{}
class ExecutorPvt : public Runnable{
public:
ExecutorPvt(String threadName,ThreadPriority priority);
~ExecutorPvt();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
virtual void run();
private:
ExecutorList executorList;
ExecutorList runList;
Event moreWork;
Event stopped;
Mutex mutex;
Thread thread;
};
ExecutorPvt::ExecutorPvt(String threadName,ThreadPriority priority)
: executorList(),
runList(),
moreWork(),
stopped(),
mutex(),
thread(threadName,priority,this)
{}
ExecutorPvt::~ExecutorPvt()
Executor::Executor(String threadName,ThreadPriority priority)
: thread(threadName,priority,this)
{
ExecutorNode shutdownNode(shutdown);
}
execute(&shutdownNode);
Executor::~Executor()
{
execute(shutdown);
stopped.wait();
// The thread signals 'stopped' while still holding
// the lock. By taking it we wait for the run() function
// to actually return
Lock xx(mutex);
ExecutorListNode *node;
while((node=executorList.removeHead())!=0) {
delete &node->getObject();
}
head.reset();
tail.reset();
}
void ExecutorPvt::run()
void Executor::run()
{
Lock xx(mutex);
while(true) {
ExecutorListNode * executorListNode = 0;
while(runList.isEmpty()) {
while(head.get()==NULL) {
xx.unlock();
moreWork.wait();
xx.lock();
}
executorListNode = runList.removeHead();
if(!executorListNode) continue;
Command *cmd=executorListNode->getObject().command;
if(cmd==shutdown) break;
CommandPtr command = head;
if(command.get()==NULL) continue;
if(command.get()==shutdown.get()) break;
xx.unlock();
try {
executorListNode->getObject().command->command();
command->command();
}catch(std::exception& e){
//TODO: feed into logging mechanism
fprintf(stderr, "Executor: Unhandled exception: %s",e.what());
@@ -122,41 +68,20 @@ void ExecutorPvt::run()
xx.lock();
}
stopped.signal();
}
ExecutorNode * ExecutorPvt::createNode(Command *command)
void Executor::execute(CommandPtr const & command)
{
Lock xx(mutex);
ExecutorNode *executorNode = new ExecutorNode(command);
executorList.addTail(executorNode->node);
return executorNode;
command->next.reset();
if(head.get()==NULL) {
head = command;
moreWork.signal();
return;
}
if(tail.get()==NULL) return;
tail->next = command;
}
void ExecutorPvt::execute(ExecutorNode *node)
{
Lock xx(mutex);
if(node->runNode.isOnList()) return;
bool isEmpty = runList.isEmpty();
runList.addTail(node->runNode);
if(isEmpty) moreWork.signal();
}
Executor::Executor(String threadName,ThreadPriority priority)
: pImpl(new ExecutorPvt(threadName,priority))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(executor);
}
Executor::~Executor() {
delete pImpl;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(executor);
}
ExecutorNode * Executor::createNode(Command*command)
{return pImpl->createNode(command);}
void Executor::execute(ExecutorNode *node) {pImpl->execute(node);}
}}

View File

@@ -7,30 +7,43 @@
#ifndef EXECUTOR_H
#define EXECUTOR_H
#include <memory>
#include <vector>
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
#include <pv/lock.h>
#include <pv/event.h>
#include <pv/thread.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
// This is created by Executor.createNode and passed to Executor.execute
class ExecutorNode;
class Command;
class Executor;
typedef std::tr1::shared_ptr<Command> CommandPtr;
typedef std::tr1::shared_ptr<Executor> ExecutorPtr;
class Command {
public:
POINTER_DEFINITIONS(Command);
virtual ~Command(){}
virtual void command() = 0;
private:
CommandPtr next;
friend class Executor;
};
class Executor : private NoDefaultMethods {
class Executor : public Runnable{
public:
POINTER_DEFINITIONS(Executor);
Executor(String threadName,ThreadPriority priority);
~Executor();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
void execute(CommandPtr const &node);
virtual void run();
private:
class ExecutorPvt *pImpl;
CommandPtr head;
CommandPtr tail;
epics::pvData::Mutex mutex;
epics::pvData::Event moreWork;
epics::pvData::Event stopped;
epics::pvData::Thread thread;
};
}}

View File

@@ -1,84 +0,0 @@
/* linkedList.h */
/**
* 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.
*/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <pv/linkedListVoid.h>
namespace epics { namespace pvData {
template <typename T>
class LinkedList;
template <typename T>
class LinkedListNode : private LinkedListVoidNode {
public:
LinkedListNode(T &object) : LinkedListVoidNode(&object){}
~LinkedListNode() {}
T &getObject() { return *static_cast<T *>(LinkedListVoidNode::getObject());}
bool isOnList() {return LinkedListVoidNode::isOnList();}
friend class LinkedList<T>;
};
template <typename T>
class LinkedList : private LinkedListVoid {
public:
LinkedList() : LinkedListVoid() {}
~LinkedList() {}
int getLength() {return LinkedListVoid::getLength();}
void addTail(LinkedListNode<T> &listNode)
{
LinkedListVoid::addTail(static_cast<LinkedListVoidNode &>(listNode));
}
void addHead(LinkedListNode<T> &listNode)
{
LinkedListVoid::addHead(static_cast<LinkedListVoidNode &>(listNode));
}
void insertAfter(LinkedListNode<T> &listNode,
LinkedListNode<T> &addNode)
{
LinkedListVoid::insertAfter(
static_cast<LinkedListVoidNode &>(listNode),
static_cast<LinkedListVoidNode &>(addNode));
}
void insertBefore(LinkedListNode<T> &listNode,
LinkedListNode<T> &addNode)
{
LinkedListVoid::insertBefore(
static_cast<LinkedListVoidNode &>(listNode),
static_cast<LinkedListVoidNode &>(addNode));
}
LinkedListNode<T> *removeTail(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeTail());
}
LinkedListNode<T> *removeHead(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeHead());
}
void remove(LinkedListNode<T> &listNode){
LinkedListVoid::remove(static_cast<LinkedListVoidNode &>(listNode));
}
LinkedListNode<T> *getHead(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getHead());
}
LinkedListNode<T> *getTail(){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getTail());
}
LinkedListNode<T> *getNext(LinkedListNode<T> &listNode){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getNext(
static_cast<LinkedListVoidNode &>(listNode)));
}
LinkedListNode<T> *getPrev(LinkedListNode<T> &listNode){
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getPrev(
static_cast<LinkedListVoidNode &>(listNode)));
}
bool isEmpty() { return LinkedListVoid::isEmpty();}
};
}}
#endif /* LINKEDLIST_H */

View File

@@ -1,210 +0,0 @@
/* linkedListVoid.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 <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/linkedListVoid.h>
#include <pv/CDRMonitor.h>
namespace epics { namespace pvData {
static String alreadyOnList("already on list");
PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedListNode);
PVDATA_REFCOUNT_MONITOR_DEFINE(LinkedList);
LinkedListVoidNode::LinkedListVoidNode(void *object)
: object(object),before(0),after(0),linkedListVoid(0)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode);
}
LinkedListVoidNode::LinkedListVoidNode(bool isHead)
: object(this),before(this),after(this)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedListNode);
}
LinkedListVoidNode::~LinkedListVoidNode()
{
PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedListNode);
}
void *LinkedListVoidNode::getObject() {
return object;
}
bool LinkedListVoidNode::isOnList()
{
if(before==0 && after==0) return false;
return true;
}
LinkedListVoid::LinkedListVoid()
: head(new LinkedListVoidNode(true)),length(0)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(LinkedList);
}
LinkedListVoid::~LinkedListVoid()
{
delete head;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(LinkedList);
}
int LinkedListVoid::getLength()
{
return length;
}
void LinkedListVoid::addTail(LinkedListVoidNode &node)
{
if(node.before!=0 || node.after!=0) {
throw std::logic_error(alreadyOnList);
}
node.linkedListVoid = this;
node.before = head->before;
node.after = head;
head->before->after = &node;
head->before = &node;
++length;
}
void LinkedListVoid::addHead(LinkedListVoidNode &node)
{
if(node.before!=0 || node.after!=0) {
throw std::logic_error(alreadyOnList);
}
node.linkedListVoid = this;
node.after = head->after;
node.before = head;
head->after->before = &node;
head->after = &node;
++length;
}
void LinkedListVoid::insertAfter(LinkedListVoidNode &node,
LinkedListVoidNode &addNode)
{
LinkedListVoidNode *existingNode = &node;
LinkedListVoidNode *newNode = &addNode;
if(existingNode->after==0 || existingNode->before==0) {
throw std::logic_error(String("listNode not on list"));
}
if(newNode->before!=0 || newNode->after!=0) {
throw std::logic_error(alreadyOnList);
}
if(node.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
newNode->linkedListVoid = this;
newNode->after = existingNode->after;
newNode->before = existingNode;
existingNode->after->before = newNode;
existingNode->after = newNode;
++length;
}
void LinkedListVoid::insertBefore(LinkedListVoidNode &node,
LinkedListVoidNode &addNode)
{
LinkedListVoidNode *existingNode = &node;
LinkedListVoidNode *newNode = &addNode;
if(existingNode->after==0 || existingNode->before==0) {
throw std::logic_error(String("listNode not on list"));
}
if(newNode->before!=0 || newNode->after!=0) {
throw std::logic_error(alreadyOnList);
}
if(node.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
newNode->linkedListVoid = this;
newNode->after = existingNode;
newNode->before = existingNode->before;
existingNode->before->after = newNode;
existingNode->before = newNode;
++length;
}
LinkedListVoidNode *LinkedListVoid::removeTail()
{
if(head->after==head) return 0;
LinkedListVoidNode *node = head->before;
remove(*head->before);
return node;
}
LinkedListVoidNode *LinkedListVoid::removeHead()
{
if(head->after==head) return 0;
LinkedListVoidNode *node = head->after;
remove(*head->after);
return node;
}
void LinkedListVoid::remove(LinkedListVoidNode &node)
{
if(node.before==0 || node.after==0) {
throw std::logic_error(String("node not on list"));
}
if(node.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
node.linkedListVoid = 0;
LinkedListVoidNode *prev = node.before;
LinkedListVoidNode *next = node.after;
node.after = node.before = 0;
prev->after = next;
next->before = prev;
length--;
}
LinkedListVoidNode *LinkedListVoid::getHead()
{
if(head->after==head) return 0;
return head->after;
}
LinkedListVoidNode *LinkedListVoid::getTail()
{
if(head->after==head) return 0;
return head->before;
}
LinkedListVoidNode *LinkedListVoid::getNext(LinkedListVoidNode &listNode)
{
if(listNode.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
if(listNode.after==head) return 0;
return listNode.after;
}
LinkedListVoidNode *LinkedListVoid::getPrev(LinkedListVoidNode &listNode)
{
if(listNode.linkedListVoid!=this) {
throw std::logic_error(String("node not on this list"));
}
if(listNode.before==head) return 0;
return listNode.before;
}
bool LinkedListVoid::isEmpty()
{
if(head->after==head) return true;
return false;
}
}}

View File

@@ -1,68 +0,0 @@
/* linkedListVoid.h */
/**
* 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.
*/
#ifndef LINKEDLISTVOID_H
#define LINKEDLISTVOID_H
#include <pv/pvType.h>
namespace epics { namespace pvData {
class LinkedListVoid;
class LinkedListVoidNode;
class LinkedListVoidNode {
public:
~LinkedListVoidNode();
void *getObject();
bool isOnList();
protected:
LinkedListVoidNode(void *object);
private:
LinkedListVoidNode(bool isHead);
friend class LinkedListVoid;
void *object;
LinkedListVoidNode *before;
LinkedListVoidNode *after;
LinkedListVoid *linkedListVoid;
// do not implement the following
LinkedListVoidNode(const LinkedListVoidNode&);
LinkedListVoidNode & operator=(const LinkedListVoidNode&);
};
class LinkedListVoid {
public:
~LinkedListVoid();
int getLength();
void addTail(LinkedListVoidNode &listNode);
void addHead(LinkedListVoidNode &listNode);
void insertAfter(LinkedListVoidNode &listNode,
LinkedListVoidNode &addNode);
void insertBefore(LinkedListVoidNode &listNode,
LinkedListVoidNode &addNode);
LinkedListVoidNode *removeTail();
LinkedListVoidNode *removeHead();
void remove(LinkedListVoidNode &listNode);
LinkedListVoidNode *getHead();
LinkedListVoidNode *getTail();
LinkedListVoidNode *getNext(LinkedListVoidNode &listNode);
LinkedListVoidNode *getPrev(LinkedListVoidNode &listNode);
bool isEmpty();
protected:
LinkedListVoid();
private:
friend class LinkedListVoidNode;
LinkedListVoidNode *head;
int length;
// do not implement the following
LinkedListVoid(const LinkedListVoid&);
LinkedListVoid & operator=(const LinkedListVoid&);
};
}}
#endif /* LINKEDLISTVOID_H */

View File

@@ -4,14 +4,19 @@
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/noDefaultMethods.h>
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <pv/pvType.h>
#include <pv/timeStamp.h>
#include <pv/timeFunction.h>
namespace epics { namespace pvData {
TimeFunction::TimeFunction(TimeFunctionRequester *requester)
TimeFunction::TimeFunction(TimeFunctionRequesterPtr const &requester)
: requester(requester) {}

View File

@@ -6,24 +6,31 @@
*/
#ifndef TIMEFUNCTION_H
#define TIMEFUNCTION_H
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
class TimeFunctionRequester;
class TimeFunction;
typedef std::tr1::shared_ptr<TimeFunctionRequester> TimeFunctionRequesterPtr;
typedef std::tr1::shared_ptr<TimeFunction> TimeFunctionPtr;
class TimeFunctionRequester {
public:
POINTER_DEFINITIONS(TimeFunctionRequester);
virtual ~TimeFunctionRequester(){}
virtual void function() = 0;
};
class TimeFunction : private NoDefaultMethods {
class TimeFunction {
public:
TimeFunction(TimeFunctionRequester *requester);
POINTER_DEFINITIONS(TimeFunction);
TimeFunction(TimeFunctionRequesterPtr const & requester);
~TimeFunction();
double timeCall();
private:
TimeFunctionRequester *requester;
TimeFunctionRequesterPtr requester;
};

View File

@@ -11,224 +11,201 @@
#include <stdio.h>
#include <stdexcept>
#include <pv/pvType.h>
#include <pv/lock.h>
#include <pv/noDefaultMethods.h>
#include <pv/CDRMonitor.h>
#include <pv/linkedList.h>
#include <pv/thread.h>
#include <pv/timeStamp.h>
#include <pv/timer.h>
#include <pv/event.h>
#include <pv/convert.h>
namespace epics { namespace pvData {
PVDATA_REFCOUNT_MONITOR_DEFINE(timerNode);
PVDATA_REFCOUNT_MONITOR_DEFINE(timer);
TimerCallback::TimerCallback()
: period(0.0),
onList(false)
{
}
typedef LinkedListNode<TimerNode::Pvt> TimerListNode;
typedef LinkedList<TimerNode::Pvt> TimerList;
class TimerNode::Pvt {
public:
TimerNode *timerNode;
TimerCallback *callback;
TimerListNode timerListNode;
TimeStamp timeToRun;
Timer::Pvt *timerPvt;
double period;
Pvt(TimerNode &timerNode,TimerCallback &callback);
~Pvt(){}
private:
};
TimerNode::Pvt::Pvt(TimerNode &timerNode,TimerCallback &callback)
: timerNode(&timerNode),callback(&callback),
timerListNode(*this),timeToRun(),
timerPvt(0), period(0.0)
{}
struct Timer::Pvt : public Runnable{
public:
Pvt(String threadName,ThreadPriority priority);
virtual void run();
public: // only used by this source module
TimerList timerList;
Mutex mutex;
Event waitForWork;
Event waitForDone;
bool alive;
Thread thread;
void addElement(TimerNode::Pvt &node);
};
Timer::Pvt::Pvt(String threadName,ThreadPriority priority)
: timerList(),
mutex(),
waitForWork(false),
Timer::Timer(String threadName,ThreadPriority priority)
: waitForWork(false),
waitForDone(false),
alive(true),
thread(threadName,priority,this)
{}
void Timer::Pvt::addElement(TimerNode::Pvt &node)
void Timer::addElement(TimerCallbackPtr const & timerCallback)
{
TimerListNode *nextNode = timerList.getHead();
if(nextNode==0) {
timerList.addTail(node.timerListNode);
timerCallback->onList = true;
if(head.get()==NULL) {
head = timerCallback;
timerCallback->next.reset();
return;
}
TimerCallbackPtr nextNode(head);
TimerCallbackPtr prevNode;
while(true) {
TimerNode::Pvt &timerListNode = nextNode->getObject();
if((node.timeToRun)<(timerListNode.timeToRun)) {
timerList.insertBefore(timerListNode.timerListNode,node.timerListNode);
return;
}
nextNode = timerList.getNext(timerListNode.timerListNode);
if(nextNode==0) {
timerList.addTail(node.timerListNode);
if(timerCallback->timeToRun < nextNode->timeToRun) {
if(prevNode.get()!=NULL) {
prevNode->next = timerCallback;
} else {
head = timerCallback;
}
timerCallback->next = nextNode;
return;
}
if(nextNode->next.get()==NULL) {
nextNode->next = timerCallback;
timerCallback->next.reset();
return;
}
prevNode = nextNode;
nextNode = nextNode->next;
}
}
TimerNode::TimerNode(TimerCallback &callback)
: pImpl(new Pvt(*this,callback))
void Timer::cancel(TimerCallbackPtr const &timerCallback)
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timerNode);
Lock xx(mutex);
if(!timerCallback->onList) return;
TimerCallbackPtr nextNode(head);
TimerCallbackPtr prevNode;
while(true) {
if(nextNode.get()==timerCallback.get()) {
if(prevNode.get()!=NULL) {
prevNode->next = timerCallback->next;
} else {
head = timerCallback->next;
}
timerCallback->next.reset();
timerCallback->onList = false;
return;
}
prevNode = nextNode;
nextNode = nextNode->next;
}
throw std::logic_error(String(""));
}
bool Timer::isScheduled(TimerCallbackPtr const &timerCallback)
{
Lock xx(mutex);
return timerCallback->onList;
}
TimerNode::~TimerNode()
{
cancel();
PVDATA_REFCOUNT_MONITOR_DESTRUCT(timerNode);
}
void TimerNode::cancel()
{
Timer::Pvt *timerPvt = pImpl->timerPvt;
if(timerPvt==0) return;
Lock xx(timerPvt->mutex);
if(pImpl->timerPvt==0) return;
pImpl->timerPvt->timerList.remove(pImpl->timerListNode);
pImpl->timerPvt = 0;
}
bool TimerNode::isScheduled()
{
Timer::Pvt *pvt = pImpl->timerPvt;
if(pvt==0) return false;
Lock xx(pvt->mutex);
return pImpl->timerListNode.isOnList();
}
void Timer::Pvt::run()
void Timer::run()
{
TimeStamp currentTime;
while(true) {
currentTime.getCurrent();
TimeStamp *timeToRun = 0;
double period = 0.0;
TimerNode::Pvt *nodeToCall = 0;
TimerCallbackPtr nodeToCall;
{
Lock xx(mutex);
currentTime.getCurrent();
if (!alive) break;
TimerListNode *timerListNode = timerList.getHead();
if(timerListNode!=0) {
TimerNode::Pvt *timerNodePvt = &timerListNode->getObject();
timeToRun = &timerNodePvt->timeToRun;
TimerCallbackPtr timerCallback = head;
if(timerCallback.get()!=NULL) {
double diff = TimeStamp::diff(
*timeToRun,currentTime);
timerCallback->timeToRun,currentTime);
if(diff<=0.0) {
nodeToCall = timerNodePvt;
timerList.removeHead();
period = timerNodePvt->period;
nodeToCall = timerCallback;
nodeToCall->onList = false;
head = head->next;
period = timerCallback->period;
if(period>0.0) {
timerNodePvt->timeToRun += period;
addElement(*timerNodePvt);
} else {
timerNodePvt->timerPvt = 0;
}
timerListNode = timerList.getHead();
if(timerListNode!=0) {
timerNodePvt = &timerListNode->getObject();
timeToRun = &timerNodePvt->timeToRun;
} else {
timeToRun = 0;
timerCallback->timeToRun += period;
addElement(timerCallback);
}
timerCallback = head;
}
}
}
if(nodeToCall!=0) {
nodeToCall->callback->callback();
if(nodeToCall.get()!=NULL) {
nodeToCall->callback();
}
{
Lock xx(mutex);
if(!alive) break;
}
if(timeToRun==0) {
if(head.get()==NULL) {
waitForWork.wait();
} else {
double delay = TimeStamp::diff(*timeToRun,currentTime);
double delay = TimeStamp::diff(head->timeToRun,currentTime);
waitForWork.wait(delay);
}
}
waitForDone.signal();
}
Timer::Timer(String threadName, ThreadPriority priority)
: pImpl(new Pvt(threadName,priority))
{
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timer);
}
Timer::~Timer() {
{
Lock xx(pImpl->mutex);
pImpl->alive = false;
Lock xx(mutex);
alive = false;
}
pImpl->waitForWork.signal();
pImpl->waitForDone.wait();
TimerListNode *node = 0;
while((node = pImpl->timerList.removeHead())!=0) {
node->getObject().callback->timerStopped();
waitForWork.signal();
waitForDone.wait();
TimerCallbackPtr timerCallback;
while(true) {
timerCallback = head;
if(head.get()==NULL) break;
head->timerStopped();
head = timerCallback->next;
timerCallback->next.reset();
timerCallback->onList = false;
}
PVDATA_REFCOUNT_MONITOR_DESTRUCT(timer);
}
void Timer::scheduleAfterDelay(TimerNode &timerNode,double delay)
void Timer::scheduleAfterDelay(
TimerCallbackPtr const &timerCallback,
double delay)
{
schedulePeriodic(timerNode,delay,0.0);
schedulePeriodic(timerCallback,delay,0.0);
}
void Timer::schedulePeriodic(TimerNode &timerNode,double delay,double period)
void Timer::schedulePeriodic(
TimerCallbackPtr const &timerCallback,
double delay,
double period)
{
TimerNode::Pvt *timerNodePvt = timerNode.pImpl.get();
if(timerNodePvt->timerListNode.isOnList()) {
if(isScheduled(timerCallback)) {
throw std::logic_error(String("already queued"));
}
{
Lock xx(pImpl->mutex);
if(!pImpl->alive) {
timerNodePvt->callback->timerStopped();
Lock xx(mutex);
if(!alive) {
timerCallback->timerStopped();
return;
}
}
TimeStamp *timeStamp = &timerNodePvt->timeToRun;
timeStamp->getCurrent();
*timeStamp += delay;
timerNodePvt->period = period;
TimeStamp timeStamp;
timeStamp.getCurrent();
timeStamp += delay;
timerCallback->timeToRun.getCurrent();
timerCallback->timeToRun += delay;
timerCallback->period = period;
bool isFirst = false;
{
Lock xx(pImpl->mutex);
timerNodePvt->timerPvt = pImpl.get();
pImpl->addElement(*timerNodePvt);
TimerNode::Pvt *first = &pImpl->timerList.getHead()->getObject();
if(first==timerNodePvt) isFirst = true;
Lock xx(mutex);
addElement(timerCallback);
if(timerCallback.get()==head.get()) isFirst = true;
}
if(isFirst) pImpl->waitForWork.signal();
if(isFirst) waitForWork.signal();
}
void Timer::toString(StringBuilder builder)
{
Lock xx(mutex);
if(!alive) return;
TimeStamp currentTime;
TimerCallbackPtr nodeToCall(head);
currentTime.getCurrent();
while(true) {
if(nodeToCall.get()==NULL) return;
TimeStamp timeToRun = nodeToCall->timeToRun;
double period = nodeToCall->period;
double diff = TimeStamp::diff(timeToRun,currentTime);
char buffer[50];
sprintf(buffer,"timeToRun %f period %f\n",diff,period);
*builder += buffer;
nodeToCall = nodeToCall->next;
}
}
}}

View File

@@ -15,44 +15,57 @@
#include <pv/pvType.h>
#include <pv/thread.h>
#include <pv/noDefaultMethods.h>
#include <pv/timeStamp.h>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/sharedPtr.h>
namespace epics { namespace pvData {
class TimerCallback;
class Timer;
typedef std::tr1::shared_ptr<TimerCallback> TimerCallbackPtr;
typedef std::tr1::shared_ptr<Timer> TimerPtr;
class TimerCallback {
public:
POINTER_DEFINITIONS(TimerCallback);
TimerCallback();
virtual ~TimerCallback(){}
virtual void callback() = 0;
virtual void timerStopped() = 0;
};
class TimerNode {
public:
TimerNode(TimerCallback &timerCallback);
~TimerNode();
void cancel();
bool isScheduled();
class Pvt;
private:
std::auto_ptr<Pvt> pImpl;
TimerCallbackPtr next;
TimeStamp timeToRun;
double period;
bool onList;
friend class Timer;
};
class Timer : private NoDefaultMethods {
class Timer : public Runnable {
public:
POINTER_DEFINITIONS(Timer);
Timer(String threadName, ThreadPriority priority);
~Timer();
void scheduleAfterDelay(TimerNode &timerNode,double delay);
void schedulePeriodic(TimerNode &timerNode,double delay,double period);
class Pvt;
virtual ~Timer();
virtual void run();
void scheduleAfterDelay(
TimerCallbackPtr const &timerCallback,
double delay);
void schedulePeriodic(
TimerCallbackPtr const &timerCallback,
double delay,
double period);
void cancel(TimerCallbackPtr const &timerCallback);
bool isScheduled(TimerCallbackPtr const &timerCallback);
void toString(StringBuilder builder);
private:
std::auto_ptr<Pvt> pImpl;
void addElement(TimerCallbackPtr const &timerCallback);
TimerCallbackPtr head;
Mutex mutex;
Event waitForWork;
Event waitForDone;
bool alive;
Thread thread;
};
}}

View File

@@ -42,10 +42,6 @@ PROD_HOST += testMessageQueue
testMessageQueue_SRCS += testMessageQueue.cpp
testMessageQueue_LIBS += pvData Com
PROD_HOST += testLinkedList
testLinkedList_SRCS += testLinkedList.cpp
testLinkedList_LIBS += pvData Com
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -12,7 +12,6 @@
#include <string.h>
#include <stdio.h>
#include <pv/bitSet.h>
#include <pv/CDRMonitor.h>
#include <epicsAssert.h>
#include <epicsExit.h>
@@ -150,8 +149,6 @@ int main(int argc,char *argv[])
}
testGetSetClearFlip(fd);
testOperators(fd);
epicsExitCallAtExits();
CDRMonitor::get().show(fd);
return(0);
}

View File

@@ -1,450 +0,0 @@
/**
* 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.
*/
/*
* testLinkedList.cpp
*
* Created on: 2010.11
* Author: Marty Kraimer
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <list>
#include <epicsAssert.h>
#include <epicsExit.h>
#include <pv/lock.h>
#include <pv/timeStamp.h>
#include <pv/linkedList.h>
#include <pv/CDRMonitor.h>
using namespace epics::pvData;
static const int numNodes = 5;
class Basic;
typedef LinkedListNode<Basic> BasicListNode;
typedef LinkedList<Basic> BasicList;
class Basic {
public:
Basic(int i): index(i),node(*this) {}
~Basic() { }
int index;
BasicListNode node;
};
static void testBasic(FILE * fd ) {
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
basicList.addTail(basics[i]->node);
assert(basicList.getLength()==i+1);
}
BasicListNode *basicNode = basicList.getHead();
fprintf(fd,"basic addTail");
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.getNext(*basicNode);
}
assert(basicList.isEmpty()==false);
basicNode = basicList.getTail();
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
assert(basicNode->isOnList());
basicNode = basicList.getPrev(*basicNode);
}
fprintf(fd,"\n");
for(int i=0; i<numNodes; i++) {
basicNode = basicList.getHead();
assert(basicNode!=0);
Basic &basic = basicNode->getObject();
assert(basic.index==i);
assert(basics[i]->node.isOnList()==true);
basicList.remove(basics[i]->node);
assert(basics[i]->node.isOnList()==false);
int length = basicList.getLength();
assert(length==(numNodes-i-1));
}
assert(basicList.isEmpty());
for(int i=numNodes-1; i>=0; i--) {
basicList.addHead(basics[i]->node);
assert(basicList.getLength()==numNodes-i);
}
basicNode = basicList.getHead();
fprintf(fd,"basic addHead");
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.getNext(*basicNode);
}
fprintf(fd,"\n");
for(int i=0; i<numNodes; i++) {
basicNode = basicList.getHead();
assert(basicNode!=0);
Basic &basic = basicNode->getObject();
assert(basic.index==i);
basicList.removeHead();
assert(basic.node.isOnList()==false);
int length = basicList.getLength();
assert(length==(numNodes-i-1));
}
assert(basicList.isEmpty());
basicList.addTail(basics[0]->node);
basicNode = basicList.getTail();
assert(basicNode->getObject().index==0);
for(int i=1;i<numNodes;i++) {
basicList.insertAfter(*basicNode,basics[i]->node);
basicNode = basicList.getTail();
assert(basicList.getLength()==i+1);
}
fprintf(fd,"basic addTail insertAfter");
basicNode = basicList.getHead();
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.getNext(*basicNode);
}
fprintf(fd,"\n");
for(int i=numNodes-1; i>=0; i--) {
Basic &basic = basicList.getTail()->getObject();
assert(basic.index==i);
basicList.removeTail();
assert(basic.node.isOnList()==false);
int length = basicList.getLength();
assert(length==i);
}
assert(basicList.isEmpty());
basicList.addHead(basics[numNodes-1]->node);
basicNode = basicList.getHead();
assert(basicNode->getObject().index==4);
for(int i=numNodes-2; i>=0; i--) {
basicList.insertBefore(*basicNode,basics[i]->node);
basicNode = basicList.getHead();
assert(basicList.getLength()==numNodes-i);
}
fprintf(fd,"basic addTail insertBefore");
basicNode = basicList.getHead();
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.getNext(*basicNode);
}
fprintf(fd,"\n");
for(int i=numNodes-1; i>=0; i--) {
Basic &basic = basicList.getTail()->getObject();
assert(basic.index==i);
basicList.remove(basic.node);
assert(basic.node.isOnList()==false);
int length = basicList.getLength();
assert(length==i);
}
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testQueue(FILE * fd ) {
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(fd,"\nQueue test\n");
for(int i=0;i<numNodes;i++) {
basicList.addTail(basics[i]->node);
assert(basicList.getLength()==i+1);
}
BasicListNode *basicNode = basicList.removeHead();
while(basicNode!=0) basicNode = basicList.removeHead();
for(int i=0;i<numNodes;i++) basicList.addTail(basics[i]->node);
basicNode = basicList.removeHead();
fprintf(fd,"queue");
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.removeHead();
}
fprintf(fd,"\n");
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testStack(FILE * fd ) {
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(fd,"\nStack test\n");
for(int i=0;i<numNodes;i++) {
basicList.addHead(basics[i]->node);
assert(basicList.getLength()==i+1);
}
BasicListNode *basicNode = basicList.removeHead();
while(basicNode!=0) basicNode = basicList.removeHead();
for(int i=0;i<numNodes;i++) basicList.addHead(basics[i]->node);
basicNode = basicList.removeHead();
fprintf(fd,"stack");
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.removeHead();
}
fprintf(fd,"\n");
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testList(FILE * fd ) {
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(fd,"\ntestList\n");
for(int i=0;i<numNodes;i++) basicList.addTail(basics[i]->node);
fprintf(fd,"list");
BasicListNode *basicNode = basicList.removeHead();
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.removeHead();
}
fprintf(fd,"\n");
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testRandomInsertRemove(FILE * fd ) {
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(fd,"\nRandom insert/remove test\n");
basicList.addHead(basics[4]->node);
basicList.insertAfter(basics[4]->node,basics[3]->node);
basicList.insertAfter(basics[3]->node,basics[2]->node);
basicList.addTail(basics[1]->node);
basicList.addTail(basics[0]->node);
BasicListNode *basicNode = basicList.removeHead();
fprintf(fd,"stack");
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.removeHead();
}
fprintf(fd,"\n");
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testOrderedQueue(FILE * fd ) {
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
BasicListNode *basicNode = 0;
fprintf(fd,"\nOrdered Queue test\n");
basicList.addHead(basics[2]->node);
for(int i=0;i<numNodes;i++) {
if(basics[i]->node.isOnList()) continue;
basicNode = basicList.getHead();
while(basicNode!=0) {
if(basicNode->getObject().index>=basics[i]->index) {
basicList.insertBefore(*basicNode,basics[i]->node);
break;
}
basicNode = basicList.getNext(*basicNode);
}
if(basics[i]->node.isOnList()) continue;
basicList.addTail(basics[i]->node);
}
fprintf(fd,"list");
basicNode = basicList.removeHead();
while(basicNode!=0) {
fprintf(fd," %d",basicNode->getObject().index);
basicNode = basicList.removeHead();
}
fprintf(fd,"\n");
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testTime(FILE *auxFd) {
TimeStamp startTime;
TimeStamp endTime;
const int numNodes = 1000;
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(auxFd,"\nTime test\n");
int ntimes = 1000;
startTime.getCurrent();
for(int i=0; i<ntimes; i++) {
for(int j=0;j<numNodes;j++) basicList.addTail(basics[j]->node);
BasicListNode *basicNode = basicList.removeHead();
while(basicNode!=0) basicNode = basicList.removeHead();
}
endTime.getCurrent();
double diff = TimeStamp::diff(endTime,startTime);
diff *= 1000.0;
fprintf(auxFd,"diff %f milliSeconds\n",diff);
diff = diff/1000.0; // convert from milliseconds to seconds
diff = diff/ntimes; // seconds per outer loop
diff = diff*1e6; // converty to microseconds
fprintf(auxFd,"time per iteration %f microseconds\n",diff);
diff = diff/(numNodes*2); // convert to per addTail/removeHead
fprintf(auxFd,"time per addTail/removeHead %f microseconds\n",diff);
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testTimeLocked(FILE *auxFd) {
TimeStamp startTime;
TimeStamp endTime;
Mutex mutex;
const int numNodes = 1000;
LinkedList<Basic> basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(auxFd,"\nTime test locked\n");
int ntimes = 1000;
startTime.getCurrent();
for(int i=0; i<ntimes; i++) {
for(int j=0;j<numNodes;j++) {
Lock xx(mutex);
basicList.addTail(basics[j]->node);
}
BasicListNode *basicNode = 0;
{
Lock xx(mutex);
basicNode = basicList.removeHead();
}
while(basicNode!=0) {
Lock xx(mutex);
basicNode = basicList.removeHead();
}
}
endTime.getCurrent();
double diff = TimeStamp::diff(endTime,startTime);
diff *= 1000.0;
fprintf(auxFd,"diff %f milliSeconds\n",diff);
diff = diff/1000.0; // convert from milliseconds to seconds
diff = diff/ntimes; // seconds per outer loop
diff = diff*1e6; // converty to microseconds
fprintf(auxFd,"time per iteration %f microseconds\n",diff);
diff = diff/(numNodes*2); // convert to per addTail/removeHead
fprintf(auxFd,"time per addTail/removeHead %f microseconds\n",diff);
assert(basicList.isEmpty());
for(int i=0; i<numNodes; i++) delete basics[i];
}
typedef std::list<Basic *> stdList;
static void testStdListTime(FILE *auxFd) {
TimeStamp startTime;
TimeStamp endTime;
const int numNodes = 1000;
stdList basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(auxFd,"\nTime std::list test\n");
int ntimes = 1000;
startTime.getCurrent();
for(int i=0; i<ntimes; i++) {
for(int j=0;j<numNodes;j++) basicList.push_back(basics[j]);
while(basicList.size()>0) {
basicList.begin();
basicList.pop_front();
}
}
endTime.getCurrent();
double diff = TimeStamp::diff(endTime,startTime);
diff *= 1000.0;
fprintf(auxFd,"diff %f milliSeconds\n",diff);
diff = diff/1000.0; // convert from milliseconds to seconds
diff = diff/ntimes; // seconds per outer loop
diff = diff*1e6; // converty to microseconds
fprintf(auxFd,"time per iteration %f microseconds\n",diff);
diff = diff/(numNodes*2); // convert to per addTail/removeHead
fprintf(auxFd,"time per addTail/removeHead %f microseconds\n",diff);
for(int i=0; i<numNodes; i++) delete basics[i];
}
static void testStdListTimeLocked(FILE *auxFd) {
TimeStamp startTime;
TimeStamp endTime;
const int numNodes = 1000;
Mutex mutex;
stdList basicList;
Basic *basics[numNodes];
for(int i=0; i<numNodes; i++) {
basics[i] = new Basic(i);
}
fprintf(auxFd,"\nTime std::list test locked\n");
int ntimes = 1000;
startTime.getCurrent();
for(int i=0; i<ntimes; i++) {
for(int j=0;j<numNodes;j++) {
Lock xx(mutex);
basicList.push_back(basics[j]);
}
while(basicList.size()>0) {
Lock xx(mutex);
basicList.begin();
basicList.pop_front();
}
}
endTime.getCurrent();
double diff = TimeStamp::diff(endTime,startTime);
diff *= 1000.0;
fprintf(auxFd,"diff %f milliSeconds\n",diff);
diff = diff/1000.0; // convert from milliseconds to seconds
diff = diff/ntimes; // seconds per outer loop
diff = diff*1e6; // converty to microseconds
fprintf(auxFd,"time per iteration %f microseconds\n",diff);
diff = diff/(numNodes*2); // convert to per addTail/removeHead
fprintf(auxFd,"time per addTail/removeHead %f microseconds\n",diff);
for(int i=0; i<numNodes; i++) delete basics[i];
}
int main(int argc, char *argv[]) {
char *fileName = 0;
if(argc>1) fileName = argv[1];
FILE * fd = stdout;
if(fileName!=0 && fileName[0]!=0) {
fd = fopen(fileName,"w+");
}
char *auxFileName = 0;
if(argc>2) auxFileName = argv[2];
FILE *auxFd = stdout;
if(auxFileName!=0 && auxFileName[0]!=0) {
auxFd = fopen(auxFileName,"w+");
}
testBasic(fd);
testQueue(fd);
testStack(fd);
testList(fd);
testRandomInsertRemove(fd);
testOrderedQueue(fd);
testTime(auxFd);
testTimeLocked(auxFd);
testStdListTime(auxFd);
testStdListTimeLocked(auxFd);
epicsExitCallAtExits();
CDRMonitor::get().show(fd);
return (0);
}

View File

@@ -23,7 +23,6 @@
#include <pv/timeStamp.h>
#include <pv/requester.h>
#include <pv/messageQueue.h>
#include <pv/CDRMonitor.h>
#include <pv/event.h>
#include <pv/thread.h>
#include <pv/executor.h>
@@ -89,8 +88,6 @@ int main(int argc, char *argv[]) {
auxfd = fopen(auxFileName,"w+");
}
testBasic(fd,auxfd);
epicsExitCallAtExits();
CDRMonitor::get().show(fd);
return (0);
}

View File

@@ -20,7 +20,6 @@
#include <pv/serialize.h>
#include <pv/noDefaultMethods.h>
#include <pv/byteBuffer.h>
#include <pv/CDRMonitor.h>
#include <pv/convert.h>
#include <pv/standardField.h>
@@ -661,8 +660,6 @@ int main(int argc, char *argv[]) {
delete flusher;
epicsExitCallAtExits();
(*out)<<"Done.\n"<<CDRMonitor::get();
return 0;
}

View File

@@ -23,7 +23,6 @@
#include <pv/event.h>
#include <pv/thread.h>
#include <pv/executor.h>
#include <pv/CDRMonitor.h>
#include <pv/timeFunction.h>
using namespace epics::pvData;
@@ -39,7 +38,7 @@ public:
begin.signal();
bool waited=end.wait();
actuallyRan=true;
fprintf(out, "Action1 %s\n", waited?"true":"false");
fprintf(out, "Action %s\n", waited?"true":"false");
}
};
@@ -49,81 +48,89 @@ static void testThreadRun(FILE *fd) {
{
Thread tr("Action", lowPriority, &ax);
bool w=ax.begin.wait();
fprintf(fd, "main1 %s\n", w?"true":"false");
fprintf(fd, "main %s\n", w?"true":"false");
fprintf(fd, "Action is %s\n", ax.actuallyRan?"true":"false");
ax.end.signal();
}
fprintf(fd, "Action is %s\n", ax.actuallyRan?"true":"false");
}
class Basic : public Command {
class Basic :
public Command,
public std::tr1::enable_shared_from_this<Basic>
{
public:
Basic(Executor *executor);
POINTER_DEFINITIONS(Basic);
Basic(ExecutorPtr const &executor);
~Basic();
void run();
virtual void command();
private:
Executor *executor;
ExecutorNode *executorNode;
Event *wait;
Basic::shared_pointer getPtrSelf()
{
return shared_from_this();
}
ExecutorPtr executor;
Event wait;
};
Basic::Basic(Executor *executor)
: executor(executor),
executorNode(executor->createNode(this)),
wait(new Event())
typedef std::tr1::shared_ptr<Basic> BasicPtr;
Basic::Basic(ExecutorPtr const &executor)
: executor(executor)
{
}
Basic::~Basic() {
delete wait;
}
void Basic::run()
{
executor->execute(executorNode);
bool result = wait->wait();
executor->execute(getPtrSelf());
bool result = wait.wait();
if(result==false) printf("basic::run wait returned false\n");
}
void Basic::command()
{
wait->signal();
wait.signal();
}
static void testBasic(FILE *fd) {
Executor *executor = new Executor(String("basic"),middlePriority);
Basic *basic = new Basic(executor);
ExecutorPtr executor( new Executor(String("basic"),middlePriority));
BasicPtr basic( new Basic(executor));
basic->run();
delete basic;
String buf("");
delete executor;
}
class MyFunc : public TimeFunctionRequester {
public:
MyFunc(Basic *basic)
: basic(basic)
{}
virtual void function()
{
basic->run();
}
POINTER_DEFINITIONS(MyFunc);
MyFunc(BasicPtr const &basic);
virtual void function();
private:
Basic *basic;
BasicPtr basic;
};
MyFunc::MyFunc(BasicPtr const &basic)
: basic(basic)
{}
void MyFunc::function()
{
basic->run();
}
typedef std::tr1::shared_ptr<MyFunc> MyFuncPtr;
static void testThreadContext(FILE *fd,FILE *auxFd) {
Executor *executor = new Executor(String("basic"),middlePriority);
Basic *basic = new Basic(executor);
MyFunc myFunc(basic);
TimeFunction timeFunction(&myFunc);
double perCall = timeFunction.timeCall();
ExecutorPtr executor(new Executor(String("basic"),middlePriority));
BasicPtr basic(new Basic(executor));
MyFuncPtr myFunc(new MyFunc(basic));
TimeFunctionPtr timeFunction(new TimeFunction(myFunc));
double perCall = timeFunction->timeCall();
perCall *= 1e6;
fprintf(auxFd,"time per call %f microseconds\n",perCall);
delete basic;
delete executor;
}
int main(int argc, char *argv[]) {
@@ -142,7 +149,5 @@ int main(int argc, char *argv[]) {
testThreadRun(fd);
testBasic(fd);
testThreadContext(fd,auxFd);
epicsExitCallAtExits();
CDRMonitor::get().show(fd);
return (0);
return 0;
}

View File

@@ -22,19 +22,26 @@
#include <pv/event.h>
#include <pv/timer.h>
#include <pv/thread.h>
#include <pv/CDRMonitor.h>
using namespace epics::pvData;
static TimeStamp currentTimeStamp;
static double oneDelay = 4.0;
static double twoDelay = 2.0;
static double threeDelay = 1.0;
static int ntimes = 3;
class MyCallback;
typedef std::tr1::shared_ptr<MyCallback> MyCallbackPtr;
class MyCallback : public TimerCallback {
public:
MyCallback(String name,FILE *fd,FILE *auxfd,Event *wait)
: name(name),fd(fd),auxfd(auxfd),wait(wait),
timerNode(*this),timeStamp(TimeStamp())
POINTER_DEFINITIONS(MyCallback);
MyCallback(String name,FILE *fd,FILE *auxfd,EventPtr const & wait)
: name(name),
fd(fd),
auxfd(auxfd),
wait(wait)
{
}
~MyCallback()
@@ -49,45 +56,115 @@ public:
{
fprintf(fd,"timerStopped %s\n",name.c_str());
}
TimerNode &getTimerNode() { return timerNode;}
TimeStamp &getTimeStamp() { return timeStamp;}
private:
String name;
FILE *fd;
FILE *auxfd;
Event *wait;
TimerNode timerNode;
EventPtr wait;
TimeStamp timeStamp;
};
static void testBasic(FILE *fd, FILE *auxfd)
{
printf("\n\ntestBasic oneDelay %lf twoDelay %lf threeDaley %lf\n",
oneDelay,twoDelay,threeDelay);
String one("one");
String two("two");
Event *eventOne = new Event();
Event *eventTwo = new Event();
Timer *timer = new Timer(String("timer"),middlePriority);
MyCallback *callbackOne = new MyCallback(
one,fd,auxfd,eventOne);
MyCallback *callbackTwo = new MyCallback(
two,fd,auxfd,eventTwo);
currentTimeStamp.getCurrent();
timer->scheduleAfterDelay(callbackOne->getTimerNode(),oneDelay);
timer->scheduleAfterDelay(callbackTwo->getTimerNode(),twoDelay);
eventOne->wait();
eventTwo->wait();
double diff;
diff = TimeStamp::diff(
callbackOne->getTimeStamp(),currentTimeStamp);
fprintf(auxfd,"one requested %f diff %f seconds\n",oneDelay,diff);
diff = TimeStamp::diff(
callbackTwo->getTimeStamp(),currentTimeStamp);
fprintf(auxfd,"two requested %f diff %f seconds\n",twoDelay,diff);
delete timer;
delete callbackTwo;
delete callbackOne;
delete eventTwo;
delete eventOne;
String three("three");
EventPtr eventOne(new Event());
EventPtr eventTwo(new Event());
EventPtr eventThree(new Event());
TimerPtr timer(new Timer(String("timer"),middlePriority));
MyCallbackPtr callbackOne(new MyCallback(one,fd,auxfd,eventOne));
MyCallbackPtr callbackTwo(new MyCallback(two,fd,auxfd,eventTwo));
MyCallbackPtr callbackThree(new MyCallback(three,fd,auxfd,eventThree));
for(int n=0; n<ntimes; n++) {
currentTimeStamp.getCurrent();
assert(!timer->isScheduled(callbackOne));
assert(!timer->isScheduled(callbackTwo));
assert(!timer->isScheduled(callbackThree));
timer->scheduleAfterDelay(callbackOne,oneDelay);
timer->scheduleAfterDelay(callbackTwo,twoDelay);
timer->scheduleAfterDelay(callbackThree,threeDelay);
if(oneDelay>.1) assert(timer->isScheduled(callbackOne));
if(twoDelay>.1) assert(timer->isScheduled(callbackTwo));
if(threeDelay>.1) assert(timer->isScheduled(callbackThree));
String builder;
timer->toString(&builder);
printf("timerQueue\n%s",builder.c_str());
eventOne->wait();
eventTwo->wait();
eventThree->wait();
double diff;
double delta;
diff = TimeStamp::diff(
callbackOne->getTimeStamp(),currentTimeStamp);
delta = diff - oneDelay;
fprintf(auxfd,"one requested %f actual %f delta %f\n",oneDelay,diff,delta);
if(delta<0.0) delta = -delta;
assert(delta<.1);
diff = TimeStamp::diff(
callbackTwo->getTimeStamp(),currentTimeStamp);
delta = diff - twoDelay;
fprintf(auxfd,"two requested %f actual %f delta %f\n",twoDelay,diff,delta);
if(delta<0.0) delta = -delta;
assert(delta<.1);
diff = TimeStamp::diff(
callbackThree->getTimeStamp(),currentTimeStamp);
delta = diff - threeDelay;
fprintf(auxfd,"three requested %f actual %f delta %f\n",threeDelay,diff,delta);
if(delta<0.0) delta = -delta;
assert(delta<.1);
}
}
static void testCancel(FILE *fd, FILE *auxfd)
{
printf("\n\ntestCancel oneDelay %lf twoDelay %lf threeDaley %lf\n",
oneDelay,twoDelay,threeDelay);
String one("one");
String two("two");
String three("three");
EventPtr eventOne(new Event());
EventPtr eventTwo(new Event());
EventPtr eventThree(new Event());
TimerPtr timer(new Timer(String("timer"),middlePriority));
MyCallbackPtr callbackOne(new MyCallback(one,fd,auxfd,eventOne));
MyCallbackPtr callbackTwo(new MyCallback(two,fd,auxfd,eventTwo));
MyCallbackPtr callbackThree(new MyCallback(three,fd,auxfd,eventThree));
for(int n=0; n<ntimes; n++) {
currentTimeStamp.getCurrent();
assert(!timer->isScheduled(callbackOne));
assert(!timer->isScheduled(callbackTwo));
assert(!timer->isScheduled(callbackThree));
timer->scheduleAfterDelay(callbackOne,oneDelay);
timer->scheduleAfterDelay(callbackTwo,twoDelay);
timer->scheduleAfterDelay(callbackThree,threeDelay);
timer->cancel(callbackTwo);
if(oneDelay>.1) assert(timer->isScheduled(callbackOne));
assert(!timer->isScheduled(callbackTwo));
if(threeDelay>.1) assert(timer->isScheduled(callbackThree));
String builder;
timer->toString(&builder);
printf("timerQueue\n%s",builder.c_str());
eventOne->wait();
eventThree->wait();
double diff;
double delta;
diff = TimeStamp::diff(
callbackOne->getTimeStamp(),currentTimeStamp);
delta = diff - oneDelay;
fprintf(auxfd,"one requested %f actual %f delta %f\n",oneDelay,diff,delta);
if(delta<0.0) delta = -delta;
assert(delta<.1);
diff = TimeStamp::diff(
callbackThree->getTimeStamp(),currentTimeStamp);
delta = diff - threeDelay;
fprintf(auxfd,"three requested %f actual %f delta %f\n",threeDelay,diff,delta);
if(delta<0.0) delta = -delta;
assert(delta<.1);
}
}
int main(int argc, char *argv[]) {
@@ -105,14 +182,24 @@ int main(int argc, char *argv[]) {
}
oneDelay = .4;
twoDelay = .2;
threeDelay = .1;
testBasic(fd,auxfd);
oneDelay = .2;
testCancel(fd,auxfd);
oneDelay = .1;
twoDelay = .2;
threeDelay = .4;
testBasic(fd,auxfd);
testCancel(fd,auxfd);
oneDelay = .1;
twoDelay = .4;
threeDelay = .2;
testBasic(fd,auxfd);
testCancel(fd,auxfd);
oneDelay = .0;
twoDelay = .0;
threeDelay = .0;
testBasic(fd,auxfd);
testCancel(fd,auxfd);
epicsExitCallAtExits();
CDRMonitor::get().show(fd);
return (0);
}

View File

@@ -20,7 +20,6 @@
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/standardField.h>
#include <pv/CDRMonitor.h>
using namespace epics::pvData;

View File

@@ -89,7 +89,7 @@ void testPowerSupplyArray(FILE * fd) {
powerSupplyArray->remove(2,1);
buffer.clear();
powerSupplyArrayStruct->toString(&buffer);
fprintf(fd,"after remove 0,1,3%s\n",buffer.c_str());
fprintf(fd,"after remove 2,1%s\n",buffer.c_str());
powerSupplyArray->compress();
buffer.clear();
powerSupplyArrayStruct->toString(&buffer);