#ifndef _H_GLOBALIZER
#define _H_GLOBALIZER
#include <Security/threading.h>
#include <memory>
namespace Security {
class GlobalNexus {
public:
class Error : public std::exception {
public:
virtual ~Error() throw();
const char * const message;
Error(const char *m) : message(m) { }
const char *what() const throw() { return message; }
};
};
#if defined(_HAVE_ATOMIC_OPERATIONS)
class ModuleNexusCommon : public GlobalNexus {
protected:
AtomicWord create(void *(*make)());
protected:
AtomicWord pointer;
StaticAtomicCounter<uint32> sync;
};
template <class Type>
class ModuleNexus : public ModuleNexusCommon {
public:
Type &operator () ()
{
AtomicWord p = pointer; return *reinterpret_cast<Type *>((p && !(p & 0x1)) ? p : create(make));
}
void reset()
{
if (pointer && !(pointer & 0x1)) {
delete reinterpret_cast<Type *>(pointer);
pointer = 0;
}
}
private:
static void *make() { return new Type; }
};
template <class Type>
class CleanModuleNexus : public ModuleNexus<Type> {
public:
~CleanModuleNexus()
{
debug("nexus", "ModuleNexus %p destroyed object 0x%x", this, pointer);
delete reinterpret_cast<Type *>(pointer);
}
};
#else // !_HAVE_ATOMIC_OPERATIONS
template <class Type>
class ModuleNexus : public GlobalNexus {
public:
Type &operator () ()
{
#if !defined(PTHREAD_STRICT)
if (mSingleton)
return *mSingleton;
#endif
StLock<Mutex> _(mLock);
if (mSingleton == NULL)
mSingleton = new Type;
return *mSingleton;
}
void reset() { delete mSingleton; mSingleton = NULL; }
protected:
Type *mSingleton; Mutex mLock; };
template <class Type>
class CleanModuleNexus : public ModuleNexus<Type> {
public:
~CleanModuleNexus()
{
debug("nexus", "ModuleNexus %p destroyed object 0x%x", this, mSingleton);
delete mSingleton;
}
};
#endif // _HAVE_ATOMIC_OPERATIONS
#if _USE_THREADS == _USE_PTHREADS
template <class Type>
class ThreadNexus : public GlobalNexus {
public:
ThreadNexus() : mSlot(true) { }
Type &operator () ()
{
if (Type *p = mSlot)
return *p;
mSlot = new Type;
return *mSlot;
}
private:
PerThreadPointer<Type> mSlot;
};
#endif //_USE_PTHREADS
class ProcessNexusBase : public GlobalNexus {
protected:
ProcessNexusBase(const char *identifier);
struct Store {
void *mObject;
Mutex mLock;
};
Store *mStore;
};
template <class Type>
class ProcessNexus : public ProcessNexusBase {
public:
ProcessNexus(const char *identifier) : ProcessNexusBase(identifier) { }
Type &operator () ();
private:
Type *mObject;
};
template <class Type>
Type &ProcessNexus<Type>::operator () ()
{
#if !defined(PTHREAD_STRICT)
if (mStore->mObject)
return *reinterpret_cast<Type *>(mStore->mObject);
#endif
StLock<Mutex> _(mStore->mLock);
if (mStore->mObject == NULL)
mStore->mObject = new Type;
return *reinterpret_cast<Type *>(mStore->mObject);
};
}
#endif //_H_GLOBALIZER