1 /*=============================================================================
2 Copyright (c) 2002-2003 Joel de Guzman
3 Copyright (c) 2002-2003 Martin Wille
4 http://spirit.sourceforge.net/
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #if !defined BOOST_SPIRIT_OBJECT_WITH_ID_IPP
11 #define BOOST_SPIRIT_OBJECT_WITH_ID_IPP
14 #include <boost/shared_ptr.hpp>
16 #ifdef BOOST_SPIRIT_THREADSAFE
17 #include <boost/thread/mutex.hpp>
18 #include <boost/thread/lock_types.hpp>
19 #include <boost/thread/once.hpp>
22 #include <boost/spirit/home/classic/namespace.hpp>
24 ///////////////////////////////////////////////////////////////////////////////
25 namespace boost { namespace spirit {
27 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
31 //////////////////////////////////
32 template <typename IdT = std::size_t>
33 struct object_with_id_base_supply
35 typedef IdT object_id;
36 typedef std::vector<object_id> id_vector;
38 object_with_id_base_supply() : max_id(object_id()) {}
40 #ifdef BOOST_SPIRIT_THREADSAFE
47 void release(object_id);
50 //////////////////////////////////
51 template <typename TagT, typename IdT = std::size_t>
52 struct object_with_id_base
55 typedef IdT object_id;
59 object_id acquire_object_id();
60 void release_object_id(object_id);
63 #ifdef BOOST_SPIRIT_THREADSAFE
64 static boost::mutex &mutex_instance();
65 static void mutex_init();
68 boost::shared_ptr<object_with_id_base_supply<IdT> > id_supply;
71 //////////////////////////////////
72 template<class TagT, typename IdT = std::size_t>
73 struct object_with_id : private object_with_id_base<TagT, IdT>
75 typedef object_with_id<TagT, IdT> self_t;
76 typedef object_with_id_base<TagT, IdT> base_t;
77 typedef IdT object_id;
79 object_with_id() : id(base_t::acquire_object_id()) {}
80 object_with_id(self_t const &other)
82 , id(base_t::acquire_object_id())
84 self_t &operator = (self_t const &other)
86 base_t::operator=(other);
89 ~object_with_id() { base_t::release_object_id(id); }
90 object_id get_object_id() const { return id; }
97 //////////////////////////////////
98 template <typename IdT>
100 object_with_id_base_supply<IdT>::acquire()
102 #ifdef BOOST_SPIRIT_THREADSAFE
103 boost::unique_lock<boost::mutex> lock(mutex);
107 object_id id = *free_ids.rbegin();
113 if (free_ids.capacity()<=max_id)
114 free_ids.reserve(max_id*3/2+1);
119 //////////////////////////////////
120 template <typename IdT>
122 object_with_id_base_supply<IdT>::release(IdT id)
124 #ifdef BOOST_SPIRIT_THREADSAFE
125 boost::unique_lock<boost::mutex> lock(mutex);
130 free_ids.push_back(id); // doesn't throw
133 //////////////////////////////////
134 template <typename TagT, typename IdT>
136 object_with_id_base<TagT, IdT>::acquire_object_id()
139 #ifdef BOOST_SPIRIT_THREADSAFE
140 #ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11
141 static boost::once_flag been_here = BOOST_ONCE_INIT;
143 static boost::once_flag been_here;
145 boost::call_once(been_here, mutex_init);
146 boost::mutex &mutex = mutex_instance();
147 boost::unique_lock<boost::mutex> lock(mutex);
149 static boost::shared_ptr<object_with_id_base_supply<IdT> >
152 if (!static_supply.get())
153 static_supply.reset(new object_with_id_base_supply<IdT>());
154 id_supply = static_supply;
157 return id_supply->acquire();
160 //////////////////////////////////
161 template <typename TagT, typename IdT>
163 object_with_id_base<TagT, IdT>::release_object_id(IdT id)
165 id_supply->release(id);
168 //////////////////////////////////
169 #ifdef BOOST_SPIRIT_THREADSAFE
170 template <typename TagT, typename IdT>
171 inline boost::mutex &
172 object_with_id_base<TagT, IdT>::mutex_instance()
174 static boost::mutex mutex;
179 //////////////////////////////////
180 #ifdef BOOST_SPIRIT_THREADSAFE
181 template <typename TagT, typename IdT>
183 object_with_id_base<TagT, IdT>::mutex_init()
191 ///////////////////////////////////////////////////////////////////////////////
192 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
194 }} // namespace boost::spirit