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   	///////////////////////////////////////////////////////////////////////////////
25   	namespace boost { namespace spirit {
26   	
27   	BOOST_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   	            }
(1) Event exn_spec_violation: An exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >" is thrown but the throw list "throw()" doesn't allow it to be thrown. This will cause a call to unexpected() which usually calls terminate().
(2) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >". [details]
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.size())
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
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >". [details]
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(been_here, 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  	        {
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >". [details]
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  	///////////////////////////////////////////////////////////////////////////////
192  	BOOST_SPIRIT_CLASSIC_NAMESPACE_END
193  	
194  	}} // namespace boost::spirit
195  	
196  	#endif
197