197 lines
6.1 KiB
Plaintext
197 lines
6.1 KiB
Plaintext
|
/*=============================================================================
|
||
|
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/lock_types.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::unique_lock<boost::mutex> 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::unique_lock<boost::mutex> 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
|
||
|
#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11
|
||
|
static boost::once_flag been_here = BOOST_ONCE_INIT;
|
||
|
#else
|
||
|
static boost::once_flag been_here;
|
||
|
#endif
|
||
|
boost::call_once(been_here, mutex_init);
|
||
|
boost::mutex &mutex = mutex_instance();
|
||
|
boost::unique_lock<boost::mutex> 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
|