switch to epicsThread
Create a thin wrapper to account for the current interface and behavior differences.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user