@@ -67,6 +67,8 @@ CK_SESSION_HANDLE HandleManager::addSession(CK_SLOT_ID slotID, CK_VOID_PTR sessi
6767 Handle h ( CKH_SESSION, slotID );
6868 h.object = session;
6969 handles[++handleCounter] = h;
70+ slotHandles[slotID].insert (handleCounter);
71+ slotSessionCount[slotID]++;
7072 return (CK_SESSION_HANDLE)handleCounter;
7173}
7274
@@ -100,6 +102,8 @@ CK_OBJECT_HANDLE HandleManager::addSessionObject(CK_SLOT_ID slotID, CK_SESSION_H
100102 h.object = object;
101103 handles[++handleCounter] = h;
102104 objects[object] = handleCounter;
105+ sessionObjectHandles[hSession].insert (handleCounter);
106+ slotHandles[slotID].insert (handleCounter);
103107 return (CK_OBJECT_HANDLE)handleCounter;
104108}
105109
@@ -124,6 +128,7 @@ CK_OBJECT_HANDLE HandleManager::addTokenObject(CK_SLOT_ID slotID, bool isPrivate
124128 h.object = object;
125129 handles[++handleCounter] = h;
126130 objects[object] = handleCounter;
131+ slotHandles[slotID].insert (handleCounter);
127132 return (CK_OBJECT_HANDLE)handleCounter;
128133}
129134
@@ -153,83 +158,105 @@ void HandleManager::destroyObject(const CK_OBJECT_HANDLE hObject)
153158
154159 std::map< CK_ULONG, Handle>::iterator it = handles.find (hObject);
155160 if (it != handles.end () && CKH_OBJECT == it->second .kind ) {
161+ // Remove from secondary indexes
162+ if (it->second .hSession != CK_INVALID_HANDLE)
163+ sessionObjectHandles[it->second .hSession ].erase (hObject);
164+ slotHandles[it->second .slotID ].erase (hObject);
165+
156166 objects.erase (it->second .object );
157167 handles.erase (it);
158168 }
159169}
160170
161171void HandleManager::sessionClosed (const CK_SESSION_HANDLE hSession)
162172{
163- CK_SLOT_ID slotID;
164173 MutexLocker lock (handlesMutex);
165174
166175 std::map< CK_ULONG, Handle>::iterator it = handles.find (hSession);
167176 if (it == handles.end () || CKH_SESSION != it->second .kind )
168177 return ; // Unable to find the specified session.
169178
170- slotID = it->second .slotID ;
179+ CK_SLOT_ID slotID = it->second .slotID ;
171180
172181 // session closed, so we can erase information about it.
182+ slotHandles[slotID].erase (hSession);
173183 handles.erase (it);
174184
175- // Erase all session object handles associated with the given session handle.
176- CK_ULONG openSessionCount = 0 ;
177- for (it = handles.begin (); it != handles.end (); ) {
178- Handle &h = it->second ;
179- if (CKH_SESSION == h.kind && slotID == h.slotID ) {
180- ++openSessionCount; // another session is open for this slotID.
181- } else {
182- if (CKH_OBJECT == h.kind && hSession == h.hSession ) {
183- // A session object is present for the given session, so erase it.
184- objects.erase (it->second .object );
185- // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
186- handles.erase (it++);
187- continue ;
185+ // Erase all session object handles associated with the given session handle
186+ // using the secondary index instead of scanning the entire handles map.
187+ std::map< CK_SESSION_HANDLE, std::set<CK_ULONG> >::iterator soit = sessionObjectHandles.find (hSession);
188+ if (soit != sessionObjectHandles.end ()) {
189+ std::set<CK_ULONG>& objHandles = soit->second ;
190+ for (std::set<CK_ULONG>::iterator oit = objHandles.begin (); oit != objHandles.end (); ++oit) {
191+ std::map< CK_ULONG, Handle>::iterator hit = handles.find (*oit);
192+ if (hit != handles.end ()) {
193+ objects.erase (hit->second .object );
194+ slotHandles[slotID].erase (*oit);
195+ handles.erase (hit);
188196 }
189197 }
190- ++it ;
198+ sessionObjectHandles. erase (soit) ;
191199 }
192200
193- // We are done when there are still sessions open.
194- if (openSessionCount)
201+ // Use the session counter to check if there are remaining open sessions.
202+ CK_ULONG& count = slotSessionCount[slotID];
203+ if (count > 0 )
204+ count--;
205+
206+ if (count > 0 )
195207 return ;
196208
197- // No more sessions open for this token, so remove all object handles that are still valid for the given slotID.
209+ // No more sessions open for this token, so remove all remaining object handles (token objects)
210+ // for the given slotID.
211+ slotSessionCount.erase (slotID);
198212 allSessionsClosed (slotID, true );
199213}
200214
201215void HandleManager::allSessionsClosed (const CK_SLOT_ID slotID, bool isLocked)
202216{
203217 MutexLocker lock (isLocked ? NULL : handlesMutex);
204218
205- // Erase all "session", "session object" and "token object" handles for a given slot id.
206- std::map< CK_ULONG, Handle>::iterator it;
207- for (it = handles.begin (); it != handles.end (); ) {
208- Handle &h = it->second ;
209- if (slotID == h.slotID ) {
210- if (CKH_OBJECT == it->second .kind )
211- objects.erase (it->second .object );
212- // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
213- handles.erase (it++);
214- continue ;
219+ // Erase all "session", "session object" and "token object" handles for a given slot id
220+ // using the per-slot index instead of scanning the entire handles map.
221+ std::map< CK_SLOT_ID, std::set<CK_ULONG> >::iterator sit = slotHandles.find (slotID);
222+ if (sit != slotHandles.end ()) {
223+ std::set<CK_ULONG>& handleSet = sit->second ;
224+ for (std::set<CK_ULONG>::iterator it = handleSet.begin (); it != handleSet.end (); ++it) {
225+ std::map< CK_ULONG, Handle>::iterator hit = handles.find (*it);
226+ if (hit != handles.end ()) {
227+ if (CKH_OBJECT == hit->second .kind )
228+ objects.erase (hit->second .object );
229+ if (CKH_SESSION == hit->second .kind )
230+ sessionObjectHandles.erase (*it);
231+ handles.erase (hit);
232+ }
215233 }
216- ++it ;
234+ slotHandles. erase (sit) ;
217235 }
236+
237+ slotSessionCount.erase (slotID);
218238}
219239
220240void HandleManager::tokenLoggedOut (const CK_SLOT_ID slotID)
221241{
222242 MutexLocker lock (handlesMutex);
223243
224- // Erase all private "token object" or "session object" handles for a given slot id.
225- std::map< CK_ULONG, Handle>::iterator it;
226- for (it = handles.begin (); it != handles.end (); ) {
227- Handle &h = it->second ;
228- if (CKH_OBJECT == h.kind && slotID == h.slotID && h.isPrivate ) {
244+ // Erase all private "token object" or "session object" handles for a given slot id
245+ // using the per-slot index instead of scanning the entire handles map.
246+ std::map< CK_SLOT_ID, std::set<CK_ULONG> >::iterator sit = slotHandles.find (slotID);
247+ if (sit == slotHandles.end ())
248+ return ;
249+
250+ std::set<CK_ULONG>& handleSet = sit->second ;
251+ for (std::set<CK_ULONG>::iterator it = handleSet.begin (); it != handleSet.end (); ) {
252+ std::map< CK_ULONG, Handle>::iterator hit = handles.find (*it);
253+ if (hit != handles.end () && CKH_OBJECT == hit->second .kind && hit->second .isPrivate ) {
229254 // A private object is present for the given slotID so we need to remove it.
230- objects.erase (it->second .object );
231- // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
232- handles.erase (it++);
255+ objects.erase (hit->second .object );
256+ if (hit->second .hSession != CK_INVALID_HANDLE)
257+ sessionObjectHandles[hit->second .hSession ].erase (*it);
258+ handles.erase (hit);
259+ handleSet.erase (it++);
233260 continue ;
234261 }
235262 ++it;
0 commit comments