1 /* 2 Copyright (c) 2005-2022 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #ifndef __TBB_test_common_concurrent_lru_cache_common 18 #define __TBB_test_common_concurrent_lru_cache_common 19 20 21 #include "test.h" 22 #include "utils.h" 23 #include <tbb/concurrent_lru_cache.h> 24 25 //----------------------------------------------------------------------------- 26 // Concurrent LRU Cache Tests: Cache Helpers 27 //----------------------------------------------------------------------------- 28 29 namespace concurrent_lru_cache_helpers { 30 31 // call counter 32 33 template<std::size_t id> 34 struct tag{}; 35 36 template<typename Tag, typename Type> 37 struct call_counter { 38 static int calls; 39 callcall_counter40 static Type call(Type t) { 41 ++calls; 42 return t; 43 } 44 }; 45 46 template<typename Tag, typename Type> 47 int call_counter<Tag, Type>::calls = 0; 48 49 // cloner 50 51 template<typename ValueType> 52 struct cloner { 53 ValueType& my_ref_to_original; 54 clonercloner55 cloner(ValueType& ref_to_original) : my_ref_to_original(ref_to_original) {} 56 57 template<typename KeyType> operatorcloner58 ValueType operator()(KeyType) const { return my_ref_to_original; } 59 }; 60 61 // map searcher 62 63 template <typename KeyType, typename ValueType> 64 struct map_searcher { 65 using map_type = std::map<KeyType, ValueType>; 66 using map_iter = typename map_type::iterator; 67 68 map_type& my_map_ref; 69 map_searchermap_searcher70 map_searcher(map_type& map_ref) : my_map_ref(map_ref) {} 71 operatormap_searcher72 ValueType& operator()(KeyType k) { 73 map_iter it = my_map_ref.find(k); 74 if (it == my_map_ref.end()) 75 it = my_map_ref.insert(it, std::make_pair(k, ValueType())); 76 77 return it->second; 78 } 79 }; 80 81 // array searcher 82 83 template<typename key_type, typename value_type, std::size_t array_size> 84 struct array_searcher { 85 using array_type = value_type[array_size]; 86 87 array_type const& my_array_ref; 88 array_searcherarray_searcher89 array_searcher(array_type const& array_ref) : my_array_ref(array_ref) {} 90 operatorarray_searcher91 const value_type& operator()(key_type k) const { 92 std::size_t index = k; 93 REQUIRE_MESSAGE(k < array_size, "incorrect test setup"); 94 return my_array_ref[index]; 95 } 96 }; 97 98 // instance counter 99 100 template<typename CounterType = std::size_t> 101 struct instance_counter { 102 CounterType* my_p_count; 103 instance_counterinstance_counter104 instance_counter() : my_p_count(new CounterType) { 105 *my_p_count = 1; 106 } 107 instance_counterinstance_counter108 instance_counter(instance_counter const& other) : my_p_count(other.my_p_count) { 109 ++(*my_p_count); 110 } 111 112 instance_counter& operator=(instance_counter other) { 113 std::swap(this->my_p_count, other.my_p_count); 114 return *this; 115 } 116 ~instance_counterinstance_counter117 ~instance_counter() { 118 bool is_last = ! --(*my_p_count); 119 #if __GNUC__ == 12 120 // GCC 12 warns about using my_p_count after delete. 121 // The test was investigated and no problems were detected 122 // The following statement silence the warning 123 static bool unused_is_last = is_last; 124 utils::suppress_unused_warning(unused_is_last); 125 #endif 126 if (is_last) 127 delete(my_p_count); 128 } instances_countinstance_counter129 std::size_t instances_count() const { return *my_p_count; } 130 }; 131 132 using instance_serial_counter = instance_counter<>; 133 using instance_concurrent_counter = instance_counter<std::atomic<std::size_t>>; 134 }; 135 136 //----------------------------------------------------------------------------- 137 // Concurrent LRU Cache Tests: Cache Presets 138 //----------------------------------------------------------------------------- 139 140 namespace concurrent_lru_cache_presets { 141 142 namespace helpers = concurrent_lru_cache_helpers; 143 144 // base preset with common typedefs and fields 145 146 template<typename... CacheTypes> 147 struct preset_base { 148 using cache_type = tbb::concurrent_lru_cache<CacheTypes...>; 149 using handle_type = typename cache_type::handle; 150 preset_basepreset_base151 preset_base() {} 152 preset_base(const preset_base&) = delete; 153 preset_base(preset_base&&) = delete; 154 preset_base& operator=(const preset_base&) = delete; 155 preset_base& operator=(preset_base&&) = delete; 156 }; 157 158 // default preset 159 160 template<typename Key, typename Value> 161 struct preset_default : preset_base<Key, Value> { 162 using cache_type = typename preset_base<Key, Value>::cache_type; 163 using handle_type = typename cache_type::handle; 164 using callback_type = typename cache_type::value_function_type; 165 166 const std::size_t number_of_lru_history_items; 167 cache_type cache; 168 preset_defaultpreset_default169 preset_default(callback_type callback, std::size_t history_items) : 170 number_of_lru_history_items(history_items), 171 cache(callback, number_of_lru_history_items) {}; 172 }; 173 174 // preset1 175 176 struct preset1 : preset_base<std::string, std::string> { 177 const std::size_t number_of_lru_history_items; 178 cache_type cache; 179 handle_type default_ctor_check; 180 callbackpreset1181 static std::string callback(std::string key) { return key; } 182 preset1preset1183 preset1() : 184 number_of_lru_history_items(1), 185 cache(&callback, number_of_lru_history_items) {}; 186 }; 187 188 // preset for call counting 189 190 template<std::size_t tag_id> 191 struct preset_call_count : preset_base<int, int> { 192 using cache_miss_tag = helpers::tag<tag_id>; 193 using counter_type = helpers::call_counter<cache_miss_tag, int>; 194 195 const std::size_t number_of_lru_history_items; 196 cache_type cache; 197 preset_call_countpreset_call_count198 preset_call_count() : 199 number_of_lru_history_items(8), 200 cache(&counter_type::call, number_of_lru_history_items) {} 201 }; 202 203 // preset for instance counting 204 205 struct preset_instance_count : preset_base< 206 std::size_t, helpers::instance_serial_counter, 207 helpers::cloner<helpers::instance_serial_counter>> { 208 209 using cloner_type = helpers::cloner<helpers::instance_serial_counter>; 210 211 helpers::instance_serial_counter source; 212 cloner_type cloner; 213 const std::size_t number_of_lru_history_items; 214 cache_type cache; 215 preset_instance_countpreset_instance_count216 preset_instance_count() : 217 cloner(source), 218 number_of_lru_history_items(8), 219 cache(cloner, number_of_lru_history_items) {} 220 }; 221 222 // preset for instance counting with external map 223 224 struct preset_map_instance_count : preset_base< 225 std::size_t, helpers::instance_serial_counter, 226 helpers::map_searcher<std::size_t, helpers::instance_serial_counter>> { 227 228 using map_searcher_type = helpers::map_searcher<std::size_t, helpers::instance_serial_counter>; 229 using objects_map_type = map_searcher_type::map_type; 230 231 static const std::size_t number_of_lru_history_items; 232 map_searcher_type::map_type objects_map; 233 cache_type cache; 234 preset_map_instance_countpreset_map_instance_count235 preset_map_instance_count() : 236 cache(map_searcher_type(objects_map), number_of_lru_history_items) {} 237 is_evictedpreset_map_instance_count238 bool is_evicted(std::size_t key) { 239 objects_map_type::iterator it = objects_map.find(key); 240 241 REQUIRE_MESSAGE( 242 it != objects_map.end(), 243 "no value for key - error in test logic ?"); 244 245 return it->second.instances_count() == 1; 246 } 247 fill_up_cachepreset_map_instance_count248 void fill_up_cache(std::size_t lower_bound, std::size_t upper_bound) { 249 for (std::size_t i = lower_bound; i < upper_bound; ++i) 250 cache[i]; 251 } 252 }; 253 254 const std::size_t preset_map_instance_count::number_of_lru_history_items = 8; 255 }; 256 257 #endif // __TBB_test_common_concurrent_lru_cache_common 258