1 /* 2 Copyright (c) 2005-2021 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 <tbb/concurrent_lru_cache.h> 23 24 //----------------------------------------------------------------------------- 25 // Concurrent LRU Cache Tests: Cache Helpers 26 //----------------------------------------------------------------------------- 27 28 namespace concurrent_lru_cache_helpers { 29 30 // call counter 31 32 template<std::size_t id> 33 struct tag{}; 34 35 template<typename Tag, typename Type> 36 struct call_counter { 37 static int calls; 38 39 static Type call(Type t) { 40 ++calls; 41 return t; 42 } 43 }; 44 45 template<typename Tag, typename Type> 46 int call_counter<Tag, Type>::calls = 0; 47 48 // cloner 49 50 template<typename ValueType> 51 struct cloner { 52 ValueType& my_ref_to_original; 53 54 cloner(ValueType& ref_to_original) : my_ref_to_original(ref_to_original) {} 55 56 template<typename KeyType> 57 ValueType operator()(KeyType) const { return my_ref_to_original; } 58 }; 59 60 // map searcher 61 62 template <typename KeyType, typename ValueType> 63 struct map_searcher { 64 using map_type = std::map<KeyType, ValueType>; 65 using map_iter = typename map_type::iterator; 66 67 map_type& my_map_ref; 68 69 map_searcher(map_type& map_ref) : my_map_ref(map_ref) {} 70 71 ValueType& operator()(KeyType k) { 72 map_iter it = my_map_ref.find(k); 73 if (it == my_map_ref.end()) 74 it = my_map_ref.insert(it, std::make_pair(k, ValueType())); 75 76 return it->second; 77 } 78 }; 79 80 // array searcher 81 82 template<typename key_type, typename value_type, std::size_t array_size> 83 struct array_searcher { 84 using array_type = value_type[array_size]; 85 86 array_type const& my_array_ref; 87 88 array_searcher(array_type const& array_ref) : my_array_ref(array_ref) {} 89 90 const value_type& operator()(key_type k) const { 91 std::size_t index = k; 92 REQUIRE_MESSAGE(k < array_size, "incorrect test setup"); 93 return my_array_ref[index]; 94 } 95 }; 96 97 // instance counter 98 99 template<typename CounterType = std::size_t> 100 struct instance_counter { 101 CounterType* my_p_count; 102 103 instance_counter() : my_p_count(new CounterType) { 104 *my_p_count = 1; 105 } 106 107 instance_counter(instance_counter const& other) : my_p_count(other.my_p_count) { 108 ++(*my_p_count); 109 } 110 111 instance_counter& operator=(instance_counter other) { 112 std::swap(this->my_p_count, other.my_p_count); 113 return *this; 114 } 115 116 ~instance_counter() { 117 if (! --(*my_p_count)) 118 delete(my_p_count); 119 } 120 121 std::size_t instances_count() const { return *my_p_count; } 122 }; 123 124 using instance_serial_counter = instance_counter<>; 125 using instance_concurrent_counter = instance_counter<std::atomic<std::size_t>>; 126 }; 127 128 //----------------------------------------------------------------------------- 129 // Concurrent LRU Cache Tests: Cache Presets 130 //----------------------------------------------------------------------------- 131 132 namespace concurrent_lru_cache_presets { 133 134 namespace helpers = concurrent_lru_cache_helpers; 135 136 // base preset with common typedefs and fields 137 138 template<typename... CacheTypes> 139 struct preset_base { 140 using cache_type = tbb::concurrent_lru_cache<CacheTypes...>; 141 using handle_type = typename cache_type::handle; 142 143 preset_base() {} 144 preset_base(const preset_base&) = delete; 145 preset_base(preset_base&&) = delete; 146 preset_base& operator=(const preset_base&) = delete; 147 preset_base& operator=(preset_base&&) = delete; 148 }; 149 150 // default preset 151 152 template<typename Key, typename Value> 153 struct preset_default : preset_base<Key, Value> { 154 using cache_type = typename preset_base<Key, Value>::cache_type; 155 using handle_type = typename cache_type::handle; 156 using callback_type = typename cache_type::value_function_type; 157 158 const std::size_t number_of_lru_history_items; 159 cache_type cache; 160 161 preset_default(callback_type callback, std::size_t history_items) : 162 number_of_lru_history_items(history_items), 163 cache(callback, number_of_lru_history_items) {}; 164 }; 165 166 // preset1 167 168 struct preset1 : preset_base<std::string, std::string> { 169 const std::size_t number_of_lru_history_items; 170 cache_type cache; 171 handle_type default_ctor_check; 172 173 static std::string callback(std::string key) { return key; } 174 175 preset1() : 176 number_of_lru_history_items(1), 177 cache(&callback, number_of_lru_history_items) {}; 178 }; 179 180 // preset for call counting 181 182 template<std::size_t tag_id> 183 struct preset_call_count : preset_base<int, int> { 184 using cache_miss_tag = helpers::tag<tag_id>; 185 using counter_type = helpers::call_counter<cache_miss_tag, int>; 186 187 const std::size_t number_of_lru_history_items; 188 cache_type cache; 189 190 preset_call_count() : 191 number_of_lru_history_items(8), 192 cache(&counter_type::call, number_of_lru_history_items) {} 193 }; 194 195 // preset for instance counting 196 197 struct preset_instance_count : preset_base< 198 std::size_t, helpers::instance_serial_counter, 199 helpers::cloner<helpers::instance_serial_counter>> { 200 201 using cloner_type = helpers::cloner<helpers::instance_serial_counter>; 202 203 helpers::instance_serial_counter source; 204 cloner_type cloner; 205 const std::size_t number_of_lru_history_items; 206 cache_type cache; 207 208 preset_instance_count() : 209 cloner(source), 210 number_of_lru_history_items(8), 211 cache(cloner, number_of_lru_history_items) {} 212 }; 213 214 // preset for instance counting with external map 215 216 struct preset_map_instance_count : preset_base< 217 std::size_t, helpers::instance_serial_counter, 218 helpers::map_searcher<std::size_t, helpers::instance_serial_counter>> { 219 220 using map_searcher_type = helpers::map_searcher<std::size_t, helpers::instance_serial_counter>; 221 using objects_map_type = map_searcher_type::map_type; 222 223 static const std::size_t number_of_lru_history_items; 224 map_searcher_type::map_type objects_map; 225 cache_type cache; 226 227 preset_map_instance_count() : 228 cache(map_searcher_type(objects_map), number_of_lru_history_items) {} 229 230 bool is_evicted(std::size_t key) { 231 objects_map_type::iterator it = objects_map.find(key); 232 233 REQUIRE_MESSAGE( 234 it != objects_map.end(), 235 "no value for key - error in test logic ?"); 236 237 return it->second.instances_count() == 1; 238 } 239 240 void fill_up_cache(std::size_t lower_bound, std::size_t upper_bound) { 241 for (std::size_t i = lower_bound; i < upper_bound; ++i) 242 cache[i]; 243 } 244 }; 245 246 const std::size_t preset_map_instance_count::number_of_lru_history_items = 8; 247 }; 248 249 #endif // __TBB_test_common_concurrent_lru_cache_common 250