]>
git.saurik.com Git - apple/security.git/blob - Security/libsecurity_cdsa_utilities/lib/handletemplates.h
2 * Copyright (c) 2008,2011-2012 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>
38 #include <ext/hash_map>
39 using __gnu_cxx::hash_map
;
48 // A TypedHandle is a trivial mixin class whose only feature is that
49 // it has a *handle* whose type is of the caller's choosing. Subclasses
50 // need to assign such a handle during creation.
52 template <class _Handle
>
56 typedef _Handle Handle
;
58 static const _Handle invalidHandle
= 0;
60 _Handle
handle() const { return mMyHandle
; }
61 bool validHandle() const { return mValid
; }
64 TypedHandle(_Handle h
);
67 void setHandle(_Handle h
)
69 assert(!mValid
); // guard against redefinition
80 _Handle mMyHandle
; // our handle value
81 bool mValid
; // is the handle (still) valid?
85 // MappingHandle wraps a map indexed by handles of the chosen type.
86 // A MappingHandle makes up its own handle based on some mechanism that you
87 // know nothing about.
89 // Please be very careful about the limits of the object contract here.
90 // We promise to invent a suitable, unique handle for each MappingHandle in
91 // existence within one address space. We promise that if you hand that
92 // handle to the various MappingHandle<>::find() variants, we will give you
93 // back the MappingHandle that created it. We promise to throw if you pass
94 // a bad handle to those MappingHandle<>::find() variants. This is the
97 template <class _Handle
>
98 class MappingHandle
: public TypedHandle
<_Handle
>
104 typedef typename TypedHandle
<_Handle
>::Handle Handle
;
105 virtual ~MappingHandle()
112 template <class SubType
>
113 static SubType
&find(_Handle handle
, CSSM_RETURN error
);
115 template <class Subtype
>
116 static Subtype
&findAndLock(_Handle handle
, CSSM_RETURN error
);
118 template <class Subtype
>
119 static Subtype
&findAndKill(_Handle handle
, CSSM_RETURN error
);
121 template <class Subtype
>
122 static RefPointer
<Subtype
> findRef(_Handle handle
, CSSM_RETURN error
);
124 template <class Subtype
>
125 static RefPointer
<Subtype
> findRefAndLock(_Handle handle
, CSSM_RETURN error
);
127 template <class Subtype
>
128 static RefPointer
<Subtype
> findRefAndKill(_Handle handle
, CSSM_RETURN error
);
130 // @@@ Remove when 4003540 is fixed
131 template <class Subtype
>
132 static void findAllRefs(std::vector
<_Handle
> &refs
) {
133 state().template findAllRefs
<Subtype
>(refs
);
138 virtual bool tryLock();
140 typedef hash_map
<_Handle
, MappingHandle
<_Handle
> *> HandleMap
;
144 class State
: public Mutex
, public HandleMap
148 uint32_t nextSeq() { return ++sequence
; }
150 bool handleInUse(_Handle h
);
151 MappingHandle
<_Handle
> *find(_Handle h
, CSSM_RETURN error
);
152 typename
HandleMap::iterator
locate(_Handle h
, CSSM_RETURN error
);
153 void add(_Handle h
, MappingHandle
<_Handle
> *obj
);
154 void erase(MappingHandle
<_Handle
> *obj
);
155 void erase(typename
HandleMap::iterator
&it
);
156 // @@@ Remove when 4003540 is fixed
157 template <class SubType
> void findAllRefs(std::vector
<_Handle
> &refs
);
165 // Create the handle to be used by the map
169 static ModuleNexus
<typename MappingHandle
<_Handle
>::State
> state
;
173 // MappingHandle class methods
174 // Type-specific ways to access the map in various ways
176 template <class _Handle
>
177 template <class Subclass
>
178 inline Subclass
&MappingHandle
<_Handle
>::find(_Handle handle
, CSSM_RETURN error
)
181 if (!(sub
= dynamic_cast<Subclass
*>(state().find(handle
, error
))))
182 CssmError::throwMe(error
);
186 template <class _Handle
>
187 template <class Subclass
>
188 inline Subclass
&MappingHandle
<_Handle
>::findAndLock(_Handle handle
,
192 typename
HandleMap::iterator it
= state().locate(handle
, error
);
193 StLock
<Mutex
> _(state(), true); // locate() locked it
195 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
196 CssmError::throwMe(error
); // bad type
197 if (it
->second
->tryLock()) // try to lock it
198 return *sub
; // okay, go
199 Thread::yield(); // object lock failed, backoff and retry
203 template <class _Handle
>
204 template <class Subclass
>
205 inline Subclass
&MappingHandle
<_Handle
>::findAndKill(_Handle handle
,
209 typename
HandleMap::iterator it
= state().locate(handle
, error
);
210 StLock
<Mutex
> _(state(), true); // locate() locked it
212 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
213 CssmError::throwMe(error
); // bad type
214 if (it
->second
->tryLock()) { // try to lock it
215 state().erase(it
); // kill the handle
216 return *sub
; // okay, go
218 Thread::yield(); // object lock failed, backoff and retry
222 template <class _Handle
>
223 template <class Subclass
>
224 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRef(_Handle handle
,
227 typename
HandleMap::iterator it
= state().locate(handle
, error
);
228 StLock
<Mutex
> _(state(), true); // locate() locked it
230 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
231 CssmError::throwMe(error
);
235 template <class _Handle
>
236 template <class Subclass
>
237 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRefAndLock(_Handle handle
,
241 typename
HandleMap::iterator it
= state().locate(handle
, error
);
242 StLock
<Mutex
> _(state(), true); // locate() locked it
244 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
245 CssmError::throwMe(error
); // bad type
246 if (it
->second
->tryLock()) // try to lock it
247 return sub
; // okay, go
248 Thread::yield(); // object lock failed, backoff and retry
252 template <class _Handle
>
253 template <class Subclass
>
254 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRefAndKill(_Handle handle
,
258 typename
HandleMap::iterator it
= state().locate(handle
, error
);
259 StLock
<Mutex
> _(state(), true); // locate() locked it
261 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
262 CssmError::throwMe(error
); // bad type
263 if (it
->second
->tryLock()) { // try to lock it
264 state().erase(it
); // kill the handle
265 return sub
; // okay, go
267 Thread::yield(); // object lock failed, backoff and retry
272 // @@@ Remove when 4003540 is fixed
274 // This is a hack to fix 3981388 and should NOT be used elsewhere.
275 // Also, do not follow this code's example: State methods should not
276 // implement type-specific behavior.
278 template <class _Handle
>
279 template <class Subtype
>
280 void MappingHandle
<_Handle
>::State::findAllRefs(std::vector
<_Handle
> &refs
)
282 StLock
<Mutex
> _(*this);
283 typename
HandleMap::iterator it
= (*this).begin();
284 for (; it
!= (*this).end(); ++it
)
286 Subtype
*obj
= dynamic_cast<Subtype
*>(it
->second
);
288 refs
.push_back(it
->first
);
293 } // end namespace Security
295 #endif //_H_HANDLETEMPLATES