1/*=============================================================================
2 Copyright (c) 2002-2003 Joel de Guzman
3 Copyright (c) 2002-2003 Martin Wille
4 http://spirit.sourceforge.net/
5
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
12
13#include <vector>
14#include <boost/shared_ptr.hpp>
15
16#ifdef BOOST_SPIRIT_THREADSAFE
17#include <boost/thread/mutex.hpp>
18#include <boost/thread/lock_types.hpp>
19#include <boost/thread/once.hpp>
20#endif
21
22#include <boost/spirit/home/classic/namespace.hpp>
23
24///////////////////////////////////////////////////////////////////////////////
25namespace boost { namespace spirit {
26
27BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
28
29 namespace impl {
30
31 //////////////////////////////////
32 template <typename IdT = std::size_t>
33 struct object_with_id_base_supply
34 {
35 typedef IdT object_id;
36 typedef std::vector<object_id> id_vector;
37
38 object_with_id_base_supply() : max_id(object_id()) {}
39
40#ifdef BOOST_SPIRIT_THREADSAFE
41 boost::mutex mutex;
42#endif
43 object_id max_id;
44 id_vector free_ids;
45
46 object_id acquire();
47 void release(object_id);
48 };
49
50 //////////////////////////////////
51 template <typename TagT, typename IdT = std::size_t>
52 struct object_with_id_base
53 {
54 typedef TagT tag_t;
55 typedef IdT object_id;
56
57 protected:
58
59 object_id acquire_object_id();
60 void release_object_id(object_id);
61
62 private:
63#ifdef BOOST_SPIRIT_THREADSAFE
64 static boost::mutex &mutex_instance();
65 static void mutex_init();
66#endif
67
68 boost::shared_ptr<object_with_id_base_supply<IdT> > id_supply;
69 };
70
71 //////////////////////////////////
72 template<class TagT, typename IdT = std::size_t>
73 struct object_with_id : private object_with_id_base<TagT, IdT>
74 {
75 typedef object_with_id<TagT, IdT> self_t;
76 typedef object_with_id_base<TagT, IdT> base_t;
77 typedef IdT object_id;
78
79 object_with_id() : id(base_t::acquire_object_id()) {}
80 object_with_id(self_t const &other)
81 : base_t(other)
82 , id(base_t::acquire_object_id())
83 {} // don't copy id
84 self_t &operator = (self_t const &other)
85 { // don't assign id
86 base_t::operator=(other);
87 return *this;
88 }
89 ~object_with_id() { base_t::release_object_id(id); }
90 object_id get_object_id() const { return id; }
91
92 private:
93
94 object_id const id;
95 };
96
97 //////////////////////////////////
98 template <typename IdT>
99 inline IdT
100 object_with_id_base_supply<IdT>::acquire()
101 {
102#ifdef BOOST_SPIRIT_THREADSAFE
103 boost::unique_lock<boost::mutex> lock(mutex);
104#endif
105 if (!free_ids.empty())
106 {
107 object_id id = *free_ids.rbegin();
108 free_ids.pop_back();
109 return id;
110 }
111 else
112 {
113 if (free_ids.capacity()<=max_id)
114 free_ids.reserve(max_id*3/2+1);
115 return ++max_id;
116 }
117 }
118
119 //////////////////////////////////
120 template <typename IdT>
121 inline void
122 object_with_id_base_supply<IdT>::release(IdT id)
123 {
124#ifdef BOOST_SPIRIT_THREADSAFE
125 boost::unique_lock<boost::mutex> lock(mutex);
126#endif
127 if (max_id == id)
128 max_id--;
129 else
130 free_ids.push_back(id); // doesn't throw
131 }
132
133 //////////////////////////////////
134 template <typename TagT, typename IdT>
135 inline IdT
136 object_with_id_base<TagT, IdT>::acquire_object_id()
137 {
138 {
139#ifdef BOOST_SPIRIT_THREADSAFE
140#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11
141 static boost::once_flag been_here = BOOST_ONCE_INIT;
142#else
143 static boost::once_flag been_here;
144#endif
145 boost::call_once(flag&: been_here, f&: mutex_init);
146 boost::mutex &mutex = mutex_instance();
147 boost::unique_lock<boost::mutex> lock(mutex);
148#endif
149 static boost::shared_ptr<object_with_id_base_supply<IdT> >
150 static_supply;
151
152 if (!static_supply.get())
153 static_supply.reset(new object_with_id_base_supply<IdT>());
154 id_supply = static_supply;
155 }
156
157 return id_supply->acquire();
158 }
159
160 //////////////////////////////////
161 template <typename TagT, typename IdT>
162 inline void
163 object_with_id_base<TagT, IdT>::release_object_id(IdT id)
164 {
165 id_supply->release(id);
166 }
167
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()
173 {
174 static boost::mutex mutex;
175 return mutex;
176 }
177#endif
178
179 //////////////////////////////////
180#ifdef BOOST_SPIRIT_THREADSAFE
181 template <typename TagT, typename IdT>
182 inline void
183 object_with_id_base<TagT, IdT>::mutex_init()
184 {
185 mutex_instance();
186 }
187#endif
188
189 } // namespace impl
190
191///////////////////////////////////////////////////////////////////////////////
192BOOST_SPIRIT_CLASSIC_NAMESPACE_END
193
194}} // namespace boost::spirit
195
196#endif
197

source code of boost/libs/spirit/include/boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp