Clears the internal associative array.
Retrieves the value for the key key, or returns the default value if there was none.
Returns whether or not the passed key is in the associative array.
Returns whether or not this instance has been set up.
Returns a new dynamic array of all the keys in the internal associative array.
Returns the length of the internal associative array.
Implements opEquals for this type, comparing the internal associative array with that of another MutexedAA.
Implements opEquals for this type, comparing the internal associative array with a different one.
aa[key] array retrieve operation, wrapped in a mutex lock.
aa[key] = value array assign operation, wrapped in a mutex lock.
Implements index assign operations by mixin strings.
Implements unary operations by mixin strings.
Rehashes the internal associative array.
aa.remove(key) array operation, wrapped in a mutex lock.
Returns the value for the key key, inserting value lazily if it is not present.
Sets up this instance. Does nothing if it has already been set up.
Reserves a unique key in the associative array.
Updates the value for the key key in the internal associative array, invoking the first of the passed delegate to insert a new value if it doesn't exist, or the second selegate to modify it in place if it does.
Returns a new dynamic array of all the values in the internal associative array.
MutexedAA!(string[int]) aa; aa.setup(); // important! aa[1] = "one"; aa[2] = "two"; aa[3] = "three"; auto hasOne = aa.has(1); assert(hasOne); assert(aa[1] == "one"); assert(aa[2] == "two"); auto three = aa.get(3); assert(three == "three"); auto four = aa.get(4, "four"); assert(four == "four"); auto five = aa.require(5, "five"); assert(five == "five"); assert(aa[5] == "five"); auto keys = aa.keys; assert(keys.canFind(1)); assert(keys.canFind(5)); assert(!keys.canFind(6)); auto values = aa.values; assert(values.canFind("one")); assert(values.canFind("four")); assert(!values.canFind("six")); aa.rehash();
1 { 2 MutexedAA!(string[int]) aa1; 3 assert(!aa1.isReady); 4 aa1.setup(); 5 assert(aa1.isReady); 6 aa1.setup(); // extra setups ignored 7 8 MutexedAA!(string[int]) aa2; 9 aa2.setup(); 10 11 aa1[42] = "hello"; 12 aa2[42] = "world"; 13 assert(aa1 != aa2); 14 15 aa1[42] = "world"; 16 assert(aa1 == aa2); 17 18 aa2[99] = "goodbye"; 19 assert(aa1 != aa2); 20 } 21 { 22 MutexedAA!(string[int]) aa; 23 aa.setup(); 24 25 assert(!aa.has(42)); 26 aa.require(42, "hello"); 27 assert((aa[42] == "hello"), aa[42]); 28 29 bool set1; 30 assert(!aa.has(99)); 31 string world1 = aa.require(99, { set1 = true; return "world"; }()); 32 assert(set1); 33 assert((world1 == "world"), world1); 34 assert((aa[99] == "world"), aa[99]); 35 36 bool set2; 37 string world2 = aa.require(99, { set2 = true; return "goodbye"; }()); 38 assert(!set2); 39 assert((world2 != "goodbye"), world2); 40 assert((aa[99] != "goodbye"), aa[99]); 41 } 42 { 43 import std.concurrency : Tid, send, spawn; 44 import std.conv : to; 45 import core.time : MonoTime, seconds; 46 47 static immutable timeout = 1.seconds; 48 49 static void workerFn(MutexedAA!(string[int]) aa) 50 { 51 static void _assert( 52 lazy bool condition, 53 const string message = "unittest failure", 54 const string file = __FILE__, 55 const uint line = __LINE__) 56 { 57 if (!condition) 58 { 59 import std.format : format; 60 import std.stdio : writeln; 61 62 enum pattern = "core.exception.AssertError@%s(%d): %s"; 63 immutable assertMessage = pattern.format(file, line, message); 64 writeln(assertMessage); 65 assert(0, assertMessage); 66 } 67 } 68 69 _assert(aa.isReady, "MutexedAA passed to worker was not set up properly"); 70 71 bool halt; 72 73 while (!halt) 74 { 75 import std.concurrency : OwnerTerminated, receiveTimeout; 76 import std.variant : Variant; 77 78 immutable receivedSomething = receiveTimeout(timeout, 79 (bool _) 80 { 81 halt = true; 82 }, 83 (int i) 84 { 85 _assert((aa.length == i-1), "Incorrect MutexedAA length before insert"); 86 aa[i] = i.to!string; 87 _assert((aa.length == i), "Incorrect MutexedAA length after insert"); 88 }, 89 (OwnerTerminated _) 90 { 91 halt = true; 92 }, 93 (Variant v) 94 { 95 import std.stdio : writeln; 96 writeln("MutexedAA unit test worker received unknown message: ", v); 97 halt = true; 98 } 99 ); 100 101 if (!receivedSomething) return; 102 } 103 } 104 105 MutexedAA!(string[int]) aa; 106 aa.setup(); 107 108 auto worker = spawn(&workerFn, aa); 109 immutable start = MonoTime.currTime; 110 111 foreach (/*immutable*/ i; 1..10) // start at 1 to enable length checks in worker 112 { 113 worker.send(i); 114 aa.setup(); 115 auto present = aa.has(i); 116 117 while (!present && (MonoTime.currTime - start) < timeout) 118 { 119 import core.thread : Thread; 120 import core.time : msecs; 121 122 static immutable briefWait = 2.msecs; 123 Thread.sleep(briefWait); 124 present = aa.has(i); 125 } 126 127 assert(present, "MutexedAA unit test worker timed out responding to " ~ i.to!string); 128 assert((aa[i] == i.to!string), aa[i]); 129 } 130 131 worker.send(true); // halt 132 } 133 { 134 import std.algorithm.searching : canFind; 135 136 MutexedAA!(int[int]) aa; 137 aa.setup(); 138 139 aa[1] = 42; 140 aa[2] = 99; 141 assert(aa.length == 2); 142 143 auto keys = aa.keys; 144 assert(keys.canFind(1)); 145 assert(keys.canFind(2)); 146 assert(!keys.canFind(3)); 147 148 auto values = aa.values; 149 assert(values.canFind(42)); 150 assert(values.canFind(99)); 151 assert(!values.canFind(0)); 152 153 assert(aa.get(1, 0) == 42); 154 assert(aa.get(2, 0) == 99); 155 assert(aa.get(0, 0) == 0); 156 assert(aa.get(3, 999) == 999); 157 } 158 { 159 MutexedAA!(int[int]) aa1; 160 aa1.setup(); 161 162 aa1[1] = 42; 163 aa1[2] = 99; 164 165 int[int] aa2; 166 167 aa2[1] = 42; 168 assert(aa1 != aa2); 169 170 aa2[2] = 99; 171 assert(aa1 == aa2); 172 173 ++aa2[2]; 174 assert(aa2[2] == 100); 175 176 aa2[1] += 1; 177 assert(aa2[1] == 43); 178 179 aa2[1] -= 1; 180 assert(aa2[1] == 42); 181 182 aa2[1] *= 2; 183 assert(aa2[1] == 84); 184 185 int i = -aa2[1]; 186 assert(i == -84); 187 } 188 { 189 MutexedAA!(char[][int]) aa; 190 aa.setup(); 191 192 aa[1] ~= 'a'; 193 aa[1] ~= 'b'; 194 aa[1] ~= 'c'; 195 assert(aa[1] == "abc".dup); 196 197 aa[1] ~= [ 'd', 'e', 'f' ]; 198 assert(aa[1] == "abcdef".dup); 199 } 200 { 201 MutexedAA!(int[int]) aa; 202 aa.setup(); 203 204 immutable key = aa.uniqueKey; 205 assert(key > 0); 206 207 assert(aa.has(key)); 208 assert(aa[key] == int.init); 209 aa.remove(key); 210 assert(!aa.has(key)); 211 212 immutable key2 = aa.uniqueKey(1, 2, -1); 213 assert(key2 == 1); 214 assert(aa.has(key2)); 215 assert(aa[key2] == -1); 216 } 217 static if (__VERSION__ >= 2088L) 218 {{ 219 MutexedAA!(int[int]) aa; 220 aa.setup(); 221 222 assert(!aa.has(1)); 223 224 aa.update(1, 225 () => 42, 226 (int i) => i + 1); 227 assert(aa.has(1)); 228 assert(aa[1] == 42); 229 230 aa.update(1, 231 () => 42, 232 (int i) => i + 1); 233 assert(aa[1] == 43); 234 }}
An associative array and a Mutex. Wraps associative array operations in mutex locks.