1 /* 2 * Copyright (c) 2002 3 * John Maddock 4 * 5 * Use, modification and distribution are subject to the 6 * Boost Software License, Version 1.0. (See accompanying file 7 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 * 9 */ 10 11 /* 12 * LOCATION: see http://www.boost.org for most recent version. 13 * FILE mem_block_cache.hpp 14 * VERSION see <boost/version.hpp> 15 * DESCRIPTION: memory block cache used by the non-recursive matcher. 16 */ 17 18 #ifndef BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP 19 #define BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP 20 21 #include <new> 22 #ifdef BOOST_HAS_THREADS 23 #include <boost/regex/pending/static_mutex.hpp> 24 #endif 25 26 #ifdef BOOST_HAS_ABI_HEADERS 27 # include BOOST_ABI_PREFIX 28 #endif 29 30 #ifndef BOOST_NO_CXX11_HDR_ATOMIC 31 #include <atomic> 32 #if ATOMIC_POINTER_LOCK_FREE == 2 33 #define BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE 34 #define BOOST_REGEX_ATOMIC_POINTER std::atomic 35 #endif 36 #endif 37 38 namespace boost{ 39 namespace BOOST_REGEX_DETAIL_NS{ 40 41 #ifdef BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE /* lock free implementation */ 42 struct mem_block_cache 43 { 44 std::atomic<void*> cache[BOOST_REGEX_MAX_CACHE_BLOCKS]; 45 ~mem_block_cacheboost::BOOST_REGEX_DETAIL_NS::mem_block_cache46 ~mem_block_cache() 47 { 48 for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { 49 if (cache[i].load()) ::operator delete(cache[i].load()); 50 } 51 } getboost::BOOST_REGEX_DETAIL_NS::mem_block_cache52 void* get() 53 { 54 for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { 55 void* p = cache[i].load(); 56 if (p != NULL) { 57 if (cache[i].compare_exchange_strong(p, NULL)) return p; 58 } 59 } 60 return ::operator new(BOOST_REGEX_BLOCKSIZE); 61 } putboost::BOOST_REGEX_DETAIL_NS::mem_block_cache62 void put(void* ptr) 63 { 64 for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { 65 void* p = cache[i].load(); 66 if (p == NULL) { 67 if (cache[i].compare_exchange_strong(p, ptr)) return; 68 } 69 } 70 ::operator delete(ptr); 71 } 72 instanceboost::BOOST_REGEX_DETAIL_NS::mem_block_cache73 static mem_block_cache& instance() 74 { 75 static mem_block_cache block_cache = { { {nullptr} } }; 76 return block_cache; 77 } 78 }; 79 80 81 #else /* lock-based implementation */ 82 83 84 struct mem_block_node 85 { 86 mem_block_node* next; 87 }; 88 89 struct mem_block_cache 90 { 91 // this member has to be statically initialsed: 92 mem_block_node* next; 93 unsigned cached_blocks; 94 #ifdef BOOST_HAS_THREADS 95 boost::static_mutex mut; 96 #endif 97 98 ~mem_block_cache() 99 { 100 while(next) 101 { 102 mem_block_node* old = next; 103 next = next->next; 104 ::operator delete(old); 105 } 106 } 107 void* get() 108 { 109 #ifdef BOOST_HAS_THREADS 110 boost::static_mutex::scoped_lock g(mut); 111 #endif 112 if(next) 113 { 114 mem_block_node* result = next; 115 next = next->next; 116 --cached_blocks; 117 return result; 118 } 119 return ::operator new(BOOST_REGEX_BLOCKSIZE); 120 } 121 void put(void* p) 122 { 123 #ifdef BOOST_HAS_THREADS 124 boost::static_mutex::scoped_lock g(mut); 125 #endif 126 if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS) 127 { 128 ::operator delete(p); 129 } 130 else 131 { 132 mem_block_node* old = static_cast<mem_block_node*>(p); 133 old->next = next; 134 next = old; 135 ++cached_blocks; 136 } 137 } 138 static mem_block_cache& instance() 139 { 140 #ifdef BOOST_HAS_THREADS 141 static mem_block_cache block_cache = { 0, 0, BOOST_STATIC_MUTEX_INIT, }; 142 #else 143 static mem_block_cache block_cache = { 0, 0, }; 144 #endif 145 return block_cache; 146 } 147 }; 148 #endif 149 150 #if BOOST_REGEX_MAX_CACHE_BLOCKS == 0 151 get_mem_block()152inline void* BOOST_REGEX_CALL get_mem_block() 153 { 154 return ::operator new(BOOST_REGEX_BLOCKSIZE); 155 } 156 put_mem_block(void * p)157inline void BOOST_REGEX_CALL put_mem_block(void* p) 158 { 159 ::operator delete(p); 160 } 161 162 #else 163 get_mem_block()164inline void* BOOST_REGEX_CALL get_mem_block() 165 { 166 return mem_block_cache::instance().get(); 167 } 168 put_mem_block(void * p)169inline void BOOST_REGEX_CALL put_mem_block(void* p) 170 { 171 mem_block_cache::instance().put(p); 172 } 173 174 #endif 175 } 176 } // namespace boost 177 178 #ifdef BOOST_HAS_ABI_HEADERS 179 # include BOOST_ABI_SUFFIX 180 #endif 181 182 #endif 183 184