]> git.saurik.com Git - apple/security.git/blame - libsecurity_cdsa_utilities/lib/handletemplates_defs.h
Security-55179.13.tar.gz
[apple/security.git] / libsecurity_cdsa_utilities / lib / handletemplates_defs.h
CommitLineData
b1ab9ed8
A
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
43namespace Security
44{
45
46//
47// TypedHandle
48//
49template <class _Handle>
50TypedHandle<_Handle>::TypedHandle()
51 : mMyHandle(invalidHandle), mValid(false)
52{
53}
54
55template <class _Handle>
56TypedHandle<_Handle>::TypedHandle(_Handle h)
57 : mMyHandle(h), mValid(true)
58{
59}
60
61
62//
63// MappingHandle instance methods
64//
65template <class _Handle>
66MappingHandle<_Handle>::MappingHandle() : TypedHandle<_Handle>()
67{
68 make();
69}
70
71template <class _Handle>
72void 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.
90template <class _Handle>
91void MappingHandle<_Handle>::lock() { }
92
93template <class _Handle>
94bool 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.
104template <class _Handle>
105MappingHandle<_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//
115template <class _Handle>
116bool 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//
126template <class _Handle>
127MappingHandle<_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//
145template <class _Handle>
146typename MappingHandle<_Handle>::HandleMap::iterator
147MappingHandle<_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//
166template <class _Handle>
167void 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//
178template <class _Handle>
179void MappingHandle<_Handle>::State::erase(MappingHandle<_Handle> *obj)
180{
181 if (obj->validHandle())
182 HandleMap::erase(obj->handle());
183}
184
185template <class _Handle>
186void 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//
198template <class _Handle>
199ModuleNexus<typename MappingHandle<_Handle>::State> MappingHandle<_Handle>::state;
200
201
202} // end namespace Security
203
204#endif //_H_HANDLETEMPLATES_DEFS