/* * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // // handleobject - give an object a process-global unique handle // #include <security_cdsa_utilities/handleobject.h> // // Static members of HandleObject // ModuleNexus<HandleObject::State> HandleObject::state; // // Bring the State constructor out of line // HandleObject::State::State() { } // // HandleObject destructor (virtual) // HandleObject::~HandleObject() { State &st = state(); StLock<Mutex> _(st); st.erase(this); } // // Assign a HandleObject's (new) Handle. // void HandleObject::State::make(HandleObject *obj) { StLock<Mutex> _(*this); for (;;) { Handle handle = reinterpret_cast<uint32>(obj) ^ (++sequence << 19); if (handleMap[handle] == NULL) { secdebug("handleobj", "create 0x%lx for %p", handle, obj); obj->setHandle(handle); handleMap[handle] = obj; return; } } } // // Clean up a HandleObject that dies. // Note that an object MAY clear its handle before (in which case we do nothing). // In particular, killHandle will do this. // void HandleObject::State::erase(HandleObject *obj) { if (obj->validHandle()) handleMap.erase(obj->handle()); } void HandleObject::State::erase(HandleMap::iterator &it) { if (it->second->validHandle()) handleMap.erase(it); } // // Observing proper map locking, locate a handle in the global handle map // and return a pointer to its object. Throw CssmError(error) if it cannot // be found, or it is corrupt. // HandleObject *HandleObject::State::find(CSSM_HANDLE h, CSSM_RETURN error) { StLock<Mutex> _(*this); HandleMap::const_iterator it = handleMap.find(h); if (it == handleMap.end()) CssmError::throwMe(error); HandleObject *obj = it->second; if (obj == NULL || obj->handle() != h) CssmError::throwMe(error); return obj; } // // Look up the handle given in the global handle map. // If not found, or if the object is corrupt, throw an exception. // Otherwise, hold the State lock and return an iterator to the map entry. // Caller must release the State lock in a timely manner. // HandleObject::HandleMap::iterator HandleObject::State::locate(CSSM_HANDLE h, CSSM_RETURN error) { StLock<Mutex> locker(*this); HandleMap::iterator it = handleMap.find(h); if (it == handleMap.end()) CssmError::throwMe(error); HandleObject *obj = it->second; if (obj == NULL || obj->handle() != h) CssmError::throwMe(error); locker.release(); return it; } // // The default locking virtual methods do nothing and succeed. // void HandleObject::lock() { } bool HandleObject::tryLock() { return true; }