]> git.saurik.com Git - apple/security.git/blob - libsecurity_cdsa_utilities/lib/handletemplates_defs.h
Security-55179.11.tar.gz
[apple/security.git] / libsecurity_cdsa_utilities / lib / handletemplates_defs.h
1 /*
2 * Copyright (c) 2008 Apple Inc. All Rights Reserved.
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 // adjunct to handletemplates.h
27 //
28 // this header should only be #included by source files defining
29 // TypedHandle or MappingHandle subclasses
30 //
31 // @@@ Should use non-CSSM error codes
32 //
33 #ifndef _H_HANDLETEMPLATES_DEFS
34 #define _H_HANDLETEMPLATES_DEFS
35
36 #include <Security/cssm.h>
37 #include <security_utilities/refcount.h>
38 #include <security_utilities/threading.h>
39 #include <security_utilities/globalizer.h>
40 #include <security_cdsa_utilities/cssmerrors.h>
41 #include <security_cdsa_utilities/handletemplates.h>
42
43 namespace Security
44 {
45
46 //
47 // TypedHandle
48 //
49 template <class _Handle>
50 TypedHandle<_Handle>::TypedHandle()
51 : mMyHandle(invalidHandle), mValid(false)
52 {
53 }
54
55 template <class _Handle>
56 TypedHandle<_Handle>::TypedHandle(_Handle h)
57 : mMyHandle(h), mValid(true)
58 {
59 }
60
61
62 //
63 // MappingHandle instance methods
64 //
65 template <class _Handle>
66 MappingHandle<_Handle>::MappingHandle() : TypedHandle<_Handle>()
67 {
68 make();
69 }
70
71 template <class _Handle>
72 void MappingHandle<_Handle>::make()
73 {
74 StLock<Mutex> _(state());
75
76 _Handle hbase = reinterpret_cast<uintptr_t>(this);
77 for (;;) {
78 _Handle handle = hbase ^ state().nextSeq();
79 if (!state().handleInUse(handle)) {
80 // assumes sizeof(unsigned long) >= sizeof(handle)
81 secdebug("handleobj", "create %#lx for %p", static_cast<unsigned long>(handle), this);
82 TypedHandle<_Handle>::setHandle(handle);
83 state().add(handle, this);
84 return;
85 }
86 }
87 }
88
89 // The default locking virtual methods do nothing and succeed.
90 template <class _Handle>
91 void MappingHandle<_Handle>::lock() { }
92
93 template <class _Handle>
94 bool MappingHandle<_Handle>::tryLock() { return true; }
95
96
97 //
98 // MappingHandle::State
99 //
100
101 // The default State constructor should not be inlined in a standard
102 // header: its use via ModuleNexus would result in the inlined code
103 // appearing *everywhere* the State object might have to be constructed.
104 template <class _Handle>
105 MappingHandle<_Handle>::State::State()
106 : sequence(1)
107 {
108 }
109
110 //
111 // Check if the handle is already in the map. Caller must already hold
112 // the map lock. Intended for use by a subclass' implementation of
113 // MappingHandle<...>::make().
114 //
115 template <class _Handle>
116 bool MappingHandle<_Handle>::State::handleInUse(_Handle h)
117 {
118 return (HandleMap::find(h) != (*this).end());
119 }
120
121 //
122 // Observing proper map locking, locate a handle in the global handle map
123 // and return a pointer to its object. Throw CssmError(error) if it cannot
124 // be found, or it is corrupt.
125 //
126 template <class _Handle>
127 MappingHandle<_Handle> *MappingHandle<_Handle>::State::find(_Handle h, CSSM_RETURN error)
128 {
129 StLock<Mutex> _(*this);
130 typename HandleMap::const_iterator it = HandleMap::find(h);
131 if (it == (*this).end())
132 CssmError::throwMe(error);
133 MappingHandle<_Handle> *obj = it->second;
134 if (obj == NULL || obj->handle() != h)
135 CssmError::throwMe(error);
136 return obj;
137 }
138
139 //
140 // Look up the handle given in the global handle map.
141 // If not found, or if the object is corrupt, throw an exception.
142 // Otherwise, hold the State lock and return an iterator to the map entry.
143 // Caller must release the State lock in a timely manner.
144 //
145 template <class _Handle>
146 typename MappingHandle<_Handle>::HandleMap::iterator
147 MappingHandle<_Handle>::State::locate(_Handle h, CSSM_RETURN error)
148 {
149 StLock<Mutex> locker(*this);
150 typename HandleMap::iterator it = HandleMap::find(h);
151 if (it == (*this).end())
152 CssmError::throwMe(error);
153 MappingHandle<_Handle> *obj = it->second;
154 if (obj == NULL || obj->handle() != h)
155 CssmError::throwMe(error);
156 locker.release();
157 return it;
158 }
159
160 //
161 // Add a handle and its associated object to the map. Caller must already
162 // hold the map lock, and is responsible for collision-checking prior to
163 // calling this method. Intended for use by a subclass' implementation of
164 // MappingHandle<...>::make().
165 //
166 template <class _Handle>
167 void MappingHandle<_Handle>::State::add(_Handle h, MappingHandle<_Handle> *obj)
168 {
169 (*this)[h] = obj;
170 }
171
172 //
173 // Clean up the handle for an object that dies. Caller must already hold
174 // the map lock.
175 // Note that an object MAY clear its handle before (in which case we do nothing).
176 // In particular, killHandle will do this.
177 //
178 template <class _Handle>
179 void MappingHandle<_Handle>::State::erase(MappingHandle<_Handle> *obj)
180 {
181 if (obj->validHandle())
182 HandleMap::erase(obj->handle());
183 }
184
185 template <class _Handle>
186 void MappingHandle<_Handle>::State::erase(typename HandleMap::iterator &it)
187 {
188 if (it->second->validHandle())
189 HandleMap::erase(it);
190 }
191
192
193 //
194 // All explicit instantiations of MappingHandle subclasses get the
195 // generation of their 'state' member for free (if they #include this
196 // file).
197 //
198 template <class _Handle>
199 ModuleNexus<typename MappingHandle<_Handle>::State> MappingHandle<_Handle>::state;
200
201
202 } // end namespace Security
203
204 #endif //_H_HANDLETEMPLATES_DEFS