started on documentation and changes to misc as a result

This commit is contained in:
Marty Kraimer
2010-12-02 15:28:09 -05:00
parent fdfd11c755
commit 358923d064
46 changed files with 4515 additions and 1113 deletions
+1
View File
@@ -23,6 +23,7 @@ INC += timer.h
LIBSRCS += byteBuffer.cpp
LIBSRCS += bitSet.cpp
LIBSRCS += requester.cpp
LIBSRCS += serializeHelper.cpp
LIBSRCS += showConstructDestruct.cpp
LIBSRCS += linkedListVoid.cpp
-4
View File
@@ -12,10 +12,6 @@
//#include "serialize.h"
namespace epics { namespace pvData {
// TODO !!!
typedef unsigned long long uint64;
typedef std::string * StringBuilder;
/**
* This class implements a vector of bits that grows as needed. Each
* component of the bit set has a {@code bool} value. The
+11 -2
View File
@@ -9,6 +9,7 @@
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <memory>
#include <vector>
@@ -56,13 +57,17 @@ static void init()
Event::~Event() {
epicsEventDestroy(id);
id = 0;
Lock xx(globalMutex);
totalDestruct++;
}
Event::Event(EventInitialState initial)
: id(epicsEventCreate((initial==eventEmpty)?epicsEventEmpty : epicsEventFull))
Event::Event(bool full)
: id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty))
{
init();
Lock xx(globalMutex);
totalConstruct++;
}
@@ -74,23 +79,27 @@ ConstructDestructCallback *Event::getConstructDestructCallback()
void Event::signal()
{
if(id==0) throw std::logic_error(String("event was deleted"));
epicsEventSignal(id);
}
bool Event::wait ()
{
if(id==0) throw std::logic_error(String("event was deleted"));
epicsEventWaitStatus status = epicsEventWait(id);
return status==epicsEventWaitOK ? true : false;
}
bool Event::wait ( double timeOut )
{
if(id==0) throw std::logic_error(String("event was deleted"));
epicsEventWaitStatus status = epicsEventWaitWithTimeout(id,timeOut);
return status==epicsEventWaitOK ? true : false;
}
bool Event::tryWait ()
{
if(id==0) throw std::logic_error(String("event was deleted"));
epicsEventWaitStatus status = epicsEventTryWait(id);
return status==epicsEventWaitOK ? true : false;
}
+1 -13
View File
@@ -16,22 +16,10 @@
namespace epics { namespace pvData {
enum EventWaitStatus {
eventWaitOK,
eventWaitTimeout,
eventWaitError
};
enum EventInitialState {
eventEmpty,
eventFull
};
class Event : private NoDefaultMethods {
public:
explicit Event(bool = false);
~Event();
Event(EventInitialState initial);
static ConstructDestructCallback *getConstructDestructCallback();
void signal();
bool wait (); /* blocks until full */
+17 -39
View File
@@ -81,14 +81,13 @@ ConstructDestructCallback *Executor::getConstructDestructCallback()
return pConstructDestructCallback;
}
class ExecutorPvt : public RunnableReady {
class ExecutorPvt : public Runnable{
public:
ExecutorPvt(String threadName,ThreadPriority priority);
~ExecutorPvt();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
void destroy();
virtual void run(ThreadReady *threadReady);
virtual void run();
private:
ExecutorList *executorList;
ExecutorList *runList;
@@ -102,37 +101,39 @@ private:
ExecutorPvt::ExecutorPvt(String threadName,ThreadPriority priority)
: executorList(new ExecutorList()),
runList(new ExecutorList()),
moreWork(new Event(eventEmpty)),
stopped(new Event(eventEmpty)),
moreWork(new Event(false)),
stopped(new Event(false)),
mutex(Mutex()),
alive(true),
thread(new Thread(threadName,priority,this))
{
thread->start();
}
{}
ExecutorPvt::~ExecutorPvt()
{
{
Lock xx(&mutex);
alive = false;
}
moreWork->signal();
{
Lock xx(&mutex);
stopped->wait();
}
ExecutorListNode *node;
while((node=executorList->removeHead())!=0) {
delete node->getObject();
}
delete thread;
delete stopped;
delete moreWork;
delete runList;
delete executorList;
delete thread;
}
void ExecutorPvt::run(ThreadReady *threadReady)
void ExecutorPvt::run()
{
bool firstTime = true;
while(alive) {
ExecutorListNode * executorListNode = 0;
if(firstTime) {
firstTime = false;
threadReady->ready();
}
while(alive && runList->isEmpty()) {
moreWork->wait();
}
@@ -164,20 +165,6 @@ void ExecutorPvt::execute(ExecutorNode *node)
if(isEmpty) moreWork->signal();
}
void ExecutorPvt::destroy()
{
{
Lock xx(&mutex);
alive = false;
}
moreWork->signal();
{
Lock xx(&mutex);
stopped->wait();
}
delete this;
}
Executor::Executor(String threadName,ThreadPriority priority)
: pImpl(new ExecutorPvt(threadName,priority))
{
@@ -187,23 +174,14 @@ Executor::Executor(String threadName,ThreadPriority priority)
}
Executor::~Executor() {
delete pImpl;
Lock xx(globalMutex);
totalDestruct++;
}
Executor *Executor::create(String threadName,ThreadPriority priority)
{
return new Executor(threadName,priority);
}
ExecutorNode * Executor::createNode(Command*command)
{return pImpl->createNode(command);}
void Executor::execute(ExecutorNode *node) {pImpl->execute(node);}
void Executor::destroy() {
pImpl->destroy();
delete this;
}
}}
+4 -6
View File
@@ -24,14 +24,12 @@ public:
class Executor : private NoDefaultMethods {
public:
static ConstructDestructCallback *getConstructDestructCallback();
static Executor *create(String threadName,ThreadPriority priority);
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
void destroy();
private:
Executor(String threadName,ThreadPriority priority);
~Executor();
static ConstructDestructCallback *getConstructDestructCallback();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
private:
class ExecutorPvt *pImpl;
};
+18 -15
View File
@@ -17,8 +17,9 @@ class LinkedListNode : private LinkedListVoidNode {
public:
LinkedListNode(T *object) : LinkedListVoidNode(object){}
~LinkedListNode() {}
T *getObject() { return (T *)LinkedListVoidNode::getObject();}
T *getObject() { return static_cast<T *>(LinkedListVoidNode::getObject());}
bool isOnList() {return LinkedListVoidNode::isOnList();}
friend class LinkedList<T>;
};
template <typename T>
@@ -29,49 +30,51 @@ public:
int getLength() {return LinkedListVoid::getLength();}
void addTail(LinkedListNode<T> *listNode)
{
LinkedListVoid::addTail((LinkedListVoidNode *)listNode);
LinkedListVoid::addTail(static_cast<LinkedListVoidNode *>(listNode));
}
void addHead(LinkedListNode<T> *listNode)
{
LinkedListVoid::addHead((LinkedListVoidNode *)listNode);
LinkedListVoid::addHead(static_cast<LinkedListVoidNode *>(listNode));
}
void insertAfter(LinkedListNode<T> *listNode,
LinkedListNode<T> *addNode)
{
LinkedListVoid::insertAfter(
(LinkedListVoidNode *)listNode,(LinkedListVoidNode *)addNode);
static_cast<LinkedListVoidNode *>(listNode),
static_cast<LinkedListVoidNode *>(addNode));
}
void insertBefore(LinkedListNode<T> *listNode,
LinkedListNode<T> *addNode)
{
LinkedListVoid::insertBefore((LinkedListVoidNode *)listNode,
(LinkedListVoidNode *)addNode);
LinkedListVoid::insertBefore(
static_cast<LinkedListVoidNode *>(listNode),
static_cast<LinkedListVoidNode *>(addNode));
}
LinkedListNode<T> *removeTail(){
return (LinkedListNode<T>*)LinkedListVoid::removeTail();
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeTail());
}
LinkedListNode<T> *removeHead(){
return (LinkedListNode<T>*)LinkedListVoid::removeHead();
return static_cast<LinkedListNode<T> *>(LinkedListVoid::removeHead());
}
void remove(LinkedListNode<T> *listNode){
LinkedListVoid::remove((LinkedListVoidNode *)listNode);
LinkedListVoid::remove(static_cast<LinkedListVoidNode *>(listNode));
}
void remove(T *object){
LinkedListVoid::remove(object);
}
LinkedListNode<T> *getHead(){
return (LinkedListNode<T>*)LinkedListVoid::getHead();
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getHead());
}
LinkedListNode<T> *getTail(){
return (LinkedListNode<T>*)LinkedListVoid::getTail();
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getTail());
}
LinkedListNode<T> *getNext(LinkedListNode<T> *listNode){
return (LinkedListNode<T>*)LinkedListVoid::getNext(
(LinkedListVoidNode *)listNode);
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getNext(
static_cast<LinkedListVoidNode *>(listNode)));
}
LinkedListNode<T> *getPrev(LinkedListNode<T> *listNode){
return (LinkedListNode<T>*)LinkedListVoid::getPrev(
(LinkedListVoidNode *)listNode);
return static_cast<LinkedListNode<T> *>(LinkedListVoid::getPrev(
static_cast<LinkedListVoidNode *>(listNode)));
}
bool isEmpty() { return LinkedListVoid::isEmpty();}
bool contains(T *object) { return LinkedListVoid::contains(object);}
+24 -4
View File
@@ -69,7 +69,7 @@ static void initPvt()
LinkedListVoidNode::LinkedListVoidNode(void *object)
: object(object),before(0),after(0)
: object(object),before(0),after(0),linkedListVoid(0)
{
initPvt();
Lock xx(globalMutex);
@@ -138,6 +138,7 @@ 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;
@@ -150,6 +151,7 @@ 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;
@@ -168,6 +170,10 @@ void LinkedListVoid::insertAfter(LinkedListVoidNode *node,
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;
@@ -186,6 +192,10 @@ void LinkedListVoid::insertBefore(LinkedListVoidNode *node,
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;
@@ -209,12 +219,15 @@ LinkedListVoidNode *LinkedListVoid::removeHead()
return node;
}
void LinkedListVoid::remove(LinkedListVoidNode *listNode)
void LinkedListVoid::remove(LinkedListVoidNode *node)
{
LinkedListVoidNode *node = listNode;
if(node->before==0 || node->after==0) {
throw std::logic_error(String("listNode not on list"));
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;
@@ -233,6 +246,7 @@ void LinkedListVoid::remove(void * object)
}
node = getNext(node);
}
throw std::logic_error(String("object not on this list"));
}
LinkedListVoidNode *LinkedListVoid::getHead()
@@ -249,12 +263,18 @@ LinkedListVoidNode *LinkedListVoid::getTail()
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;
}
+1
View File
@@ -28,6 +28,7 @@ private:
void *object;
LinkedListVoidNode *before;
LinkedListVoidNode *after;
LinkedListVoid *linkedListVoid;
// do not implement the following
LinkedListVoidNode(const LinkedListVoidNode&);
LinkedListVoidNode & operator=(const LinkedListVoidNode&);
+18 -18
View File
@@ -14,25 +14,25 @@
namespace epics { namespace pvData {
class Mutex {
public:
Mutex() : id(epicsMutexMustCreate()){}
~Mutex() { epicsMutexDestroy(id) ;};
void lock(){epicsMutexMustLock(id);}\
void unlock(){epicsMutexUnlock(id);}
private:
epicsMutexId id;
};
class Mutex {
public:
Mutex() : id(epicsMutexMustCreate()){}
~Mutex() { epicsMutexDestroy(id) ;}
void lock(){epicsMutexMustLock(id);}
void unlock(){epicsMutexUnlock(id);}
private:
epicsMutexId id;
};
class Lock : private NoDefaultMethods {
public:
explicit Lock(Mutex *pm)
: mutexPtr(pm)
{mutexPtr->lock();}
~Lock(){mutexPtr->unlock();}
private:
Mutex *mutexPtr;
};
class Lock : private NoDefaultMethods {
public:
explicit Lock(Mutex *pm)
: mutexPtr(pm)
{mutexPtr->lock();}
~Lock(){mutexPtr->unlock();}
private:
Mutex *mutexPtr;
};
}}
#endif /* LOCK_H */
+9 -9
View File
@@ -10,16 +10,16 @@
namespace epics { namespace pvData {
typedef signed char int8;
typedef short int16;
typedef int int32;
typedef long long int64;
typedef unsigned int uint32;
typedef unsigned long long uint64;
typedef signed char int8;
typedef short int16;
typedef int int32;
typedef long long int64;
typedef unsigned int uint32;
typedef unsigned long long uint64;
typedef std::string String;
typedef std::string * StringBuilder;
typedef String* StringArray;
typedef std::string String;
typedef std::string * StringBuilder;
typedef String* StringArray;
}}
#endif /* PVTYPE_H */
+20
View File
@@ -0,0 +1,20 @@
/* requester.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 <string>
#include "requester.h"
namespace epics { namespace pvData {
static std::string typeName[] = {
String("info"),
String("warning"),
String("error"),
String("fatalError")
};
StringArray messageTypeName = typeName;
}}
+13 -15
View File
@@ -7,24 +7,22 @@
#include <string>
#ifndef REQUESTER_H
#define REQUESTER_H
#include "pvIntrospect.h"
#include "pvType.h"
namespace epics { namespace pvData {
class Requester;
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
class Requester;
static std::string messageTypeName[] = {
"info","warning","error","fatalError"
};
class Requester {
public:
virtual String getRequesterName() = 0;
virtual void message(String message,MessageType messageType) = 0;
};
enum MessageType {
infoMessage,warningMessage,errorMessage,fatalErrorMessage
};
extern StringArray messageTypeName;
class Requester {
public:
virtual String getRequesterName() = 0;
virtual void message(String message,MessageType messageType) = 0;
};
}}
#endif /* REQUESTER_H */
+30 -3
View File
@@ -9,6 +9,7 @@
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdexcept>
#include "noDefaultMethods.h"
#include "lock.h"
@@ -62,6 +63,7 @@ ShowConstructDestruct::ShowConstructDestruct() {}
void ShowConstructDestruct::constuctDestructTotals(FILE *fd)
{
getShowConstructDestruct(); // make it initialize
Lock xx(globalMutex);
ListNode *node = list->getHead();
while(node!=0) {
@@ -80,8 +82,33 @@ void ShowConstructDestruct::constuctDestructTotals(FILE *fd)
void ShowConstructDestruct::registerCallback(ConstructDestructCallback *callback)
{
static ConstructDestructCallback *listCallback = 0;
static ConstructDestructCallback *listNodeCallback = 0;
Lock xx(globalMutex);
ListNode *listNode = new ListNode(callback);
ListNode *listNode = 0;
if(list==0) {
if(callback->getConstructName().compare("linkedListNode")==0) {
listNodeCallback = callback;
} else if(callback->getConstructName().compare("linkedList")==0) {
listCallback = callback;
} else {
throw std::logic_error(String("ShowConstructDestruct::registerCallback"));
}
return;
}
if(listCallback!=0) {
if(listNodeCallback==0) {
throw std::logic_error(String(
"ShowConstructDestruct::registerCallback expected listNodeCallback!=0"));
}
listNode = new ListNode(listNodeCallback);
list->addTail(listNode);
listNode = new ListNode(listCallback);
list->addTail(listNode);
listCallback = 0;
listNodeCallback = 0;
}
listNode = new ListNode(callback);
list->addTail(listNode);
}
@@ -91,9 +118,9 @@ ShowConstructDestruct * getShowConstructDestruct()
Lock xx(&mutex);
if(pShowConstructDestruct==0) {
globalMutex = new Mutex();
list = new List();
pShowConstructDestruct = new ShowConstructDestruct();
}
list = new List();
}
return pShowConstructDestruct;
}
+2 -2
View File
@@ -40,8 +40,8 @@ private:
class ShowConstructDestruct : private NoDefaultMethods {
public:
static void constuctDestructTotals(FILE *fd);
static void registerCallback(ConstructDestructCallback *callback);
void constuctDestructTotals(FILE *fd);
void registerCallback(ConstructDestructCallback *callback);
private:
ShowConstructDestruct();
friend ShowConstructDestruct* getShowConstructDestruct();
+40 -68
View File
@@ -9,6 +9,7 @@
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <epicsThread.h>
#include <epicsEvent.h>
@@ -48,9 +49,7 @@ typedef LinkedList<ThreadListElement> ThreadList;
static volatile int64 totalConstruct = 0;
static volatile int64 totalDestruct = 0;
static Mutex *globalMutex = 0;
static void addThread(Thread *thread);
static void removeThread(Thread *thread);
static ThreadList *list;
static ThreadList *threadList;
static int64 getTotalConstruct()
{
@@ -72,7 +71,7 @@ static void init()
Lock xx(&mutex);
if(globalMutex==0) {
globalMutex = new Mutex();
list = new ThreadList();
threadList = new ThreadList();
pConstructDestructCallback = new ConstructDestructCallback(
String("thread"),
getTotalConstruct,getTotalDestruct,0);
@@ -96,38 +95,37 @@ int ThreadPriorityFunc::getEpicsPriority(ThreadPriority threadPriority) {
extern "C" void myFunc ( void * pPvt );
class Runnable : public ThreadReady {
class ThreadPvt {
public:
Runnable(Thread *thread,String name,
ThreadPriority priority, RunnableReady *runnable);
virtual ~Runnable();
Thread *start();
ThreadPvt(Thread *thread,String name,
ThreadPriority priority, Runnable*runnable);
virtual ~ThreadPvt();
void ready();
public: // only used within this source module
Thread *thread;
String name;
ThreadPriority priority;
RunnableReady *runnable;
Event waitStart;
Runnable *runnable;
bool isReady;
ThreadListElement *threadListElement;
Event *waitDone;
epicsThreadId id;
};
extern "C" void myFunc ( void * pPvt )
{
Runnable *runnable = (Runnable *)pPvt;
runnable->waitStart.signal();
addThread(runnable->thread);
runnable->runnable->run(runnable);
removeThread(runnable->thread);
ThreadPvt *threadPvt = (ThreadPvt *)pPvt;
threadPvt->runnable->run();
threadPvt->waitDone->signal();
}
Runnable::Runnable(Thread *thread,String name,
ThreadPriority priority, RunnableReady *runnable)
ThreadPvt::ThreadPvt(Thread *thread,String name,
ThreadPriority priority, Runnable *runnable)
: thread(thread),name(name),priority(priority),
runnable(runnable),
waitStart(eventEmpty),
isReady(false),
threadListElement(new ThreadListElement(thread)),
waitDone(new Event()),
id(epicsThreadCreate(
name.c_str(),
epicsPriority[priority],
@@ -136,32 +134,35 @@ Runnable::Runnable(Thread *thread,String name,
{
init();
Lock xx(globalMutex);
threadList->addTail(threadListElement->node);
totalConstruct++;
}
Runnable::~Runnable()
ThreadPvt::~ThreadPvt()
{
bool result = waitDone->wait(2.0);
if(!result) {
throw std::logic_error(String("delete thread but run did not return"));
String message("destroy thread ");
message += thread->getName();
message += " but run did not return";
throw std::logic_error(message);
}
if(!threadListElement->node->isOnList()) {
String message("destroy thread ");
message += thread->getName();
message += " is not on threadlist";
throw std::logic_error(message);
}
threadList->remove(threadListElement->node);
delete waitDone;
delete threadListElement;
Lock xx(globalMutex);
totalDestruct++;
}
Thread * Runnable::start()
{
if(!waitStart.wait(10.0)) {
fprintf(stderr,"thread %s did not call ready\n",thread->getName().c_str());
}
return thread;
}
void Runnable::ready()
{
waitStart.signal();
}
Thread::Thread(String name,ThreadPriority priority,RunnableReady *runnableReady)
: pImpl(new Runnable(this,name,priority,runnableReady))
Thread::Thread(String name,ThreadPriority priority,Runnable *runnable)
: pImpl(new ThreadPvt(this,name,priority,runnable))
{
}
@@ -176,12 +177,6 @@ ConstructDestructCallback *Thread::getConstructDestructCallback()
return pConstructDestructCallback;
}
void Thread::start()
{
pImpl->start();
}
void Thread::sleep(double seconds)
{
epicsThreadSleep(seconds);;
@@ -201,38 +196,15 @@ void Thread::showThreads(StringBuilder buf)
{
init();
Lock xx(globalMutex);
ThreadListNode *node = list->getHead();
ThreadListNode *node = threadList->getHead();
while(node!=0) {
Thread *thread = node->getObject()->thread;
*buf += thread->getName();
*buf += " ";
*buf += threadPriorityNames[thread->getPriority()];
*buf += "\n";
node = list->getNext(node);
node = threadList->getNext(node);
}
}
void addThread(Thread *thread)
{
Lock xx(globalMutex);
ThreadListElement *element = new ThreadListElement(thread);
list->addTail(element->node);
}
void removeThread(Thread *thread)
{
Lock xx(globalMutex);
ThreadListNode *node = list->getHead();
while(node!=0) {
if(node->getObject()->thread==thread) {
list->remove(node);
delete node;
return;
}
node = list->getNext(node);
}
fprintf(stderr,"removeThread but thread %s did not in list\n",
thread->getName().c_str());
}
}}
+6 -12
View File
@@ -8,6 +8,7 @@
#define THREAD_H
#include "noDefaultMethods.h"
#include "pvType.h"
#include "showConstructDestruct.h"
namespace epics { namespace pvData {
@@ -27,32 +28,25 @@ public:
static int getEpicsPriority(ThreadPriority threadPriority);
};
class ThreadReady {
class Runnable{
public:
virtual void ready() = 0;
};
class RunnableReady {
public:
virtual void run(ThreadReady *threadReady) = 0;
virtual void run() = 0;
};
class Thread;
class Thread : private NoDefaultMethods {
public:
Thread(String name,ThreadPriority priority,RunnableReady *runnableReady);
Thread(String name,ThreadPriority priority,Runnable *runnable);
~Thread();
static ConstructDestructCallback *getConstructDestructCallback();
void start();
String getName();
ThreadPriority getPriority();
static void showThreads(StringBuilder buf);
static void sleep(double seconds);
private:
class Runnable *pImpl;
friend class Runnable;
class ThreadPvt *pImpl;
friend class ThreadPvt;
};
}}
+37 -9
View File
@@ -24,8 +24,44 @@ int64 posixEpochAtEpicsEpoch = POSIX_TIME_AT_EPICS_EPOCH;
TimeStamp::TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds)
: secondsPastEpoch(secondsPastEpoch),nanoSeconds(nanoSeconds)
{}
{
normalize();
}
void TimeStamp::normalize()
{
if(nanoSeconds>=0 && nanoSeconds<nanoSecPerSec) return;
while(nanoSeconds>=nanoSecPerSec) {
nanoSeconds -= nanoSecPerSec;
secondsPastEpoch++;
}
while(nanoSeconds<0) {
nanoSeconds += nanoSecPerSec;
secondsPastEpoch--;
}
}
void TimeStamp::fromTime_t(const time_t & tt)
{
epicsTimeStamp epicsTime;
epicsTimeFromTime_t(&epicsTime,tt);
secondsPastEpoch = epicsTime.secPastEpoch + posixEpochAtEpicsEpoch;
nanoSeconds = epicsTime.nsec;
}
void TimeStamp::toTime_t(time_t &tt) const
{
epicsTimeStamp epicsTime;
epicsTime.secPastEpoch = secondsPastEpoch-posixEpochAtEpicsEpoch;
epicsTime.nsec = nanoSeconds;
epicsTimeToTime_t(&tt,&epicsTime);
}
void TimeStamp::put(int64 milliseconds)
{
secondsPastEpoch = milliseconds/1000;
nanoSeconds = (milliseconds%1000)*1000000;
}
void TimeStamp::getCurrent()
{
@@ -144,12 +180,4 @@ int64 TimeStamp::getMilliseconds()
return secondsPastEpoch*1000 + nanoSeconds/1000000;
}
void TimeStamp::put(int64 milliseconds)
{
secondsPastEpoch = milliseconds/1000;
nanoSeconds = (milliseconds%1000)*1000000;
}
}}
+8 -6
View File
@@ -6,6 +6,7 @@
*/
#ifndef TIMESTAMP_H
#define TIMESTAMP_H
#include <ctime>
#include "epicsTime.h"
#include "pvType.h"
@@ -20,10 +21,12 @@ class TimeStamp {
public:
TimeStamp()
:secondsPastEpoch(0),nanoSeconds(0) {}
TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0);
//default constructors and destructor are OK
//This class should not be extended
TimeStamp(int64 secondsPastEpoch,int32 nanoSeconds = 0);
TimeStamp(epicsTimeStamp &epics);
void normalize();
void fromTime_t(const time_t &);
void toTime_t(time_t &) const;
int64 getSecondsPastEpoch() const {return secondsPastEpoch;}
int64 getEpicsSecondsPastEpoch() const {
return secondsPastEpoch - posixEpochAtEpicsEpoch;
@@ -32,7 +35,9 @@ public:
void put(int64 secondsPastEpoch,int32 nanoSeconds = 0) {
this->secondsPastEpoch = secondsPastEpoch;
this->nanoSeconds = nanoSeconds;
normalize();
}
void put(int64 milliseconds);
void getCurrent();
double toSeconds() const ;
bool operator==(TimeStamp const &) const;
@@ -46,10 +51,7 @@ public:
TimeStamp & operator-=(int64 seconds);
TimeStamp & operator+=(double seconds);
TimeStamp & operator-=(double seconds);
// milliseconds since epoch
int64 getMilliseconds();
void put(int64 milliseconds);
int64 getMilliseconds(); // milliseconds since epoch
private:
static int64 diffInt(TimeStamp const &left,TimeStamp const &right );
int64 secondsPastEpoch;
+46 -68
View File
@@ -87,14 +87,14 @@ ConstructDestructCallback * Timer::getConstructDestructCallback()
class TimerNodePvt;
typedef LinkedListNode<TimerNodePvt> ListNode;
typedef LinkedList<TimerNodePvt> List;
typedef LinkedListNode<TimerNodePvt> TimerListNode;
typedef LinkedList<TimerNodePvt> TimerList;
class TimerNodePvt {
public:
TimerNode *timerNode;
TimerCallback *callback;
ListNode *listNode;
TimerListNode *timerListNode;
TimeStamp timeToRun;
TimerPvt *timerPvt;
double period;
@@ -104,65 +104,63 @@ public:
TimerNodePvt::TimerNodePvt(TimerNode *timerNode,TimerCallback *callback)
: timerNode(timerNode),callback(callback),
listNode(new ListNode(this)),timeToRun(TimeStamp()),
timerListNode(new TimerListNode(this)),timeToRun(TimeStamp()),
timerPvt(0), period(0.0)
{}
TimerNodePvt::~TimerNodePvt()
{
delete listNode;
delete timerListNode;
}
struct TimerPvt : public RunnableReady {
struct TimerPvt : public Runnable{
public:
TimerPvt(String threadName,ThreadPriority priority);
~TimerPvt();
virtual void run(ThreadReady *threadReady);
virtual void run();
public: // only used by this source module
List *list;
TimerList *timerList;
Mutex mutex;
Event *waitForWork;
Event *waitForDone;
Thread *thread;
volatile bool alive;
Thread *thread;
};
TimerPvt::TimerPvt(String threadName,ThreadPriority priority)
: list(new List()),
: timerList(new TimerList()),
mutex(Mutex()),
waitForWork(new Event(eventEmpty)),
waitForDone(new Event(eventEmpty)),
thread(new Thread(threadName,priority,this)),
alive(true)
{
thread->start();
}
waitForWork(new Event(false)),
waitForDone(new Event(false)),
alive(true),
thread(new Thread(threadName,priority,this))
{}
TimerPvt::~TimerPvt()
{
delete thread;
delete waitForDone;
delete waitForWork;
delete list;
delete timerList;
}
static void addElement(TimerPvt *timer,TimerNodePvt *node)
{
List *list = timer->list;
ListNode *nextNode = list->getHead();
TimerList *timerList = timer->timerList;
TimerListNode *nextNode = timerList->getHead();
if(nextNode==0) {
list->addTail(node->listNode);
timerList->addTail(node->timerListNode);
return;
}
while(true) {
TimerNodePvt *listNode = nextNode->getObject();
if((node->timeToRun)<(listNode->timeToRun)) {
list->insertBefore(listNode->listNode,node->listNode);
TimerNodePvt *timerListNode = nextNode->getObject();
if((node->timeToRun)<(timerListNode->timeToRun)) {
timerList->insertBefore(timerListNode->timerListNode,node->timerListNode);
return;
}
nextNode = list->getNext(listNode->listNode);
nextNode = timerList->getNext(timerListNode->timerListNode);
if(nextNode==0) {
list->addTail(node->listNode);
timerList->addTail(node->timerListNode);
return;
}
}
@@ -177,31 +175,22 @@ TimerNode::TimerNode(TimerCallback *callback)
totalNodeConstruct++;
}
TimerNode *TimerNode::create(TimerCallback *callback)
{
return new TimerNode(callback);
}
TimerNode::~TimerNode()
{
cancel();
delete pImpl;
Lock xx(globalMutex);
totalNodeDestruct++;
}
void TimerNode::destroy()
{
cancel();
delete this;
}
void TimerNode::cancel()
{
TimerPvt *timerPvt = pImpl->timerPvt;
if(timerPvt==0) return;
Lock xx(&timerPvt->mutex);
if(pImpl->timerPvt==0) return;
pImpl->timerPvt->list->remove(pImpl);
pImpl->timerPvt->timerList->remove(pImpl);
pImpl->timerPvt = 0;
}
@@ -210,13 +199,12 @@ bool TimerNode::isScheduled()
TimerPvt *pvt = pImpl->timerPvt;
if(pvt==0) return false;
Lock xx(&pvt->mutex);
return pImpl->listNode->isOnList();
return pImpl->timerListNode->isOnList();
}
void TimerPvt::run(ThreadReady *threadReady)
void TimerPvt::run()
{
threadReady->ready();
TimeStamp currentTime;
while(alive) {
currentTime.getCurrent();
@@ -225,25 +213,25 @@ void TimerPvt::run(ThreadReady *threadReady)
TimerNodePvt *nodeToCall = 0;
{
Lock xx(&mutex);
ListNode *listNode = list->getHead();
if(listNode!=0) {
TimerNodePvt *timerNodePvt = listNode->getObject();
TimerListNode *timerListNode = timerList->getHead();
if(timerListNode!=0) {
TimerNodePvt *timerNodePvt = timerListNode->getObject();
timeToRun = &timerNodePvt->timeToRun;
double diff = TimeStamp::diff(
*timeToRun,currentTime);
if(diff<=0.0) {
nodeToCall = timerNodePvt;
list->removeHead();
timerList->removeHead();
period = timerNodePvt->period;
if(period>0) {
if(period>0.0) {
timerNodePvt->timeToRun += period;
addElement(this,timerNodePvt);
} else {
timerNodePvt->timerPvt = 0;
}
listNode = list->getHead();
if(listNode!=0) {
timerNodePvt = listNode->getObject();
timerListNode = timerList->getHead();
if(timerListNode!=0) {
timerNodePvt = timerListNode->getObject();
timeToRun = &timerNodePvt->timeToRun;
} else {
timeToRun = 0;
@@ -273,31 +261,21 @@ Timer::Timer(String threadName, ThreadPriority priority)
totalTimerConstruct++;
}
Timer * Timer::create(String threadName, ThreadPriority priority)
{
return new Timer(threadName,priority);
}
Timer::~Timer() {
delete pImpl;
Lock xx(globalMutex);
totalTimerDestruct++;
}
void Timer::destroy()
{
{
Lock xx(&pImpl->mutex);
pImpl->alive = false;
pImpl->waitForWork->signal();
pImpl->waitForDone->wait();
}
List *list = pImpl->list;
ListNode *node = 0;
while((node = list->removeHead())!=0) {
pImpl->waitForWork->signal();
pImpl->waitForDone->wait();
TimerList *timerList = pImpl->timerList;
TimerListNode *node = 0;
while((node = timerList->removeHead())!=0) {
node->getObject()->callback->timerStopped();
}
delete this;
delete pImpl;
Lock xx(globalMutex);
totalTimerDestruct++;
}
void Timer::scheduleAfterDelay(TimerNode *timerNode,double delay)
@@ -307,7 +285,7 @@ void Timer::scheduleAfterDelay(TimerNode *timerNode,double delay)
void Timer::schedulePeriodic(TimerNode *timerNode,double delay,double period)
{
TimerNodePvt *timerNodePvt = timerNode->pImpl;
if(timerNodePvt->listNode->isOnList()) {
if(timerNodePvt->timerListNode->isOnList()) {
throw std::logic_error(String("already queued"));
}
if(!pImpl->alive) {
@@ -323,7 +301,7 @@ void Timer::schedulePeriodic(TimerNode *timerNode,double delay,double period)
Lock xx(&pImpl->mutex);
timerNodePvt->timerPvt = pImpl;
addElement(pImpl,timerNodePvt);
TimerNodePvt *first = pImpl->list->getHead()->getObject();
TimerNodePvt *first = pImpl->timerList->getHead()->getObject();
if(first==timerNodePvt) isFirst = true;
}
if(isFirst) pImpl->waitForWork->signal();
+4 -8
View File
@@ -27,28 +27,24 @@ public:
class TimerNode : private NoDefaultMethods {
public:
TimerNode(TimerCallback *timerCallback);
~TimerNode();
static ConstructDestructCallback *getConstructDestructCallback();
static TimerNode *create(TimerCallback *timerCallback);
void destroy();
void cancel();
bool isScheduled();
private:
TimerNode(TimerCallback *timerCallback);
~TimerNode();
class TimerNodePvt *pImpl;
friend class Timer;
};
class Timer : private NoDefaultMethods {
public:
Timer(String threadName, ThreadPriority priority);
~Timer();
static ConstructDestructCallback *getConstructDestructCallback();
static Timer * create(String threadName, ThreadPriority priority);
void destroy();
void scheduleAfterDelay(TimerNode *timerNode,double delay);
void schedulePeriodic(TimerNode *timerNode,double delay,double period);
private:
Timer(String threadName, ThreadPriority priority);
~Timer();
class TimerPvt *pImpl;
friend class TimerNode;
};