Fix #31: Entries can disappear when deleted key is reassigned during a migration
[junction.git] / samples / MapCorrectnessTests / TestDoubleAssign.h
1 /*------------------------------------------------------------------------
2   Junction: Concurrent data structures in C++
3   Copyright (c) 2016, 2017 Jeff Preshing
4
5   Distributed under the Simplified BSD License.
6   Original location: https://github.com/preshing/junction
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the LICENSE file for more information.
11 ------------------------------------------------------------------------*/
12
13 #ifndef SAMPLES_MAPCORRECTNESSTESTS_TESTDOUBLEASSIGN_H
14 #define SAMPLES_MAPCORRECTNESSTESTS_TESTDOUBLEASSIGN_H
15
16 #include <junction/Core.h>
17 #include "TestEnvironment.h"
18 #include <turf/extra/Random.h>
19
20 class TestDoubleAssign {
21 public:
22     static const ureg KeysToInsert = 1000;
23     TestEnvironment& m_env;
24     MapAdapter::Map* m_map;
25     turf::Atomic<u32> m_index;
26
27     TestDoubleAssign(TestEnvironment& env) : m_env(env), m_map(NULL), m_index(0) {
28     }
29
30     void doubleAssignKeys(ureg threadIndex) {
31         for (;;) {
32             u32 key = m_index.fetchAdd(1, turf::Relaxed);
33             if (key >= KeysToInsert + 2)
34                 break;
35
36             m_map->assign(key, (void*) (key * 20));
37             m_map->erase(key);
38             m_map->assign(key, (void*) (key * 20));
39         }
40         m_env.threads[threadIndex].update();
41     }
42
43     void checkMapContents() {
44 #if TEST_CHECK_MAP_CONTENTS
45         for (MapAdapter::Map::Iterator iter(*m_map); iter.isValid(); iter.next()) {
46             u32 key = iter.getKey();
47             if (iter.getValue() != (void*) (key * 20))
48                 TURF_DEBUG_BREAK();
49         }
50
51         for (ureg i = 2; i < KeysToInsert + 2; i++) {
52             auto r = m_map->find(i);
53             if (r.getValue() != (void*) (i * 20))
54                 TURF_DEBUG_BREAK();
55         }
56 #endif
57     }
58
59     void run() {
60         m_map = new MapAdapter::Map(MapAdapter::getInitialCapacity(KeysToInsert));
61         m_index = 2;
62         m_env.dispatcher.kick(&TestDoubleAssign::doubleAssignKeys, *this);
63         checkMapContents();
64         delete m_map;
65         m_map = NULL;
66     }
67 };
68
69 #endif // SAMPLES_MAPCORRECTNESSTESTS_TESTDOUBLEASSIGN_H