// Copyright (c) 2003 Daniel Wallin // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. #ifndef LOCKED_PTR_030928_HPP #define LOCKED_PTR_030928_HPP #include #include #include #include struct locker_pool; struct locker { locker(boost::recursive_mutex& m, locker_pool* p) : lock(m, false) , count(0) , pool(p) , next(0) {} boost::recursive_mutex::scoped_lock lock; int count; locker_pool* pool; locker* next; }; class locker_pool { public: locker_pool() : chain(0) {} locker* allocate() { locker* p; if (chain) { boost::mutex::scoped_lock pl(pool_mutex); p = chain; chain = chain->next; } else { p = new locker(mutex, this); } p->lock.lock(); return p; } void deallocate(locker* l) { l->lock.unlock(); { boost::mutex::scoped_lock pl(pool_mutex); l->next = chain; chain = l; } } ~locker_pool() { for (locker* c = chain; c != 0; c = c->next) delete c; } private: boost::mutex pool_mutex; boost::recursive_mutex mutex; locker* chain; }; template class locked_ptr { public: locked_ptr() : m_p(0) , m_lock(0) {} locked_ptr(T* p, locker* l) : m_p(p) , m_lock(l) { ++m_lock->count; } locked_ptr(const locked_ptr& x) : m_p(x.m_p) , m_lock(x.m_lock) { ++m_lock->count; } ~locked_ptr() { if (--m_lock->count == 0) m_lock->pool->deallocate(m_lock); } void operator=(const locked_ptr& rhs) { m_p = rhs.m_p; m_lock = rhs.m_lock; ++m_lock->count; } T* operator->() const { return m_p; } T& operator*() const { return *m_p; } private: T* m_p; locker* m_lock; }; #endif // LOCKED_PTR_030928_HPP