source: NonGTP/Boost/boost/spirit/core/non_terminal/impl/object_with_id.ipp @ 857

Revision 857, 5.8 KB checked in by igarcia, 18 years ago (diff)
Line 
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///////////////////////////////////////////////////////////////////////////////
22namespace 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
Note: See TracBrowser for help on using the repository browser.