| 185 | |
| 186 | template <typename Cache> |
| 187 | static void test_cache_erase_parallel(size_t megabytes) |
| 188 | { |
| 189 | double load = 1; |
| 190 | SeedInsecureRand(SeedRand::ZEROS); |
| 191 | std::vector<uint256> hashes; |
| 192 | Cache set{}; |
| 193 | size_t bytes = megabytes * (1 << 20); |
| 194 | set.setup_bytes(bytes); |
| 195 | uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256))); |
| 196 | hashes.resize(n_insert); |
| 197 | for (uint32_t i = 0; i < n_insert; ++i) { |
| 198 | uint32_t* ptr = (uint32_t*)hashes[i].begin(); |
| 199 | for (uint8_t j = 0; j < 8; ++j) |
| 200 | *(ptr++) = InsecureRand32(); |
| 201 | } |
| 202 | /** We make a copy of the hashes because future optimizations of the |
| 203 | * cuckoocache may overwrite the inserted element, so the test is |
| 204 | * "future proofed". |
| 205 | */ |
| 206 | std::vector<uint256> hashes_insert_copy = hashes; |
| 207 | std::shared_mutex mtx; |
| 208 | |
| 209 | { |
| 210 | /** Grab lock to make sure we release inserts */ |
| 211 | std::unique_lock<std::shared_mutex> l(mtx); |
| 212 | /** Insert the first half */ |
| 213 | for (uint32_t i = 0; i < (n_insert / 2); ++i) |
| 214 | set.insert(hashes_insert_copy[i]); |
| 215 | } |
| 216 | |
| 217 | /** Spin up 3 threads to run contains with erase. |
| 218 | */ |
| 219 | std::vector<std::thread> threads; |
| 220 | /** Erase the first quarter */ |
| 221 | for (uint32_t x = 0; x < 3; ++x) |
| 222 | /** Each thread is emplaced with x copy-by-value |
| 223 | */ |
| 224 | threads.emplace_back([&, x] { |
| 225 | std::shared_lock<std::shared_mutex> l(mtx); |
| 226 | size_t ntodo = (n_insert/4)/3; |
| 227 | size_t start = ntodo*x; |
| 228 | size_t end = ntodo*(x+1); |
| 229 | for (uint32_t i = start; i < end; ++i) { |
| 230 | bool contains = set.contains(hashes[i], true); |
| 231 | assert(contains); |
| 232 | } |
| 233 | }); |
| 234 | |
| 235 | /** Wait for all threads to finish |
| 236 | */ |
| 237 | for (std::thread& t : threads) |
| 238 | t.join(); |
| 239 | /** Grab lock to make sure we observe erases */ |
| 240 | std::unique_lock<std::shared_mutex> l(mtx); |
| 241 | /** Insert the second half */ |
| 242 | for (uint32_t i = (n_insert / 2); i < n_insert; ++i) |
| 243 | set.insert(hashes_insert_copy[i]); |
| 244 |
nothing calls this directly
no test coverage detected