]>
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 ()
102 // <rdar://problem/28898053> security_filedb build error: instantiation of variable 'Security::MappingHandle<long>::state' required here, but no definition is available
103 #pragma clang diagnostic push
104 #pragma clang diagnostic ignored "-Wundefined-var-template"
106 #pragma clang diagnostic pop
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 (). template findAllRefs
< Subtype
>( refs
);
137 virtual bool tryLock ();
139 typedef std :: unordered_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 // <rdar://problem/28898053> security_filedb build error: instantiation of variable 'Security::MappingHandle<long>::state' required here, but no definition is available
181 #pragma clang diagnostic push
182 #pragma clang diagnostic ignored "-Wundefined-var-template"
183 if (!( sub
= dynamic_cast < Subclass
*>( state (). find ( handle
, error
))))
184 CssmError :: throwMe ( error
);
185 #pragma clang diagnostic pop
189 template < class _Handle
>
190 template < class Subclass
>
191 inline Subclass
& MappingHandle
< _Handle
>:: findAndLock ( _Handle handle
,
195 typename
HandleMap :: iterator it
= state (). locate ( handle
, error
);
196 StLock
< Mutex
> _ ( state (), true ); // locate() locked it
198 if (!( sub
= dynamic_cast < Subclass
*>( it
-> second
)))
199 CssmError :: throwMe ( error
); // bad type
200 if ( it
-> second
-> tryLock ()) // try to lock it
201 return * sub
; // okay, go
202 Thread :: yield (); // object lock failed, backoff and retry
206 template < class _Handle
>
207 template < class Subclass
>
208 inline Subclass
& MappingHandle
< _Handle
>:: findAndKill ( _Handle handle
,
212 // <rdar://problem/28898053> security_filedb build error: instantiation of variable 'Security::MappingHandle<long>::state' required here, but no definition is available
213 #pragma clang diagnostic push
214 #pragma clang diagnostic ignored "-Wundefined-var-template"
215 typename
HandleMap :: iterator it
= state (). locate ( handle
, error
);
216 #pragma clang diagnostic pop
217 StLock
< Mutex
> _ ( state (), true ); // locate() locked it
219 if (!( sub
= dynamic_cast < Subclass
*>( it
-> second
)))
220 CssmError :: throwMe ( error
); // bad type
221 if ( it
-> second
-> tryLock ()) { // try to lock it
222 state (). erase ( it
); // kill the handle
223 return * sub
; // okay, go
225 Thread :: yield (); // object lock failed, backoff and retry
229 template < class _Handle
>
230 template < class Subclass
>
231 inline RefPointer
< Subclass
> MappingHandle
< _Handle
>:: findRef ( _Handle handle
,
234 typename
HandleMap :: iterator it
= state (). locate ( handle
, error
);
235 StLock
< Mutex
> _ ( state (), true ); // locate() locked it
237 if (!( sub
= dynamic_cast < Subclass
*>( it
-> second
)))
238 CssmError :: throwMe ( error
);
242 template < class _Handle
>
243 template < class Subclass
>
244 inline RefPointer
< Subclass
> MappingHandle
< _Handle
>:: findRefAndLock ( _Handle handle
,
248 typename
HandleMap :: iterator it
= state (). locate ( handle
, error
);
249 StLock
< Mutex
> _ ( state (), true ); // locate() locked it
251 if (!( sub
= dynamic_cast < Subclass
*>( it
-> second
)))
252 CssmError :: throwMe ( error
); // bad type
253 if ( it
-> second
-> tryLock ()) // try to lock it
254 return sub
; // okay, go
255 Thread :: yield (); // object lock failed, backoff and retry
259 template < class _Handle
>
260 template < class Subclass
>
261 inline RefPointer
< Subclass
> MappingHandle
< _Handle
>:: findRefAndKill ( _Handle handle
,
265 typename
HandleMap :: iterator it
= state (). locate ( handle
, error
);
266 StLock
< Mutex
> _ ( state (), true ); // locate() locked it
268 if (!( sub
= dynamic_cast < Subclass
*>( it
-> second
)))
269 CssmError :: throwMe ( error
); // bad type
270 if ( it
-> second
-> tryLock ()) { // try to lock it
271 state (). erase ( it
); // kill the handle
272 return sub
; // okay, go
274 Thread :: yield (); // object lock failed, backoff and retry
279 // @@@ Remove when 4003540 is fixed
281 // This is a hack to fix 3981388 and should NOT be used elsewhere.
282 // Also, do not follow this code's example: State methods should not
283 // implement type-specific behavior.
285 template < class _Handle
>
286 template < class Subtype
>
287 void MappingHandle
< _Handle
>:: State :: findAllRefs ( std :: vector
< _Handle
> & refs
)
289 StLock
< Mutex
> _ (* this );
290 typename
HandleMap :: iterator it
= (* this ). begin ();
291 for (; it
!= (* this ). end (); ++ it
)
293 Subtype
* obj
= dynamic_cast < Subtype
*>( it
-> second
);
295 refs
. push_back ( it
-> first
);
300 } // end namespace Security
302 #endif //_H_HANDLETEMPLATES