]>
git.saurik.com Git - apple/security.git/blob - libsecurity_cdsa_utilities/lib/handletemplates.h
2 * Copyright (c) 2008 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // Templates to support HandleObject-like objects
28 #ifndef _H_HANDLETEMPLATES
29 #define _H_HANDLETEMPLATES
31 #include <security_utilities/refcount.h>
32 #include <security_utilities/threading.h>
33 #include <security_utilities/globalizer.h>
34 #include <security_cdsa_utilities/cssmerrors.h>
37 #include <ext/hash_map>
38 using __gnu_cxx::hash_map
;
47 // A TypedHandle is a trivial mixin class whose only feature is that
48 // it has a *handle* whose type is of the caller's choosing. Subclasses
49 // need to assign such a handle during creation.
51 template <class _Handle
>
55 typedef _Handle Handle
;
57 static const _Handle invalidHandle
= 0;
59 _Handle
handle() const { return mMyHandle
; }
60 bool validHandle() const { return mValid
; }
63 TypedHandle(_Handle h
);
66 void setHandle(_Handle h
)
68 assert(!mValid
); // guard against redefinition
79 _Handle mMyHandle
; // our handle value
80 bool mValid
; // is the handle (still) valid?
84 // MappingHandle wraps a map indexed by handles of the chosen type.
85 // A MappingHandle makes up its own handle based on some mechanism that you
86 // know nothing about.
88 // Please be very careful about the limits of the object contract here.
89 // We promise to invent a suitable, unique handle for each MappingHandle in
90 // existence within one address space. We promise that if you hand that
91 // handle to the various MappingHandle<>::find() variants, we will give you
92 // back the MappingHandle that created it. We promise to throw if you pass
93 // a bad handle to those MappingHandle<>::find() variants. This is the
96 template <class _Handle
>
97 class MappingHandle
: public TypedHandle
<_Handle
>
103 typedef typename TypedHandle
<_Handle
>::Handle Handle
;
104 virtual ~MappingHandle()
111 template <class SubType
>
112 static SubType
&find(_Handle handle
, CSSM_RETURN error
);
114 template <class Subtype
>
115 static Subtype
&findAndLock(_Handle handle
, CSSM_RETURN error
);
117 template <class Subtype
>
118 static Subtype
&findAndKill(_Handle handle
, CSSM_RETURN error
);
120 template <class Subtype
>
121 static RefPointer
<Subtype
> findRef(_Handle handle
, CSSM_RETURN error
);
123 template <class Subtype
>
124 static RefPointer
<Subtype
> findRefAndLock(_Handle handle
, CSSM_RETURN error
);
126 template <class Subtype
>
127 static RefPointer
<Subtype
> findRefAndKill(_Handle handle
, CSSM_RETURN error
);
129 // @@@ Remove when 4003540 is fixed
130 template <class Subtype
>
131 static void findAllRefs(std::vector
<_Handle
> &refs
) {
132 state().findAllRefs
<Subtype
>(refs
);
137 virtual bool tryLock();
139 typedef hash_map
<_Handle
, MappingHandle
<_Handle
> *> HandleMap
;
143 class State
: public Mutex
, public HandleMap
147 uint32_t nextSeq() { return ++sequence
; }
149 bool handleInUse(_Handle h
);
150 MappingHandle
<_Handle
> *find(_Handle h
, CSSM_RETURN error
);
151 typename
HandleMap::iterator
locate(_Handle h
, CSSM_RETURN error
);
152 void add(_Handle h
, MappingHandle
<_Handle
> *obj
);
153 void erase(MappingHandle
<_Handle
> *obj
);
154 void erase(typename
HandleMap::iterator
&it
);
155 // @@@ Remove when 4003540 is fixed
156 template <class SubType
> void findAllRefs(std::vector
<_Handle
> &refs
);
164 // Create the handle to be used by the map
168 static ModuleNexus
<typename MappingHandle
<_Handle
>::State
> state
;
172 // MappingHandle class methods
173 // Type-specific ways to access the map in various ways
175 template <class _Handle
>
176 template <class Subclass
>
177 inline Subclass
&MappingHandle
<_Handle
>::find(_Handle handle
, CSSM_RETURN error
)
180 if (!(sub
= dynamic_cast<Subclass
*>(state().find(handle
, error
))))
181 CssmError::throwMe(error
);
185 template <class _Handle
>
186 template <class Subclass
>
187 inline Subclass
&MappingHandle
<_Handle
>::findAndLock(_Handle handle
,
191 typename
HandleMap::iterator it
= state().locate(handle
, error
);
192 StLock
<Mutex
> _(state(), true); // locate() locked it
194 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
195 CssmError::throwMe(error
); // bad type
196 if (it
->second
->tryLock()) // try to lock it
197 return *sub
; // okay, go
198 Thread::yield(); // object lock failed, backoff and retry
202 template <class _Handle
>
203 template <class Subclass
>
204 inline Subclass
&MappingHandle
<_Handle
>::findAndKill(_Handle handle
,
208 typename
HandleMap::iterator it
= state().locate(handle
, error
);
209 StLock
<Mutex
> _(state(), true); // locate() locked it
211 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
212 CssmError::throwMe(error
); // bad type
213 if (it
->second
->tryLock()) { // try to lock it
214 state().erase(it
); // kill the handle
215 return *sub
; // okay, go
217 Thread::yield(); // object lock failed, backoff and retry
221 template <class _Handle
>
222 template <class Subclass
>
223 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRef(_Handle handle
,
226 typename
HandleMap::iterator it
= state().locate(handle
, error
);
227 StLock
<Mutex
> _(state(), true); // locate() locked it
229 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
230 CssmError::throwMe(error
);
234 template <class _Handle
>
235 template <class Subclass
>
236 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRefAndLock(_Handle handle
,
240 typename
HandleMap::iterator it
= state().locate(handle
, error
);
241 StLock
<Mutex
> _(state(), true); // locate() locked it
243 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
244 CssmError::throwMe(error
); // bad type
245 if (it
->second
->tryLock()) // try to lock it
246 return sub
; // okay, go
247 Thread::yield(); // object lock failed, backoff and retry
251 template <class _Handle
>
252 template <class Subclass
>
253 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRefAndKill(_Handle handle
,
257 typename
HandleMap::iterator it
= state().locate(handle
, error
);
258 StLock
<Mutex
> _(state(), true); // locate() locked it
260 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
261 CssmError::throwMe(error
); // bad type
262 if (it
->second
->tryLock()) { // try to lock it
263 state().erase(it
); // kill the handle
264 return sub
; // okay, go
266 Thread::yield(); // object lock failed, backoff and retry
271 // @@@ Remove when 4003540 is fixed
273 // This is a hack to fix 3981388 and should NOT be used elsewhere.
274 // Also, do not follow this code's example: State methods should not
275 // implement type-specific behavior.
277 template <class _Handle
>
278 template <class Subtype
>
279 void MappingHandle
<_Handle
>::State::findAllRefs(std::vector
<_Handle
> &refs
)
281 StLock
<Mutex
> _(*this);
282 typename
HandleMap::iterator it
= (*this).begin();
283 for (; it
!= (*this).end(); ++it
)
285 Subtype
*obj
= dynamic_cast<Subtype
*>(it
->second
);
287 refs
.push_back(it
->first
);
292 } // end namespace Security
294 #endif //_H_HANDLETEMPLATES