pooled_fixedsize_stack.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright Oliver Kowalke 2014.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_CONTEXT_POOLED_pooled_fixedsize_H
  6. #define BOOST_CONTEXT_POOLED_pooled_fixedsize_H
  7. #include <atomic>
  8. #include <cstddef>
  9. #include <cstdlib>
  10. #include <new>
  11. #include <boost/assert.hpp>
  12. #include <boost/config.hpp>
  13. #include <boost/intrusive_ptr.hpp>
  14. #include <boost/pool/pool.hpp>
  15. #include <boost/context/detail/config.hpp>
  16. #include <boost/context/stack_context.hpp>
  17. #include <boost/context/stack_traits.hpp>
  18. #if defined(BOOST_USE_VALGRIND)
  19. #include <valgrind/valgrind.h>
  20. #endif
  21. #ifdef BOOST_HAS_ABI_HEADERS
  22. # include BOOST_ABI_PREFIX
  23. #endif
  24. namespace boost {
  25. namespace context {
  26. template< typename traitsT >
  27. class basic_pooled_fixedsize_stack {
  28. private:
  29. class storage {
  30. private:
  31. std::atomic< std::size_t > use_count_;
  32. std::size_t stack_size_;
  33. boost::pool< boost::default_user_allocator_malloc_free > storage_;
  34. public:
  35. storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) :
  36. use_count_( 0),
  37. stack_size_( stack_size),
  38. storage_( stack_size, next_size, max_size) {
  39. BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size_) );
  40. }
  41. stack_context allocate() {
  42. void * vp = storage_.malloc();
  43. if ( ! vp) {
  44. throw std::bad_alloc();
  45. }
  46. stack_context sctx;
  47. sctx.size = stack_size_;
  48. sctx.sp = static_cast< char * >( vp) + sctx.size;
  49. #if defined(BOOST_USE_VALGRIND)
  50. sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
  51. #endif
  52. return sctx;
  53. }
  54. void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
  55. BOOST_ASSERT( sctx.sp);
  56. BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
  57. #if defined(BOOST_USE_VALGRIND)
  58. VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
  59. #endif
  60. void * vp = static_cast< char * >( sctx.sp) - sctx.size;
  61. storage_.free( vp);
  62. }
  63. friend void intrusive_ptr_add_ref( storage * s) noexcept {
  64. ++s->use_count_;
  65. }
  66. friend void intrusive_ptr_release( storage * s) noexcept {
  67. if ( 0 == --s->use_count_) {
  68. delete s;
  69. }
  70. }
  71. };
  72. intrusive_ptr< storage > storage_;
  73. public:
  74. typedef traitsT traits_type;
  75. basic_pooled_fixedsize_stack( std::size_t stack_size = traits_type::default_size(),
  76. std::size_t next_size = 32,
  77. std::size_t max_size = 0) BOOST_NOEXCEPT_OR_NOTHROW :
  78. storage_( new storage( stack_size, next_size, max_size) ) {
  79. }
  80. stack_context allocate() {
  81. return storage_->allocate();
  82. }
  83. void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
  84. storage_->deallocate( sctx);
  85. }
  86. };
  87. typedef basic_pooled_fixedsize_stack< stack_traits > pooled_fixedsize_stack;
  88. }}
  89. #ifdef BOOST_HAS_ABI_HEADERS
  90. # include BOOST_ABI_SUFFIX
  91. #endif
  92. #endif // BOOST_CONTEXT_POOLED_pooled_fixedsize_H