diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index bfb1ede..24e55dc 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -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 diff --git a/pvDataApp/misc/thread.cpp b/pvDataApp/misc/thread.cpp deleted file mode 100644 index be08e06..0000000 --- a/pvDataApp/misc/thread.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include - -#include -#include -#include -#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 ThreadListNode; -typedef LinkedList 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); - } -} - -}} diff --git a/pvDataApp/misc/thread.h b/pvDataApp/misc/thread.h index 422d60f..afb3fb0 100644 --- a/pvDataApp/misc/thread.h +++ b/pvDataApp/misc/thread.h @@ -10,42 +10,38 @@ #include "noDefaultMethods.h" #include "pvType.h" -namespace epics { namespace pvData { +#include + +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 pImpl; + + Thread(String name,ThreadPriority priority,Runnable *runnable) + :epicsThread(*runnable, + name.c_str(), + epicsThreadGetStackSize(epicsThreadStackBig), + priority) + { + this->start(); + } + + ~Thread() + { + this->exitWait(); + } }; }} diff --git a/testApp/misc/testThread.cpp b/testApp/misc/testThread.cpp index ce046da..9950e73 100644 --- a/testApp/misc/testThread.cpp +++ b/testApp/misc/testThread.cpp @@ -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();