switch to epicsThread

Create a thin wrapper to account for the current interface and behavior
differences.
This commit is contained in:
Michael Davidsaver
2011-03-02 17:14:07 -05:00
parent 0c61ac0833
commit 4c88ef8e99
4 changed files with 54 additions and 213 deletions

View File

@@ -35,7 +35,6 @@ LIBSRCS += requester.cpp
LIBSRCS += serializeHelper.cpp
LIBSRCS += linkedListVoid.cpp
LIBSRCS += event.cpp
LIBSRCS += thread.cpp
LIBSRCS += executor.cpp
LIBSRCS += timeFunction.cpp
LIBSRCS += timer.cpp

View File

@@ -1,180 +0,0 @@
/* thread.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 <epicsThread.h>
#include <epicsEvent.h>
#include <epicsExit.h>
#include "lock.h"
#include "event.h"
#include "thread.h"
#include "linkedList.h"
#include "CDRMonitor.h"
namespace epics { namespace pvData {
static unsigned int epicsPriority[] = {
epicsThreadPriorityLow,
epicsThreadPriorityLow + 15,
epicsThreadPriorityMedium - 15,
epicsThreadPriorityMedium,
epicsThreadPriorityMedium + 15,
epicsThreadPriorityHigh - 15,
epicsThreadPriorityHigh
};
unsigned int const * const ThreadPriorityFunc::getEpicsPriorities()
{
return epicsPriority;
}
static String threadPriorityNames[] = {
String("lowest"),String("lower"),String("low"),
String("middle"),
String("high"),String("higher"),String("highest")
};
typedef LinkedListNode<Thread> ThreadListNode;
typedef LinkedList<Thread> ThreadList;
PVDATA_REFCOUNT_MONITOR_DEFINE(thread);
static Mutex listGuard;
static ThreadList *threadList;
static void deleteStatic(void*)
{
delete threadList;
}
static void init(void*)
{
threadList = new ThreadList();
epicsAtExit(&deleteStatic,0);
}
static
epicsThreadOnceId initOnce = EPICS_THREAD_ONCE_INIT;
int ThreadPriorityFunc::getEpicsPriority(ThreadPriority threadPriority) {
return epicsPriority[threadPriority];
}
class Thread::ThreadPvt {
public:
ThreadPvt(Thread *thread,String name,
ThreadPriority priority, Runnable*runnable);
~ThreadPvt();
void ready();
const String name;
const ThreadPriority priority;
private:
Runnable *runnable;
bool isReady;
ThreadListNode threadNode;
Event waitDone;
epicsThreadId id;
static void threadMain(void*);
};
void Thread::ThreadPvt::threadMain ( void * pPvt )
{
ThreadPvt *threadPvt = (ThreadPvt *)pPvt;
threadPvt->runnable->run();
threadPvt->waitDone.signal();
}
Thread::ThreadPvt::ThreadPvt(Thread *thread,String name,
ThreadPriority priority, Runnable *runnable)
: name(name),priority(priority),
runnable(runnable),
isReady(false),
threadNode(*thread),
waitDone(),
id(epicsThreadCreate(
name.c_str(),
epicsPriority[priority],
epicsThreadGetStackSize(epicsThreadStackSmall),
&threadMain,this))
{
if(!id) {
throw std::runtime_error("Unable to create thread");
}
epicsThreadOnce(&initOnce, &init, 0);
assert(threadList);
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(thread);
Lock x(listGuard);
threadList->addTail(threadNode);
}
Thread::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 += name;
message += " but run did not return";
throw std::logic_error(message);
}
if(!threadNode.isOnList()) {
String message("destroy thread ");
message += name;
message += " is not on threadlist";
throw std::logic_error(message);
}
Lock x(listGuard);
threadList->remove(threadNode);
PVDATA_REFCOUNT_MONITOR_DESTRUCT(thread);
}
Thread::Thread(String name,ThreadPriority priority,Runnable *runnable)
: pImpl(new ThreadPvt(this,name,priority,runnable))
{
}
// Must be present or auto_ptr<> will not delete ThreadPvt
Thread::~Thread() {}
void Thread::sleep(double seconds)
{
epicsThreadSleep(seconds);;
}
String Thread::getName()
{
return pImpl->name;
}
ThreadPriority Thread::getPriority()
{
return pImpl->priority;
}
void Thread::showThreads(StringBuilder buf)
{
Lock x(listGuard);
ThreadListNode *node = threadList->getHead();
while(node!=0) {
Thread &thread = node->getObject();
*buf += thread.getName();
*buf += " ";
*buf += threadPriorityNames[thread.getPriority()];
*buf += "\n";
node = threadList->getNext(*node);
}
}
}}

View File

@@ -10,42 +10,38 @@
#include "noDefaultMethods.h"
#include "pvType.h"
namespace epics { namespace pvData {
#include <epicsThread.h>
namespace epics { namespace pvData {
enum ThreadPriority {
lowestPriority,
lowerPriority,
lowPriority,
middlePriority,
highPriority,
higherPriority,
highestPriority
};
class ThreadPriorityFunc {
public:
static unsigned int const * const getEpicsPriorities();
static int getEpicsPriority(ThreadPriority threadPriority);
lowestPriority =epicsThreadPriorityLow,
lowerPriority =epicsThreadPriorityLow + 15,
lowPriority =epicsThreadPriorityMedium - 15,
middlePriority =epicsThreadPriorityMedium,
highPriority =epicsThreadPriorityMedium + 15,
higherPriority =epicsThreadPriorityHigh - 15,
highestPriority =epicsThreadPriorityHigh
};
class Runnable{
public:
virtual void run() = 0;
};
typedef epicsThreadRunable Runnable;
class Thread;
class Thread : private NoDefaultMethods {
class Thread : public epicsThread, private NoDefaultMethods {
public:
Thread(String name,ThreadPriority priority,Runnable *runnable);
~Thread();
String getName();
ThreadPriority getPriority();
static void showThreads(StringBuilder buf);
static void sleep(double seconds);
private:
class ThreadPvt;
std::auto_ptr<ThreadPvt> pImpl;
Thread(String name,ThreadPriority priority,Runnable *runnable)
:epicsThread(*runnable,
name.c_str(),
epicsThreadGetStackSize(epicsThreadStackBig),
priority)
{
this->start();
}
~Thread()
{
this->exitWait();
}
};
}}

View File

@@ -28,6 +28,33 @@
using namespace epics::pvData;
class Action : public Runnable {
public:
FILE *out;
bool actuallyRan;
Event begin, end;
Action(FILE* fp): out(fp), actuallyRan(false) {}
virtual void run() {
fprintf(out, "Action waiting\n");
begin.signal();
bool waited=end.wait();
actuallyRan=true;
fprintf(out, "Action1 %s\n", waited?"true":"false");
}
};
static void testThreadRun(FILE *fd) {
// show that we can control thread start and stop
Action ax(fd);
{
Thread tr("Action", lowPriority, &ax);
bool w=ax.begin.wait();
fprintf(fd, "main1 %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 {
public:
@@ -71,8 +98,6 @@ static void testBasic(FILE *fd) {
basic->run();
delete basic;
String buf("");
Thread::showThreads(&buf);
fprintf(fd,"threads\n%s\n",buf.c_str());
delete executor;
}
@@ -114,6 +139,7 @@ int main(int argc, char *argv[]) {
if(auxFileName!=0 && auxFileName[0]!=0) {
auxFd = fopen(auxFileName,"w+");
}
testThreadRun(fd);
testBasic(fd);
testThreadContext(fd,auxFd);
epicsExitCallAtExits();