#ifndef _H_GLOBALIZER
#define _H_GLOBALIZER
#include <security_utilities/threading.h>
#include <memory>
#include <set>
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; }
};
};
class ModuleNexusCommon : public GlobalNexus {
protected:
void *create(void *(*make)());
protected:
void *pointer;
StaticAtomicCounter<uint32_t> sync;
};
template <class Type>
class ModuleNexus : public ModuleNexusCommon {
public:
Type &operator () ()
{
void *p = Atomic<void *>::load(pointer); if (!p || (uintptr_t(p) & 0x1)) {
p = create(make);
secdebug("nexus", "module %s 0x%p", Debug::typeName<Type>().c_str(), pointer);
}
return *reinterpret_cast<Type *>(p);
}
bool exists() const
{
return Atomic<void *>::load(pointer) != NULL;
}
void reset()
{
if (pointer && !(uintptr_t(pointer) & 0x1)) {
delete reinterpret_cast<Type *>(pointer);
Atomic<void *>::store(0, pointer);
}
}
private:
static void *make() { return new Type; }
};
template <class Type>
class CleanModuleNexus : public ModuleNexus<Type> {
public:
~CleanModuleNexus()
{
secdebug("nexus", "ModuleNexus %p destroyed object 0x%x",
this, ModuleNexus<Type>::pointer);
delete reinterpret_cast<Type *>(ModuleNexus<Type>::pointer);
}
};
typedef std::set<void*> RetentionSet;
class ThreadNexusBase {
protected:
static ModuleNexus<Mutex> mInstanceLock;
static ModuleNexus<RetentionSet> mInstances;
};
template <class Type>
class ThreadNexus : public GlobalNexus, private ThreadNexusBase {
public:
ThreadNexus() : mSlot(true) { }
Type &operator () ()
{
if (Type *p = mSlot)
return *p;
mSlot = new Type;
{
StLock<Mutex> _(mInstanceLock ());
mInstances ().insert(mSlot);
}
return *mSlot;
}
private:
PerThreadPointer<Type> mSlot;
};
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