/*============================================================================= Copyright (c) 2002-2003 Joel de Guzman Copyright (c) 2002-2003 Martin Wille http://spirit.sourceforge.net/ Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined BOOST_SPIRIT_OBJECT_WITH_ID_IPP #define BOOST_SPIRIT_OBJECT_WITH_ID_IPP #include #include #ifdef BOOST_SPIRIT_THREADSAFE #include #include #endif #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN namespace impl { ////////////////////////////////// template struct object_with_id_base_supply { typedef IdT object_id; typedef std::vector id_vector; object_with_id_base_supply() : max_id(object_id()) {} #ifdef BOOST_SPIRIT_THREADSAFE boost::mutex mutex; #endif object_id max_id; id_vector free_ids; object_id acquire(); void release(object_id); }; ////////////////////////////////// template struct object_with_id_base { typedef TagT tag_t; typedef IdT object_id; protected: object_id acquire_object_id(); void release_object_id(object_id); private: #ifdef BOOST_SPIRIT_THREADSAFE static boost::mutex &mutex_instance(); static void mutex_init(); #endif boost::shared_ptr > id_supply; }; ////////////////////////////////// template struct object_with_id : private object_with_id_base { typedef object_with_id self_t; typedef object_with_id_base base_t; typedef IdT object_id; object_with_id() : id(base_t::acquire_object_id()) {} object_with_id(self_t const &other) : base_t(other) , id(base_t::acquire_object_id()) {} // don't copy id self_t &operator = (self_t const &other) { // don't assign id base_t::operator=(other); return *this; } ~object_with_id() { base_t::release_object_id(id); } object_id get_object_id() const { return id; } private: object_id const id; }; ////////////////////////////////// template inline IdT object_with_id_base_supply::acquire() { #ifdef BOOST_SPIRIT_THREADSAFE boost::mutex::scoped_lock lock(mutex); #endif if (free_ids.size()) { object_id id = *free_ids.rbegin(); free_ids.pop_back(); return id; } else { if (free_ids.capacity()<=max_id) free_ids.reserve(max_id*3/2+1); return ++max_id; } } ////////////////////////////////// template inline void object_with_id_base_supply::release(IdT id) { #ifdef BOOST_SPIRIT_THREADSAFE boost::mutex::scoped_lock lock(mutex); #endif if (max_id == id) max_id--; else free_ids.push_back(id); // doesn't throw } ////////////////////////////////// template inline IdT object_with_id_base::acquire_object_id() { { #ifdef BOOST_SPIRIT_THREADSAFE static boost::once_flag been_here = BOOST_ONCE_INIT; boost::call_once(been_here, mutex_init); boost::mutex &mutex = mutex_instance(); boost::mutex::scoped_lock lock(mutex); #endif static boost::shared_ptr > static_supply; if (!static_supply.get()) static_supply.reset(new object_with_id_base_supply()); id_supply = static_supply; } return id_supply->acquire(); } ////////////////////////////////// template inline void object_with_id_base::release_object_id(IdT id) { id_supply->release(id); } ////////////////////////////////// #ifdef BOOST_SPIRIT_THREADSAFE template inline boost::mutex & object_with_id_base::mutex_instance() { static boost::mutex mutex; return mutex; } #endif ////////////////////////////////// #ifdef BOOST_SPIRIT_THREADSAFE template inline void object_with_id_base::mutex_init() { mutex_instance(); } #endif } // namespace impl /////////////////////////////////////////////////////////////////////////////// BOOST_SPIRIT_CLASSIC_NAMESPACE_END }} // namespace boost::spirit #endif