pooled_fixedsize_stack.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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_CONTEXT_USE_MAP_STACK)
  19. extern "C" {
  20. #include <sys/mman.h>
  21. #include <stdlib.h>
  22. }
  23. #endif
  24. #if defined(BOOST_USE_VALGRIND)
  25. #include <valgrind/valgrind.h>
  26. #endif
  27. #ifdef BOOST_HAS_ABI_HEADERS
  28. # include BOOST_ABI_PREFIX
  29. #endif
  30. namespace boost {
  31. namespace context {
  32. #if defined(BOOST_CONTEXT_USE_MAP_STACK)
  33. namespace detail {
  34. template< typename traitsT >
  35. struct map_stack_allocator {
  36. typedef std::size_t size_type;
  37. typedef std::ptrdiff_t difference_type;
  38. static char * malloc( const size_type bytes) {
  39. void * block;
  40. if ( ::posix_memalign( &block, traitsT::page_size(), bytes) != 0) {
  41. return 0;
  42. }
  43. if ( mmap( block, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0) == MAP_FAILED) {
  44. std::free( block);
  45. return 0;
  46. }
  47. return reinterpret_cast< char * >( block);
  48. }
  49. static void free( char * const block) {
  50. std::free( block);
  51. }
  52. };
  53. }
  54. #endif
  55. template< typename traitsT >
  56. class basic_pooled_fixedsize_stack {
  57. private:
  58. class storage {
  59. private:
  60. std::atomic< std::size_t > use_count_;
  61. std::size_t stack_size_;
  62. #if defined(BOOST_CONTEXT_USE_MAP_STACK)
  63. boost::pool< detail::map_stack_allocator< traitsT > > storage_;
  64. #else
  65. boost::pool< boost::default_user_allocator_malloc_free > storage_;
  66. #endif
  67. public:
  68. storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) :
  69. use_count_( 0),
  70. stack_size_( stack_size),
  71. storage_( stack_size, next_size, max_size) {
  72. BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size_) );
  73. }
  74. stack_context allocate() {
  75. void * vp = storage_.malloc();
  76. if ( ! vp) {
  77. throw std::bad_alloc();
  78. }
  79. stack_context sctx;
  80. sctx.size = stack_size_;
  81. sctx.sp = static_cast< char * >( vp) + sctx.size;
  82. #if defined(BOOST_USE_VALGRIND)
  83. sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp);
  84. #endif
  85. return sctx;
  86. }
  87. void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
  88. BOOST_ASSERT( sctx.sp);
  89. BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) );
  90. #if defined(BOOST_USE_VALGRIND)
  91. VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
  92. #endif
  93. void * vp = static_cast< char * >( sctx.sp) - sctx.size;
  94. storage_.free( vp);
  95. }
  96. friend void intrusive_ptr_add_ref( storage * s) noexcept {
  97. ++s->use_count_;
  98. }
  99. friend void intrusive_ptr_release( storage * s) noexcept {
  100. if ( 0 == --s->use_count_) {
  101. delete s;
  102. }
  103. }
  104. };
  105. intrusive_ptr< storage > storage_;
  106. public:
  107. typedef traitsT traits_type;
  108. basic_pooled_fixedsize_stack( std::size_t stack_size = traits_type::default_size(),
  109. std::size_t next_size = 32,
  110. std::size_t max_size = 0) BOOST_NOEXCEPT_OR_NOTHROW :
  111. storage_( new storage( stack_size, next_size, max_size) ) {
  112. }
  113. stack_context allocate() {
  114. return storage_->allocate();
  115. }
  116. void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW {
  117. storage_->deallocate( sctx);
  118. }
  119. };
  120. typedef basic_pooled_fixedsize_stack< stack_traits > pooled_fixedsize_stack;
  121. }}
  122. #ifdef BOOST_HAS_ABI_HEADERS
  123. # include BOOST_ABI_SUFFIX
  124. #endif
  125. #endif // BOOST_CONTEXT_POOLED_pooled_fixedsize_H