]>
git.saurik.com Git - apple/security.git/blob - OSX/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>
37 #include <unordered_map>
43 // A TypedHandle is a trivial mixin class whose only feature is that
44 // it has a *handle* whose type is of the caller's choosing. Subclasses
45 // need to assign such a handle during creation.
47 template <class _Handle
>
51 typedef _Handle Handle
;
53 static const _Handle invalidHandle
= 0;
55 _Handle
handle() const { return mMyHandle
; }
56 bool validHandle() const { return mValid
; }
59 TypedHandle(_Handle h
);
62 void setHandle(_Handle h
)
64 assert(!mValid
); // guard against redefinition
75 _Handle mMyHandle
; // our handle value
76 bool mValid
; // is the handle (still) valid?
80 // MappingHandle wraps a map indexed by handles of the chosen type.
81 // A MappingHandle makes up its own handle based on some mechanism that you
82 // know nothing about.
84 // Please be very careful about the limits of the object contract here.
85 // We promise to invent a suitable, unique handle for each MappingHandle in
86 // existence within one address space. We promise that if you hand that
87 // handle to the various MappingHandle<>::find() variants, we will give you
88 // back the MappingHandle that created it. We promise to throw if you pass
89 // a bad handle to those MappingHandle<>::find() variants. This is the
92 template <class _Handle
>
93 class MappingHandle
: public TypedHandle
<_Handle
>
99 typedef typename TypedHandle
<_Handle
>::Handle Handle
;
100 virtual ~MappingHandle()
107 template <class SubType
>
108 static SubType
&find(_Handle handle
, CSSM_RETURN error
);
110 template <class Subtype
>
111 static Subtype
&findAndLock(_Handle handle
, CSSM_RETURN error
);
113 template <class Subtype
>
114 static Subtype
&findAndKill(_Handle handle
, CSSM_RETURN error
);
116 template <class Subtype
>
117 static RefPointer
<Subtype
> findRef(_Handle handle
, CSSM_RETURN error
);
119 template <class Subtype
>
120 static RefPointer
<Subtype
> findRefAndLock(_Handle handle
, CSSM_RETURN error
);
122 template <class Subtype
>
123 static RefPointer
<Subtype
> findRefAndKill(_Handle handle
, CSSM_RETURN error
);
125 // @@@ Remove when 4003540 is fixed
126 template <class Subtype
>
127 static void findAllRefs(std::vector
<_Handle
> &refs
) {
128 state().template findAllRefs
<Subtype
>(refs
);
133 virtual bool tryLock();
135 typedef std::unordered_map
<_Handle
, MappingHandle
<_Handle
> *> HandleMap
;
139 class State
: public Mutex
, public HandleMap
143 uint32_t nextSeq() { return ++sequence
; }
145 bool handleInUse(_Handle h
);
146 MappingHandle
<_Handle
> *find(_Handle h
, CSSM_RETURN error
);
147 typename
HandleMap::iterator
locate(_Handle h
, CSSM_RETURN error
);
148 void add(_Handle h
, MappingHandle
<_Handle
> *obj
);
149 void erase(MappingHandle
<_Handle
> *obj
);
150 void erase(typename
HandleMap::iterator
&it
);
151 // @@@ Remove when 4003540 is fixed
152 template <class SubType
> void findAllRefs(std::vector
<_Handle
> &refs
);
160 // Create the handle to be used by the map
164 static ModuleNexus
<typename MappingHandle
<_Handle
>::State
> state
;
168 // MappingHandle class methods
169 // Type-specific ways to access the map in various ways
171 template <class _Handle
>
172 template <class Subclass
>
173 inline Subclass
&MappingHandle
<_Handle
>::find(_Handle handle
, CSSM_RETURN error
)
176 if (!(sub
= dynamic_cast<Subclass
*>(state().find(handle
, error
))))
177 CssmError::throwMe(error
);
181 template <class _Handle
>
182 template <class Subclass
>
183 inline Subclass
&MappingHandle
<_Handle
>::findAndLock(_Handle handle
,
187 typename
HandleMap::iterator it
= state().locate(handle
, error
);
188 StLock
<Mutex
> _(state(), true); // locate() locked it
190 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
191 CssmError::throwMe(error
); // bad type
192 if (it
->second
->tryLock()) // try to lock it
193 return *sub
; // okay, go
194 Thread::yield(); // object lock failed, backoff and retry
198 template <class _Handle
>
199 template <class Subclass
>
200 inline Subclass
&MappingHandle
<_Handle
>::findAndKill(_Handle handle
,
204 typename
HandleMap::iterator it
= state().locate(handle
, error
);
205 StLock
<Mutex
> _(state(), true); // locate() locked it
207 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
208 CssmError::throwMe(error
); // bad type
209 if (it
->second
->tryLock()) { // try to lock it
210 state().erase(it
); // kill the handle
211 return *sub
; // okay, go
213 Thread::yield(); // object lock failed, backoff and retry
217 template <class _Handle
>
218 template <class Subclass
>
219 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRef(_Handle handle
,
222 typename
HandleMap::iterator it
= state().locate(handle
, error
);
223 StLock
<Mutex
> _(state(), true); // locate() locked it
225 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
226 CssmError::throwMe(error
);
230 template <class _Handle
>
231 template <class Subclass
>
232 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRefAndLock(_Handle handle
,
236 typename
HandleMap::iterator it
= state().locate(handle
, error
);
237 StLock
<Mutex
> _(state(), true); // locate() locked it
239 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
240 CssmError::throwMe(error
); // bad type
241 if (it
->second
->tryLock()) // try to lock it
242 return sub
; // okay, go
243 Thread::yield(); // object lock failed, backoff and retry
247 template <class _Handle
>
248 template <class Subclass
>
249 inline RefPointer
<Subclass
> MappingHandle
<_Handle
>::findRefAndKill(_Handle handle
,
253 typename
HandleMap::iterator it
= state().locate(handle
, error
);
254 StLock
<Mutex
> _(state(), true); // locate() locked it
256 if (!(sub
= dynamic_cast<Subclass
*>(it
->second
)))
257 CssmError::throwMe(error
); // bad type
258 if (it
->second
->tryLock()) { // try to lock it
259 state().erase(it
); // kill the handle
260 return sub
; // okay, go
262 Thread::yield(); // object lock failed, backoff and retry
267 // @@@ Remove when 4003540 is fixed
269 // This is a hack to fix 3981388 and should NOT be used elsewhere.
270 // Also, do not follow this code's example: State methods should not
271 // implement type-specific behavior.
273 template <class _Handle
>
274 template <class Subtype
>
275 void MappingHandle
<_Handle
>::State::findAllRefs(std::vector
<_Handle
> &refs
)
277 StLock
<Mutex
> _(*this);
278 typename
HandleMap::iterator it
= (*this).begin();
279 for (; it
!= (*this).end(); ++it
)
281 Subtype
*obj
= dynamic_cast<Subtype
*>(it
->second
);
283 refs
.push_back(it
->first
);
288 } // end namespace Security
290 #endif //_H_HANDLETEMPLATES