diff --git a/src/factory/FieldCreateFactory.cpp b/src/factory/FieldCreateFactory.cpp index 82eef14..b80eed0 100644 --- a/src/factory/FieldCreateFactory.cpp +++ b/src/factory/FieldCreateFactory.cpp @@ -19,6 +19,7 @@ #include #include +#include #define epicsExportSharedSymbols #include @@ -1452,18 +1453,33 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl } } -// TODO replace with non-locking singleton pattern -const FieldCreatePtr& FieldCreate::getFieldCreate() -{ - static FieldCreatePtr fieldCreate; - static Mutex mutex; - - Lock xx(mutex); - if(fieldCreate.get()==0) { - fieldCreate = FieldCreatePtr(new FieldCreate()); +namespace detail { +struct field_factory { + FieldCreatePtr fieldCreate; + field_factory() :fieldCreate(new FieldCreate()) { registerRefCounter("Field", &Field::num_instances); } - return fieldCreate; +}; +} + +static detail::field_factory* field_factory_s; +static epicsThreadOnceId field_factory_once = EPICS_THREAD_ONCE_INIT; + +static void field_factory_init(void*) +{ + try { + field_factory_s = new detail::field_factory; + }catch(std::exception& e){ + std::cerr<<"Error initializing getFieldCreate() : "<fieldCreate) + throw std::logic_error("getFieldCreate() not initialized"); + return field_factory_s->fieldCreate; } FieldCreate::FieldCreate() diff --git a/src/factory/PVDataCreateFactory.cpp b/src/factory/PVDataCreateFactory.cpp index bd9acd4..aaec7ee 100644 --- a/src/factory/PVDataCreateFactory.cpp +++ b/src/factory/PVDataCreateFactory.cpp @@ -17,6 +17,7 @@ #include #include +#include #define epicsExportSharedSymbols #include @@ -604,19 +605,33 @@ PVUnionPtr PVDataCreate::createPVUnion(PVUnionPtr const & unionToClone) return punion; } -// TODO not thread-safe (local static initializers) -// TODO replace with non-locking singleton pattern +namespace detail { +struct pvfield_factory { + PVDataCreatePtr pvDataCreate; + pvfield_factory() :pvDataCreate(new PVDataCreate()) { + registerRefCounter("PVField", &PVField::num_instances); + } +}; +} + +static detail::pvfield_factory* pvfield_factory_s; +static epicsThreadOnceId pvfield_factory_once = EPICS_THREAD_ONCE_INIT; + +static void pvfield_factory_init(void*) +{ + try { + pvfield_factory_s = new detail::pvfield_factory; + }catch(std::exception& e){ + std::cerr<<"Error initializing getFieldCreate() : "<pvDataCreate) + throw std::logic_error("getPVDataCreate() not initialized"); + return pvfield_factory_s->pvDataCreate; } // explicitly instanciate to ensure that windows diff --git a/src/pv/pvData.h b/src/pv/pvData.h index 38f6909..ff2582e 100644 --- a/src/pv/pvData.h +++ b/src/pv/pvData.h @@ -1475,11 +1475,16 @@ typedef std::tr1::shared_ptr PVDoubleArrayPtr; typedef PVValueArray PVStringArray; typedef std::tr1::shared_ptr PVStringArrayPtr; +namespace detail { +struct pvfield_factory; +} + /** * @brief This is a singleton class for creating data instances. * */ class epicsShareClass PVDataCreate { + friend struct detail::pvfield_factory; public: /** * get the singleton diff --git a/src/pv/pvIntrospect.h b/src/pv/pvIntrospect.h index 36f92fd..50ab8f5 100644 --- a/src/pv/pvIntrospect.h +++ b/src/pv/pvIntrospect.h @@ -1065,11 +1065,16 @@ private: const bool createNested; // true - endNested() creates in parent, false - endNested() appends to parent }; +namespace detail { +struct field_factory; +} + /** * @brief This is a singleton class for creating introspection interfaces. * */ class epicsShareClass FieldCreate { + friend struct detail::field_factory; public: static const FieldCreatePtr &getFieldCreate(); /**