2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // handleobject - give an object a process-global unique handle
22 #ifndef _H_HANDLEOBJECT
23 #define _H_HANDLEOBJECT
25 #include <Security/cssm.h>
26 #include <Security/utilities.h>
27 #include <Security/threading.h>
28 #include <Security/globalizer.h>
31 #include <ext/hash_map>
32 using __gnu_cxx::hash_map
;
41 // A HandledObject is a trivial mixin class whose only feature is that
42 // it has a *handle*, in the form of (currently) a CSSM_HANDLE of some kind.
43 // Subclasses need to assign such a handle during creation.
47 typedef CSSM_HANDLE Handle
;
48 static const Handle invalidHandle
= 0;
50 Handle
handle() const { return mMyHandle
; }
51 bool validHandle() const { return mValid
; }
54 HandledObject(Handle h
) : mMyHandle(h
), mValid(true) { }
55 HandledObject() { /*IFDEBUG(*/ mMyHandle
= invalidHandle
/*)*/ ; mValid
= false; }
57 void setHandle(Handle h
)
59 assert(!mValid
); // guard against redefinition
64 { assert(mValid
); mValid
= false; }
67 Handle mMyHandle
; // our handle value
68 bool mValid
; // is the handle (still) valid?
73 // Mapping CSSM_HANDLE values to object pointers and back.
74 // A HandleObject is a HandledObject (see above) that makes up its own handle
75 // based on some mechanism that you know nothing about.
77 // Please be very careful about the limits of the object contract here.
78 // We promise to invent a suitable, unique Handle for each HandleObject in
79 // existence within one address space. We promise that if you hand that handle
80 // to the various findHandle<>() variants, we will give you back the HandleObject
81 // that created it. This is the entire contract.
82 // We *will* make some efforts to diagnose invalid handles and throw exceptions on
83 // them, but the find() operation is supposed to be *fast*, so no heroic measures
86 class HandleObject
: public HandledObject
{
91 HandleObject() { state().make(this); }
92 virtual ~HandleObject();
95 template <class Subtype
>
96 static Subtype
&find(CSSM_HANDLE handle
, CSSM_RETURN error
);
98 template <class Subtype
>
99 static Subtype
&findAndLock(CSSM_HANDLE handle
, CSSM_RETURN error
);
101 template <class Subtype
>
102 static Subtype
&findAndKill(CSSM_HANDLE handle
, CSSM_RETURN error
);
106 virtual bool tryLock();
109 typedef hash_map
<CSSM_HANDLE
, HandleObject
*> HandleMap
;
110 class State
: public Mutex
{
113 void make(HandleObject
*obj
);
114 HandleObject
*find(Handle h
, CSSM_RETURN error
);
115 HandleMap::iterator
locate(Handle h
, CSSM_RETURN error
);
116 void erase(HandleObject
*obj
);
117 void erase(HandleMap::iterator
&it
);
124 static ModuleNexus
<State
> state
;
129 // Type-specific ways to access the HandleObject map in various ways
131 template <class Subclass
>
132 inline Subclass
&HandleObject::find(CSSM_HANDLE handle
, CSSM_RETURN error
)
135 if (!(sub
= dynamic_cast<Subclass
*>(state().find(handle
, error
))))
136 CssmError::throwMe(error
);
140 template <class Subclass
>
141 inline Subclass
&HandleObject::findAndLock(CSSM_HANDLE handle
,
145 HandleMap::iterator it
= state().locate(handle
, error
);
146 StLock
<Mutex
> _(state(), true); // locate() locked it
148 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
149 CssmError::throwMe(error
); // bad type
150 if (it
->second
->tryLock()) // try to lock it
151 return *sub
; // okay, go
152 Thread::yield(); // object lock failed, backoff and retry
156 template <class Subclass
>
157 inline Subclass
&HandleObject::findAndKill(CSSM_HANDLE handle
,
161 HandleMap::iterator it
= state().locate(handle
, error
);
162 StLock
<Mutex
> _(state(), true); // locate() locked it
164 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
165 CssmError::throwMe(error
); // bad type
166 if (it
->second
->tryLock()) { // try to lock it
167 state().erase(it
); // kill the handle
168 return *sub
; // okay, go
170 Thread::yield(); // object lock failed, backoff and retry
176 // Compatibility with old (global function) accessors
178 template <class Subclass
>
179 inline Subclass
&findHandle(CSSM_HANDLE handle
,
180 CSSM_RETURN error
= CSSMERR_CSSM_INVALID_ADDIN_HANDLE
)
181 { return HandleObject::find
<Subclass
>(handle
, error
); }
183 template <class Subclass
>
184 inline Subclass
&findHandleAndLock(CSSM_HANDLE handle
,
185 CSSM_RETURN error
= CSSMERR_CSSM_INVALID_ADDIN_HANDLE
)
186 { return HandleObject::findAndLock
<Subclass
>(handle
, error
); }
188 template <class Subclass
>
189 inline Subclass
&killHandle(CSSM_HANDLE handle
,
190 CSSM_RETURN error
= CSSMERR_CSSM_INVALID_ADDIN_HANDLE
)
191 { return HandleObject::findAndKill
<Subclass
>(handle
, error
); }
194 } // end namespace Security
196 #endif //_H_HANDLEOBJECT