Use epicsThreadOnce for safe lazy initialization

Also use epicsAtExit to handle cleanup.
This commit is contained in:
Michael Davidsaver
2011-01-30 18:07:54 -05:00
parent d8fe325dc0
commit 099215986f
3 changed files with 47 additions and 59 deletions
+14 -12
View File
@@ -7,6 +7,8 @@
#include <string>
#include <cstdio>
#include <stdexcept>
#include <epicsThread.h>
#include <epicsExit.h>
#include <lock.h>
#include "pvIntrospect.h"
#include "standardField.h"
@@ -14,8 +16,6 @@
namespace epics { namespace pvData {
static Mutex globalMutex;
static bool notInited = true;
static StandardField* standardField = 0;
static String notImplemented("not implemented");
@@ -462,7 +462,7 @@ StandardField::StandardField(){init();}
StandardField::~StandardField(){
}
static void myDeleteStatic()
static void myDeleteStatic(void*)
{
int count = alarmField->getReferenceCount();
if(count!=1) printf("~StandardField() alarmField reference count %d\n",count);
@@ -502,16 +502,18 @@ static void myDeleteStatic()
enumeratedAlarmField->decReferenceCount();
}
static void myInitStatic(void*)
{
standardField = new StandardField();
fieldCreate = getFieldCreate();
epicsAtExit(&myDeleteStatic,0);
}
static
epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT;
StandardField * getStandardField() {
Lock xx(&globalMutex);
if(notInited) {
notInited = false;
standardField = new StandardField();
fieldCreate = getFieldCreate();
ShowConstructDestruct::registerCallback(
"standardField",
0,0,0,myDeleteStatic);
}
epicsThreadOnce(&myInitOnce,&myInitStatic,0);
return standardField;
}
+16 -14
View File
@@ -6,6 +6,8 @@
*/
#include <string>
#include <stdexcept>
#include <epicsThread.h>
#include <epicsExit.h>
#include <lock.h>
#include "pvIntrospect.h"
#include "pvData.h"
@@ -16,8 +18,6 @@
namespace epics { namespace pvData {
static Mutex globalMutex;
static bool notInited = true;
static StandardField *standardField = 0;
static String notImplemented("not implemented");
@@ -329,23 +329,25 @@ public:
StandardPVFieldExt(): StandardPVField(){};
};
static void myDeleteStatic()
static void myDeleteStatic(void*)
{
delete standardPVField;
}
static void myInitStatic(void*)
{
fieldCreate = getFieldCreate();
pvDataCreate = getPVDataCreate();
standardField = getStandardField();
standardPVField = new StandardPVFieldExt();
epicsAtExit(&myDeleteStatic, 0);
}
static
epicsThreadOnceId myInitOnce = EPICS_THREAD_ONCE_INIT;
StandardPVField * getStandardPVField() {
Lock xx(&globalMutex);
if(notInited) {
notInited = false;
fieldCreate = getFieldCreate();
pvDataCreate = getPVDataCreate();
standardField = getStandardField();
standardPVField = new StandardPVFieldExt();
ShowConstructDestruct::registerCallback(
"standardPVField",
0,0,0,myDeleteStatic);
}
epicsThreadOnce(&myInitOnce, &myInitStatic, 0);
return standardPVField;
}
+17 -33
View File
@@ -13,6 +13,7 @@
#include <epicsThread.h>
#include <epicsEvent.h>
#include <epicsExit.h>
#include "lock.h"
#include "event.h"
#include "thread.h"
@@ -47,41 +48,25 @@ class ThreadListElement;
typedef LinkedListNode<ThreadListElement> ThreadListNode;
typedef LinkedList<ThreadListElement> ThreadList;
static volatile int64 totalConstruct = 0;
static volatile int64 totalDestruct = 0;
static Mutex globalMutex;
static bool notInited = true;
PVDATA_REFCOUNT_MONITOR_DEFINE(thread);
static Mutex listGuard;
static ThreadList *threadList;
static int64 getTotalConstruct()
{
Lock xx(&globalMutex);
return totalConstruct;
}
static int64 getTotalDestruct()
{
Lock xx(&globalMutex);
return totalDestruct;
}
static void deleteStatic()
static void deleteStatic(void*)
{
delete threadList;
}
static void init()
static void init(void*)
{
Lock xx(&globalMutex);
if(notInited) {
notInited = false;
threadList = new ThreadList();
ShowConstructDestruct::registerCallback(
String("thread"),
getTotalConstruct,getTotalDestruct,0,deleteStatic);
}
threadList = new ThreadList();
epicsAtExit(&deleteStatic,0);
}
static
epicsThreadOnceId initOnce = EPICS_THREAD_ONCE_INIT;
class ThreadListElement {
public:
@@ -136,10 +121,10 @@ ThreadPvt::ThreadPvt(Thread *thread,String name,
epicsThreadGetStackSize(epicsThreadStackSmall),
myFunc,this))
{
init();
Lock xx(&globalMutex);
epicsThreadOnce(&initOnce, &init, 0);
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(thread);
Lock x(&listGuard);
threadList->addTail(threadListElement->node);
totalConstruct++;
}
ThreadPvt::~ThreadPvt()
@@ -158,11 +143,11 @@ ThreadPvt::~ThreadPvt()
message += " is not on threadlist";
throw std::logic_error(message);
}
Lock x(&listGuard);
threadList->remove(threadListElement->node);
delete waitDone;
delete threadListElement;
Lock xx(&globalMutex);
totalDestruct++;
PVDATA_REFCOUNT_MONITOR_DESTRUCT(thread);
}
Thread::Thread(String name,ThreadPriority priority,Runnable *runnable)
@@ -192,8 +177,7 @@ ThreadPriority Thread::getPriority()
void Thread::showThreads(StringBuilder buf)
{
init();
Lock xx(&globalMutex);
Lock x(&listGuard);
ThreadListNode *node = threadList->getHead();
while(node!=0) {
Thread *thread = node->getObject()->thread;