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