diff --git a/src/libCom/osi/epicsThread.cpp b/src/libCom/osi/epicsThread.cpp index 892d73d..8a6efc4 100644 --- a/src/libCom/osi/epicsThread.cpp +++ b/src/libCom/osi/epicsThread.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -25,6 +26,7 @@ #include "epicsAlgorithm.h" #include "epicsTime.h" #include "epicsThread.h" +#include "epicsString.h" #include "epicsAssert.h" #include "epicsGuard.h" #include "errlog.h" @@ -348,7 +350,49 @@ extern "C" { assert ( id ); return id; } + + struct caller { + char *name; + EPICSTHREADCPPFUNC func; + void *parm; + + caller(const char *iname, EPICSTHREADCPPFUNC ifunc, void *iparm) : + name(epicsStrDup(iname)), func(ifunc), parm(iparm) {} + }; + static void callCpp(void *parm) + { + struct caller *pc = static_cast(parm); + try { + pc->func(pc->parm); + } + catch (std::exception &except) { + errlogPrintf("epicsThread::callCpp(): Unexpected exception " + "from thread '%s': \"%s\"\n", + pc->name, except.what()); + } + catch (...) { + errlogPrintf("epicsThread::callCpp(): Unexpected exception " + "from thread '%s'\n", pc->name); + } + std::free(pc->name); + delete pc; + } + } // extern "C" +epicsThreadId epicsThreadCreateCpp(const char * name, + unsigned int priority, unsigned int stackSize, + EPICSTHREADCPPFUNC func, void *parm) +{ + caller *pc = new caller(name, func, parm); + epicsThreadId tid = epicsThreadCreate(name, priority, stackSize, + callCpp, pc); + if (!tid) + throw epicsThread::unableToCreateThread (); + + return tid; +} + + // Ensure the main thread gets a unique ID epicsThreadId epicsThreadMainId = epicsThreadGetIdSelf(); diff --git a/src/libCom/osi/epicsThread.h b/src/libCom/osi/epicsThread.h index 84b2c47..78434cd 100644 --- a/src/libCom/osi/epicsThread.h +++ b/src/libCom/osi/epicsThread.h @@ -127,6 +127,11 @@ epicsShareFunc void * epicsShareAPI epicsThreadPrivateGet(epicsThreadPrivateId); #ifdef __cplusplus +typedef void (*EPICSTHREADCPPFUNC)(void *parm); +epicsShareFunc epicsThreadId epicsThreadCreateCpp(const char *name, + unsigned int priority, unsigned int stackSize, + EPICSTHREADCPPFUNC funptr,void *parm); + #include "epicsEvent.h" #include "epicsMutex.h" diff --git a/src/libCom/test/epicsAtomicTest.cpp b/src/libCom/test/epicsAtomicTest.cpp index 1c4dcf2..bd8d30c 100644 --- a/src/libCom/test/epicsAtomicTest.cpp +++ b/src/libCom/test/epicsAtomicTest.cpp @@ -137,9 +137,9 @@ void testIncrDecr () testOk ( get ( testData.m_testIterations ) == 0u, "get returns initial incr/decr test thread iterations value that was set" ); for ( size_t i = 0u; i < N; i++ ) { - epicsThreadCreate ( "incr", + epicsThreadCreateCpp ( "incr", 50, stackSize, incr < T >, & testData ); - epicsThreadCreate ( "decr", + epicsThreadCreateCpp ( "decr", 50, stackSize, decr < T >, & testData ); } while ( testData.m_testIterations < 2 * N ) { @@ -169,9 +169,9 @@ void testAddSub () testOk ( get ( testData.m_testIterations ) == 0u, "get returns initial incr/decr test thread iterations value that was set" ); for ( size_t i = 0u; i < N; i++ ) { - epicsThreadCreate ( "add", + epicsThreadCreateCpp ( "add", 50, stackSize, add < T >, & testData ); - epicsThreadCreate ( "sub", + epicsThreadCreateCpp ( "sub", 50, stackSize, sub < T >, & testData ); } while ( testData.m_testIterations < 2 * N ) { @@ -204,7 +204,7 @@ void testCAS () testOk ( get ( testData.m_testValue ) == trueValue < T > (), "set/get a true value" ); for ( size_t i = 0u; i < N; i++ ) { - epicsThreadCreate ( "tns", + epicsThreadCreateCpp ( "tns", 50, stackSize, cas < T >, & testData ); } set ( testData.m_testValue, falseValue < T > () ); diff --git a/src/libCom/test/epicsThreadTest.cpp b/src/libCom/test/epicsThreadTest.cpp index f80d3da..97bff56 100644 --- a/src/libCom/test/epicsThreadTest.cpp +++ b/src/libCom/test/epicsThreadTest.cpp @@ -64,7 +64,7 @@ typedef struct info { } info; extern "C" { -static void thread(void *arg) +static void thread1(void *arg) { info *pinfo = (info *)arg; @@ -78,6 +78,10 @@ static void thread(void *arg) } } +static void thread2(void *arg) +{ + thread1(arg); +} MAIN(epicsThreadTest) { @@ -104,10 +108,10 @@ MAIN(epicsThreadTest) unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); info infoA = {0}; - epicsThreadCreate("threadA", 50, stackSize, thread, &infoA); + epicsThreadCreate("threadA", 50, stackSize, thread1, &infoA); info infoB = {1}; - epicsThreadCreate("threadB", 50, stackSize, thread, &infoB); + epicsThreadCreateCpp("threadB", 50, stackSize, thread2, &infoB); epicsThreadSleep(2.0);