/Src/Dependencies/Boost/boost/spirit/home/classic/core/non_terminal/impl/object_with_id.ipp

http://hadesmem.googlecode.com/ · C++ Header · 191 lines · 140 code · 31 blank · 20 comment · 5 complexity · cf8860d39b53fd950b6fca3a68d37530 MD5 · raw file

  1. /*=============================================================================
  2. Copyright (c) 2002-2003 Joel de Guzman
  3. Copyright (c) 2002-2003 Martin Wille
  4. http://spirit.sourceforge.net/
  5. Use, modification and distribution is subject to the Boost Software
  6. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. #if !defined BOOST_SPIRIT_OBJECT_WITH_ID_IPP
  10. #define BOOST_SPIRIT_OBJECT_WITH_ID_IPP
  11. #include <vector>
  12. #include <boost/shared_ptr.hpp>
  13. #ifdef BOOST_SPIRIT_THREADSAFE
  14. #include <boost/thread/mutex.hpp>
  15. #include <boost/thread/once.hpp>
  16. #endif
  17. #include <boost/spirit/home/classic/namespace.hpp>
  18. ///////////////////////////////////////////////////////////////////////////////
  19. namespace boost { namespace spirit {
  20. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  21. namespace impl {
  22. //////////////////////////////////
  23. template <typename IdT = std::size_t>
  24. struct object_with_id_base_supply
  25. {
  26. typedef IdT object_id;
  27. typedef std::vector<object_id> id_vector;
  28. object_with_id_base_supply() : max_id(object_id()) {}
  29. #ifdef BOOST_SPIRIT_THREADSAFE
  30. boost::mutex mutex;
  31. #endif
  32. object_id max_id;
  33. id_vector free_ids;
  34. object_id acquire();
  35. void release(object_id);
  36. };
  37. //////////////////////////////////
  38. template <typename TagT, typename IdT = std::size_t>
  39. struct object_with_id_base
  40. {
  41. typedef TagT tag_t;
  42. typedef IdT object_id;
  43. protected:
  44. object_id acquire_object_id();
  45. void release_object_id(object_id);
  46. private:
  47. #ifdef BOOST_SPIRIT_THREADSAFE
  48. static boost::mutex &mutex_instance();
  49. static void mutex_init();
  50. #endif
  51. boost::shared_ptr<object_with_id_base_supply<IdT> > id_supply;
  52. };
  53. //////////////////////////////////
  54. template<class TagT, typename IdT = std::size_t>
  55. struct object_with_id : private object_with_id_base<TagT, IdT>
  56. {
  57. typedef object_with_id<TagT, IdT> self_t;
  58. typedef object_with_id_base<TagT, IdT> base_t;
  59. typedef IdT object_id;
  60. object_with_id() : id(base_t::acquire_object_id()) {}
  61. object_with_id(self_t const &other)
  62. : base_t(other)
  63. , id(base_t::acquire_object_id())
  64. {} // don't copy id
  65. self_t &operator = (self_t const &other)
  66. { // don't assign id
  67. base_t::operator=(other);
  68. return *this;
  69. }
  70. ~object_with_id() { base_t::release_object_id(id); }
  71. object_id get_object_id() const { return id; }
  72. private:
  73. object_id const id;
  74. };
  75. //////////////////////////////////
  76. template <typename IdT>
  77. inline IdT
  78. object_with_id_base_supply<IdT>::acquire()
  79. {
  80. #ifdef BOOST_SPIRIT_THREADSAFE
  81. boost::mutex::scoped_lock lock(mutex);
  82. #endif
  83. if (free_ids.size())
  84. {
  85. object_id id = *free_ids.rbegin();
  86. free_ids.pop_back();
  87. return id;
  88. }
  89. else
  90. {
  91. if (free_ids.capacity()<=max_id)
  92. free_ids.reserve(max_id*3/2+1);
  93. return ++max_id;
  94. }
  95. }
  96. //////////////////////////////////
  97. template <typename IdT>
  98. inline void
  99. object_with_id_base_supply<IdT>::release(IdT id)
  100. {
  101. #ifdef BOOST_SPIRIT_THREADSAFE
  102. boost::mutex::scoped_lock lock(mutex);
  103. #endif
  104. if (max_id == id)
  105. max_id--;
  106. else
  107. free_ids.push_back(id); // doesn't throw
  108. }
  109. //////////////////////////////////
  110. template <typename TagT, typename IdT>
  111. inline IdT
  112. object_with_id_base<TagT, IdT>::acquire_object_id()
  113. {
  114. {
  115. #ifdef BOOST_SPIRIT_THREADSAFE
  116. static boost::once_flag been_here = BOOST_ONCE_INIT;
  117. boost::call_once(been_here, mutex_init);
  118. boost::mutex &mutex = mutex_instance();
  119. boost::mutex::scoped_lock lock(mutex);
  120. #endif
  121. static boost::shared_ptr<object_with_id_base_supply<IdT> >
  122. static_supply;
  123. if (!static_supply.get())
  124. static_supply.reset(new object_with_id_base_supply<IdT>());
  125. id_supply = static_supply;
  126. }
  127. return id_supply->acquire();
  128. }
  129. //////////////////////////////////
  130. template <typename TagT, typename IdT>
  131. inline void
  132. object_with_id_base<TagT, IdT>::release_object_id(IdT id)
  133. {
  134. id_supply->release(id);
  135. }
  136. //////////////////////////////////
  137. #ifdef BOOST_SPIRIT_THREADSAFE
  138. template <typename TagT, typename IdT>
  139. inline boost::mutex &
  140. object_with_id_base<TagT, IdT>::mutex_instance()
  141. {
  142. static boost::mutex mutex;
  143. return mutex;
  144. }
  145. #endif
  146. //////////////////////////////////
  147. #ifdef BOOST_SPIRIT_THREADSAFE
  148. template <typename TagT, typename IdT>
  149. inline void
  150. object_with_id_base<TagT, IdT>::mutex_init()
  151. {
  152. mutex_instance();
  153. }
  154. #endif
  155. } // namespace impl
  156. ///////////////////////////////////////////////////////////////////////////////
  157. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  158. }} // namespace boost::spirit
  159. #endif