/*============================================================================= | |
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 <vector> | |
#include <boost/shared_ptr.hpp> | |
#ifdef BOOST_SPIRIT_THREADSAFE | |
#include <boost/thread/mutex.hpp> | |
#include <boost/thread/once.hpp> | |
#endif | |
#include <boost/spirit/home/classic/namespace.hpp> | |
/////////////////////////////////////////////////////////////////////////////// | |
namespace boost { namespace spirit { | |
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN | |
namespace impl { | |
////////////////////////////////// | |
template <typename IdT = std::size_t> | |
struct object_with_id_base_supply | |
{ | |
typedef IdT object_id; | |
typedef std::vector<object_id> 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 <typename TagT, typename IdT = std::size_t> | |
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<object_with_id_base_supply<IdT> > id_supply; | |
}; | |
////////////////////////////////// | |
template<class TagT, typename IdT = std::size_t> | |
struct object_with_id : private object_with_id_base<TagT, IdT> | |
{ | |
typedef object_with_id<TagT, IdT> self_t; | |
typedef object_with_id_base<TagT, IdT> 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 <typename IdT> | |
inline IdT | |
object_with_id_base_supply<IdT>::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 <typename IdT> | |
inline void | |
object_with_id_base_supply<IdT>::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 <typename TagT, typename IdT> | |
inline IdT | |
object_with_id_base<TagT, IdT>::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<object_with_id_base_supply<IdT> > | |
static_supply; | |
if (!static_supply.get()) | |
static_supply.reset(new object_with_id_base_supply<IdT>()); | |
id_supply = static_supply; | |
} | |
return id_supply->acquire(); | |
} | |
////////////////////////////////// | |
template <typename TagT, typename IdT> | |
inline void | |
object_with_id_base<TagT, IdT>::release_object_id(IdT id) | |
{ | |
id_supply->release(id); | |
} | |
////////////////////////////////// | |
#ifdef BOOST_SPIRIT_THREADSAFE | |
template <typename TagT, typename IdT> | |
inline boost::mutex & | |
object_with_id_base<TagT, IdT>::mutex_instance() | |
{ | |
static boost::mutex mutex; | |
return mutex; | |
} | |
#endif | |
////////////////////////////////// | |
#ifdef BOOST_SPIRIT_THREADSAFE | |
template <typename TagT, typename IdT> | |
inline void | |
object_with_id_base<TagT, IdT>::mutex_init() | |
{ | |
mutex_instance(); | |
} | |
#endif | |
} // namespace impl | |
/////////////////////////////////////////////////////////////////////////////// | |
BOOST_SPIRIT_CLASSIC_NAMESPACE_END | |
}} // namespace boost::spirit | |
#endif |