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 }; 73 74 75 #else /* lock-based implementation */ 76 77 78 struct mem_block_node 79 { 80 mem_block_node* next; 81 }; 82 83 struct mem_block_cache 84 { 85 // this member has to be statically initialsed: 86 mem_block_node* next; 87 unsigned cached_blocks; 88 #ifdef BOOST_HAS_THREADS 89 boost::static_mutex mut; 90 #endif 91 92 ~mem_block_cache() 93 { 94 while(next) 95 { 96 mem_block_node* old = next; 97 next = next->next; 98 ::operator delete(old); 99 } 100 } 101 void* get() 102 { 103 #ifdef BOOST_HAS_THREADS 104 boost::static_mutex::scoped_lock g(mut); 105 #endif 106 if(next) 107 { 108 mem_block_node* result = next; 109 next = next->next; 110 --cached_blocks; 111 return result; 112 } 113 return ::operator new(BOOST_REGEX_BLOCKSIZE); 114 } 115 void put(void* p) 116 { 117 #ifdef BOOST_HAS_THREADS 118 boost::static_mutex::scoped_lock g(mut); 119 #endif 120 if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS) 121 { 122 ::operator delete(p); 123 } 124 else 125 { 126 mem_block_node* old = static_cast<mem_block_node*>(p); 127 old->next = next; 128 next = old; 129 ++cached_blocks; 130 } 131 } 132 }; 133 #endif 134 135 extern mem_block_cache block_cache; 136 137 } 138 } // namespace boost 139 140 #ifdef BOOST_HAS_ABI_HEADERS 141 # include BOOST_ABI_SUFFIX 142 #endif 143 144 #endif 145 146