#ifndef _H_HANDLEOBJECT
#define _H_HANDLEOBJECT
#include <Security/cssm.h>
#include <Security/utilities.h>
#include <Security/threading.h>
#include <Security/globalizer.h>
#include <hash_map>
namespace Security
{
class HandledObject {
public:
typedef CSSM_HANDLE Handle;
static const Handle invalidHandle = 0;
Handle handle() const { return mMyHandle; }
bool validHandle() const { return mValid; }
protected:
HandledObject(Handle h) : mMyHandle(h), mValid(true) { }
HandledObject() { mMyHandle = invalidHandle ; mValid = false; }
void setHandle(Handle h)
{
assert(!mValid); mMyHandle = h;
mValid = true;
}
void clearHandle()
{ assert(mValid); mValid = false; }
private:
Handle mMyHandle; bool mValid; };
class HandleObject : public HandledObject {
NOCOPY(HandleObject)
class State; friend class State;
template <class Subtype> friend Subtype &findHandle(CSSM_HANDLE, CSSM_RETURN);
template <class Subtype> friend Subtype &findHandleAndLock(CSSM_HANDLE, CSSM_RETURN);
template <class Subtype> friend Subtype &killHandle(CSSM_HANDLE, CSSM_RETURN);
public:
HandleObject() { state().make(this); }
virtual ~HandleObject() { state().erase(this); }
protected:
virtual void lock();
virtual bool tryLock();
private:
enum LocateMode { lockTarget, findTarget, removeTarget };
private:
typedef hash_map<CSSM_HANDLE, HandleObject *> HandleMap;
class State {
public:
State();
void make(HandleObject *obj);
HandleObject *locate(Handle h, LocateMode mode, CSSM_RETURN error);
void erase(HandleObject *obj);
private:
HandleMap handleMap;
uint32 sequence;
Mutex mLock;
};
static ModuleNexus<State> state;
};
template <class Subclass>
Subclass &findHandle(CSSM_HANDLE handle,
CSSM_RETURN error = CSSMERR_CSSM_INVALID_ADDIN_HANDLE)
{
Subclass *sub;
if (!(sub = dynamic_cast<Subclass *>(HandleObject::state().locate(handle, HandleObject::findTarget, error))))
CssmError::throwMe(error);
return *sub;
}
template <class Subclass>
Subclass &findHandleAndLock(CSSM_HANDLE handle,
CSSM_RETURN error = CSSMERR_CSSM_INVALID_ADDIN_HANDLE)
{
Subclass *sub;
if (!(sub = dynamic_cast<Subclass *>(HandleObject::state().locate(handle, HandleObject::lockTarget, error))))
CssmError::throwMe(error);
return *sub;
}
template <class Subclass>
Subclass &killHandle(CSSM_HANDLE handle,
CSSM_RETURN error = CSSMERR_CSSM_INVALID_ADDIN_HANDLE)
{
Subclass *sub;
if (!(sub = dynamic_cast<Subclass *>(HandleObject::state().locate(handle, HandleObject::removeTarget, error))))
CssmError::throwMe(error);
return *sub;
}
}
#endif //_H_HANDLEOBJECT