/*============================================================================= 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 #endif /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { 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: 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::mutex mutex; 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); } } // namespace impl /////////////////////////////////////////////////////////////////////////////// }} // namespace boost::spirit #endif