]> git.saurik.com Git - apple/security.git/blame - OSX/include/security_cdsa_utilities/handletemplates.h
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / include / security_cdsa_utilities / handletemplates.h
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2008,2011-2012 Apple Inc. All Rights Reserved.
b1ab9ed8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// Templates to support HandleObject-like objects
27//
28#ifndef _H_HANDLETEMPLATES
29#define _H_HANDLETEMPLATES
30
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>
427c49bc 35#include <vector>
b1ab9ed8 36
5c19dc3a 37#include <unordered_map>
b1ab9ed8
A
38
39namespace Security
40{
41
42//
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.
46//
47template <class _Handle>
48struct TypedHandle
49{
50public:
51 typedef _Handle Handle;
52
53 static const _Handle invalidHandle = 0;
54
55 _Handle handle() const { return mMyHandle; }
56 bool validHandle() const { return mValid; }
57
58protected:
59 TypedHandle(_Handle h);
60 TypedHandle();
61
62 void setHandle(_Handle h)
63 {
64 assert(!mValid); // guard against redefinition
65 mMyHandle = h;
66 mValid = true;
67 }
68 void clearHandle()
69 {
70 assert(mValid);
71 mValid = false;
72 }
73
74private:
75 _Handle mMyHandle; // our handle value
76 bool mValid; // is the handle (still) valid?
77};
78
79//
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.
83//
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
90// entire contract.
91//
92template <class _Handle>
93class MappingHandle : public TypedHandle<_Handle>
94{
95protected:
96 class State;
97
98public:
99 typedef typename TypedHandle<_Handle>::Handle Handle;
100 virtual ~MappingHandle()
101 {
102 State &st = state();
103 StLock<Mutex> _(st);
104 st.erase(this);
105 }
106
107 template <class SubType>
108 static SubType &find(_Handle handle, CSSM_RETURN error);
109
110 template <class Subtype>
111 static Subtype &findAndLock(_Handle handle, CSSM_RETURN error);
112
113 template <class Subtype>
114 static Subtype &findAndKill(_Handle handle, CSSM_RETURN error);
115
116 template <class Subtype>
117 static RefPointer<Subtype> findRef(_Handle handle, CSSM_RETURN error);
118
119 template <class Subtype>
120 static RefPointer<Subtype> findRefAndLock(_Handle handle, CSSM_RETURN error);
121
122 template <class Subtype>
123 static RefPointer<Subtype> findRefAndKill(_Handle handle, CSSM_RETURN error);
124
125 // @@@ Remove when 4003540 is fixed
126 template <class Subtype>
127 static void findAllRefs(std::vector<_Handle> &refs) {
427c49bc 128 state().template findAllRefs<Subtype>(refs);
b1ab9ed8
A
129 }
130
131protected:
132 virtual void lock();
133 virtual bool tryLock();
134
5c19dc3a 135 typedef std::unordered_map<_Handle, MappingHandle<_Handle> *> HandleMap;
b1ab9ed8
A
136
137 MappingHandle();
138
139 class State : public Mutex, public HandleMap
140 {
141 public:
142 State();
143 uint32_t nextSeq() { return ++sequence; }
144
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);
153
154 private:
155 uint32_t sequence;
156 };
157
158private:
159 //
160 // Create the handle to be used by the map
161 //
162 void make();
163
164 static ModuleNexus<typename MappingHandle<_Handle>::State> state;
165};
166
167//
168// MappingHandle class methods
169// Type-specific ways to access the map in various ways
170//
171template <class _Handle>
172template <class Subclass>
173inline Subclass &MappingHandle<_Handle>::find(_Handle handle, CSSM_RETURN error)
174{
175 Subclass *sub;
176 if (!(sub = dynamic_cast<Subclass *>(state().find(handle, error))))
177 CssmError::throwMe(error);
178 return *sub;
179}
180
181template <class _Handle>
182template <class Subclass>
183inline Subclass &MappingHandle<_Handle>::findAndLock(_Handle handle,
184 CSSM_RETURN error)
185{
186 for (;;) {
187 typename HandleMap::iterator it = state().locate(handle, error);
188 StLock<Mutex> _(state(), true); // locate() locked it
189 Subclass *sub;
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
195 }
196}
197
198template <class _Handle>
199template <class Subclass>
200inline Subclass &MappingHandle<_Handle>::findAndKill(_Handle handle,
201 CSSM_RETURN error)
202{
203 for (;;) {
204 typename HandleMap::iterator it = state().locate(handle, error);
205 StLock<Mutex> _(state(), true); // locate() locked it
206 Subclass *sub;
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
212 }
213 Thread::yield(); // object lock failed, backoff and retry
214 }
215}
216
217template <class _Handle>
218template <class Subclass>
219inline RefPointer<Subclass> MappingHandle<_Handle>::findRef(_Handle handle,
220 CSSM_RETURN error)
221{
222 typename HandleMap::iterator it = state().locate(handle, error);
223 StLock<Mutex> _(state(), true); // locate() locked it
224 Subclass *sub;
225 if (!(sub = dynamic_cast<Subclass *>(it->second)))
226 CssmError::throwMe(error);
227 return sub;
228}
229
230template <class _Handle>
231template <class Subclass>
232inline RefPointer<Subclass> MappingHandle<_Handle>::findRefAndLock(_Handle handle,
233 CSSM_RETURN error)
234{
235 for (;;) {
236 typename HandleMap::iterator it = state().locate(handle, error);
237 StLock<Mutex> _(state(), true); // locate() locked it
238 Subclass *sub;
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
244 }
245}
246
247template <class _Handle>
248template <class Subclass>
249inline RefPointer<Subclass> MappingHandle<_Handle>::findRefAndKill(_Handle handle,
250 CSSM_RETURN error)
251{
252 for (;;) {
253 typename HandleMap::iterator it = state().locate(handle, error);
254 StLock<Mutex> _(state(), true); // locate() locked it
255 Subclass *sub;
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
261 }
262 Thread::yield(); // object lock failed, backoff and retry
263 }
264}
265
266//
267// @@@ Remove when 4003540 is fixed
268//
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.
272//
273template <class _Handle>
274template <class Subtype>
275void MappingHandle<_Handle>::State::findAllRefs(std::vector<_Handle> &refs)
276{
277 StLock<Mutex> _(*this);
278 typename HandleMap::iterator it = (*this).begin();
279 for (; it != (*this).end(); ++it)
280 {
281 Subtype *obj = dynamic_cast<Subtype *>(it->second);
282 if (obj)
283 refs.push_back(it->first);
284 }
285}
286
287
288} // end namespace Security
289
290#endif //_H_HANDLETEMPLATES