include/boost/regex/v5/mem_block_cache.hpp

100.0% Lines (29/29) 100.0% List of functions (8/8)
mem_block_cache.hpp
f(x) Functions (8)
Line TLA Hits Source Code
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_V5_MEM_BLOCK_CACHE_HPP
19 #define BOOST_REGEX_V5_MEM_BLOCK_CACHE_HPP
20
21 #include <boost/regex/config.hpp>
22 #ifndef BOOST_REGEX_AS_MODULE
23 #include <new>
24 #ifdef BOOST_HAS_THREADS
25 #include <mutex>
26 #endif
27
28 #ifndef BOOST_NO_CXX11_HDR_ATOMIC
29 #include <atomic>
30 #if ATOMIC_POINTER_LOCK_FREE == 2
31 #define BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE
32 #define BOOST_REGEX_ATOMIC_POINTER std::atomic
33 #endif
34 #endif
35 #endif
36
37
38 namespace boost{
39 namespace BOOST_REGEX_DETAIL_NS{
40
41 #if BOOST_REGEX_MAX_CACHE_BLOCKS != 0
42 #ifdef BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE /* lock free implementation */
43 struct mem_block_cache
44 {
45 std::atomic<void*> cache[BOOST_REGEX_MAX_CACHE_BLOCKS];
46
47 40x ~mem_block_cache()
48 {
49 680x for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
50 640x if (cache[i].load()) ::operator delete(cache[i].load());
51 }
52 40x }
53 1052311x void* get()
54 {
55 1267714x for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
56 1258744x void* p = cache[i].load();
57 1258744x if (p != NULL) {
58 1046164x if (cache[i].compare_exchange_strong(p, NULL)) return p;
59 }
60 }
61 8970x return ::operator new(BOOST_REGEX_BLOCKSIZE);
62 }
63 1052311x void put(void* ptr)
64 {
65 1266636x for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) {
66 1257750x void* p = cache[i].load();
67 1257750x if (p == NULL) {
68 1045933x if (cache[i].compare_exchange_strong(p, ptr)) return;
69 }
70 }
71 8886x ::operator delete(ptr);
72 }
73
74 2104622x static mem_block_cache& instance()
75 {
76 2104622x static mem_block_cache block_cache = { { {nullptr} } };
77 2104622x return block_cache;
78 }
79 };
80
81
82 #else /* lock-based implementation */
83
84
85 struct mem_block_node
86 {
87 mem_block_node* next;
88 };
89
90 struct mem_block_cache
91 {
92 // this member has to be statically initialsed:
93 mem_block_node* next { nullptr };
94 unsigned cached_blocks { 0 };
95 #ifdef BOOST_HAS_THREADS
96 std::mutex mut;
97 #endif
98
99 ~mem_block_cache()
100 {
101 while(next)
102 {
103 mem_block_node* old = next;
104 next = next->next;
105 ::operator delete(old);
106 }
107 }
108 void* get()
109 {
110 #ifdef BOOST_HAS_THREADS
111 std::lock_guard<std::mutex> g(mut);
112 #endif
113 if(next)
114 {
115 mem_block_node* result = next;
116 next = next->next;
117 --cached_blocks;
118 return result;
119 }
120 return ::operator new(BOOST_REGEX_BLOCKSIZE);
121 }
122 void put(void* p)
123 {
124 #ifdef BOOST_HAS_THREADS
125 std::lock_guard<std::mutex> g(mut);
126 #endif
127 if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS)
128 {
129 ::operator delete(p);
130 }
131 else
132 {
133 mem_block_node* old = static_cast<mem_block_node*>(p);
134 old->next = next;
135 next = old;
136 ++cached_blocks;
137 }
138 }
139 static mem_block_cache& instance()
140 {
141 static mem_block_cache block_cache;
142 return block_cache;
143 }
144 };
145 #endif
146 #endif
147
148 #if BOOST_REGEX_MAX_CACHE_BLOCKS == 0
149
150 716020x inline void* get_mem_block()
151 {
152 716020x return ::operator new(BOOST_REGEX_BLOCKSIZE);
153 }
154
155 716020x inline void put_mem_block(void* p)
156 {
157 716020x ::operator delete(p);
158 716020x }
159
160 #else
161
162 1052311x inline void* get_mem_block()
163 {
164 1052311x return mem_block_cache::instance().get();
165 }
166
167 1052311x inline void put_mem_block(void* p)
168 {
169 1052311x mem_block_cache::instance().put(p);
170 1052311x }
171
172 #endif
173 }
174 } // namespace boost
175
176 #endif
177
178