1 /++
2     Containers.
3 
4     Example:
5     ---
6     {
7         Buffer!string buffer;
8 
9         buffer.put("abc");
10         buffer.put("def");
11         assert(!buffer.empty);
12         assert(buffer.front == "abc");
13         buffer.popFront();
14         assert(buffer.front == "def");
15         buffer.popFront();
16         assert(buffer.empty);
17     }
18     {
19         Buffer!(char, Yes.dynamic, 3) buffer;
20 
21         assert(!buffer.buf.length);
22         buffer ~= 'a';
23         assert(buffer.buf.length == 3);
24         buffer ~= 'b';
25         buffer ~= 'c';
26         assert(buffer.length == 3);
27         buffer ~= 'd';
28         assert(buffer.buf.length > 3);
29         assert(buffer[0..5] == "abcd");
30         buffer.clear();
31         assert(buffer.empty);
32     }
33     {
34         RehashingAA!(int[string]) aa;
35         aa.minimumNeededForRehash = 2;
36 
37         aa["abc"] = 123;
38         aa["def"] = 456;
39         assert((aa.newKeysSinceLastRehash == 2), aa.newKeysSinceLastRehash.to!string);
40         assert((aa.numRehashes == 0), aa.numRehashes.to!string);
41         aa["ghi"] = 789;
42         assert((aa.numRehashes == 1), aa.numRehashes.to!string);
43         assert((aa.newKeysSinceLastRehash == 0), aa.newKeysSinceLastRehash.to!string);
44         aa.rehash();
45         assert((aa.numRehashes == 2), aa.numRehashes.to!string);
46 
47         auto realAA = cast(int[string])aa;
48         assert("abc" in realAA);
49         assert("def" in realAA);
50 
51         auto alsoRealAA = aa.aaOf;
52         assert("ghi" in realAA);
53         assert("jkl" !in realAA);
54 
55         auto aa2 = aa.dup;
56         aa2["jkl"] = 123;
57         assert("jkl" in aa2);
58         assert("jkl" !in aa);
59     }
60     {
61         MutexedAA!(string[int]) aa;
62         aa.setup();  // important!
63 
64         aa[1] = "one";
65         aa[2] = "two";
66         aa[3] = "three";
67 
68         auto hasOne = aa.has(1);
69         assert(hasOne);
70         assert(aa[1] == "one");
71 
72         assert(aa[2] == "two");
73 
74         auto three = aa.get(3);
75         assert(three == "three");
76 
77         auto four = aa.get(4, "four");
78         assert(four == "four");
79 
80         auto five = aa.require(5, "five");
81         assert(five == "five");
82         assert(aa[5] == "five");
83 
84         auto keys = aa.keys;
85         assert(keys.canFind(1));
86         assert(keys.canFind(5));
87         assert(!keys.canFind(6));
88 
89         auto values = aa.values;
90         assert(values.canFind("one"));
91         assert(values.canFind("four"));
92         assert(!values.canFind("six"));
93 
94         aa.rehash();
95     }
96     ---
97 
98     Copyright: [JR](https://github.com/zorael)
99     License: [Boost Software License 1.0](https://www.boost.org/users/license.html)
100 
101     Authors:
102         [JR](https://github.com/zorael)
103  +/
104 module lu.container;
105 
106 private:
107 
108 import std.typecons : Flag, No, Yes;
109 
110 public:
111 
112 
113 // Buffer
114 /++
115     Simple buffer/queue for storing and fetching items of any type `T`.
116     Does not use manual memory allocation.
117 
118     It can use a static array internally to store elements on the stack, which
119     imposes a hard limit on how many items can be added, or a dynamic heap one
120     with a resizable buffer.
121 
122     Example:
123     ---
124     Buffer!(string, No.dynamic, 16) buffer;
125 
126     buffer.put("abc");
127     buffer ~= "def";
128     assert(!buffer.empty);
129     assert(buffer.front == "abc");
130     buffer.popFront();
131     assert(buffer.front == "def");
132     buffer.popFront();
133     assert(buffer.empty);
134     ---
135 
136     Params:
137         T = Buffer item type.
138         dynamic = Whether to use a dynamic array whose size can be grown at
139             runtime, or to use a static array with a fixed size. Trying to add
140             more elements than there is room for will cause an assert.
141             Defaults to `No.dynamic`; a static array.
142         originalSize = How many items to allocate space for. If `No.dynamic` was
143             passed it will assert if you attempt to store anything past this amount.
144  +/
145 struct Buffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 128)
146 {
147 pure nothrow:
148     static if (dynamic)
149     {
150         /++
151             By how much to grow the buffer when we reach the end of it.
152          +/
153         private enum growthFactor = 1.5;
154 
155         /++
156             Internal buffer dynamic array.
157          +/
158         T[] buf;
159 
160         /++
161             Variable buffer size.
162          +/
163         size_t bufferSize;
164     }
165     else
166     {
167         /++
168             Internal buffer static array.
169          +/
170         T[bufferSize] buf;
171 
172         /++
173             Static buffer size.
174          +/
175         alias bufferSize = originalSize;
176     }
177 
178     /++
179         Current position in the array.
180      +/
181     ptrdiff_t pos;
182 
183     /++
184         Position of last entry in the array.
185      +/
186     ptrdiff_t end;
187 
188     static if (dynamic)
189     {
190         // put
191         /++
192             Append an item to the end of the buffer.
193 
194             If it would be put beyond the end of the buffer, it will be resized to fit.
195 
196             Params:
197                 more = Item to add.
198          +/
199         void put(/*const*/ T more) pure @safe nothrow
200         {
201             if (end == bufferSize)
202             {
203                 bufferSize = !bufferSize ? originalSize : cast(size_t)(bufferSize * growthFactor);
204                 buf.length = bufferSize;
205             }
206 
207             buf[end++] = more;
208         }
209     }
210     else
211     {
212         // put
213         /++
214             Append an item to the end of the buffer.
215 
216             If it would be put beyond the end of the buffer, it will assert.
217 
218             Params:
219                 more = Item to add.
220          +/
221         void put(/*const*/ T more) pure @safe nothrow @nogc
222         in ((end < bufferSize), '`' ~ typeof(this).stringof ~ "` buffer overflow")
223         {
224             buf[end++] = more;
225         }
226     }
227 
228     static if (dynamic)
229     {
230         // reserve
231         /++
232             Reserves enough room for the specified number of elements. If there
233             is already enough room, nothing is done. Otherwise the buffer is grown.
234 
235             Params:
236                 reserveSize = Number of elements to reserve size for.
237          +/
238         void reserve(const size_t reserveSize) pure @safe nothrow
239         {
240             if (bufferSize < reserveSize)
241             {
242                 bufferSize = reserveSize;
243                 buf.length = bufferSize;
244             }
245         }
246     }
247 
248     // opOpAssign
249     /++
250         Implements `buf ~= someT` (appending) by wrapping `put`.
251 
252         Params:
253             op = Operation type, here specialised to "`~`".
254             more = Item to add.
255      +/
256     void opOpAssign(string op : "~")(/*const*/ T more) pure @safe nothrow
257     {
258         return put(more);
259     }
260 
261     // front
262     /++
263         Fetches the item at the current position of the buffer.
264 
265         Returns:
266             An item T.
267      +/
268     ref auto front() inout pure @safe nothrow @nogc
269     in ((end > 0), '`' ~ typeof(this).stringof ~ "` buffer underrun")
270     {
271         return buf[pos];
272     }
273 
274     // popFront
275     /++
276         Advances the current position to the next item in the buffer.
277      +/
278     void popFront() pure @safe nothrow @nogc
279     {
280         if (++pos == end) reset();
281     }
282 
283     // length
284     /++
285         Returns what amounts to the current length of the buffer; the distance
286         between the current position `pos` and the last element `end`.
287 
288         Returns:
289             The buffer's current length.
290      +/
291     auto length() const inout
292     {
293         return (end - pos);
294     }
295 
296     // empty
297     /++
298         Returns whether or not the container is considered empty.
299 
300         Mind that the buffer may well still contain old contents. Use `clear`
301         to zero it out.
302 
303         Returns:
304             `true` if there are items available to get via `front`,
305             `false` if not.
306      +/
307     auto empty() const inout
308     {
309         return (end == 0);
310     }
311 
312     // reset
313     /++
314         Resets the array positions, effectively soft-emptying the buffer.
315 
316         The old elements' values are still there, they will just be overwritten
317         as the buffer is appended to.
318      +/
319     void reset() pure @safe nothrow @nogc
320     {
321         pos = 0;
322         end = 0;
323     }
324 
325     // clear
326     /++
327         Zeroes out the buffer's elements, getting rid of old contents.
328      +/
329     void clear() pure @safe nothrow @nogc
330     {
331         reset();
332         buf[] = T.init;
333     }
334 }
335 
336 ///
337 unittest
338 {
339     {
340         Buffer!(bool, No.dynamic, 4) buffer;
341 
342         assert(buffer.empty);
343         buffer.put(true);
344         buffer.put(false);
345         assert(buffer.length == 2);
346         buffer.put(true);
347         buffer.put(false);
348 
349         assert(!buffer.empty);
350         assert(buffer.front == true);
351         buffer.popFront();
352         assert(buffer.front == false);
353         buffer.popFront();
354         assert(buffer.front == true);
355         buffer.popFront();
356         assert(buffer.front == false);
357         buffer.popFront();
358         assert(buffer.empty);
359         assert(buffer.buf == [ true, false, true, false ]);
360         buffer.put(false);
361         assert(buffer.buf == [ false, false, true, false ]);
362         buffer.reset();
363         assert(buffer.empty);
364         buffer.clear();
365         assert(buffer.buf == [ false, false, false, false ]);
366     }
367     {
368         Buffer!(string, No.dynamic, 4) buffer;
369 
370         assert(buffer.empty);
371         buffer.put("abc");
372         buffer.put("def");
373         buffer.put("ghi");
374 
375         assert(!buffer.empty);
376         assert(buffer.front == "abc");
377         buffer.popFront();
378         assert(buffer.front == "def");
379         buffer.popFront();
380         buffer.put("JKL");
381         assert(buffer.front == "ghi");
382         buffer.popFront();
383         assert(buffer.front == "JKL");
384         buffer.popFront();
385         assert(buffer.empty);
386         assert(buffer.buf == [ "abc", "def", "ghi", "JKL" ]);
387         buffer.put("MNO");
388         assert(buffer.buf == [ "MNO", "def", "ghi", "JKL" ]);
389         buffer.clear();
390         assert(buffer.buf == [ string.init, string.init, string.init, string.init ]);
391     }
392     {
393         Buffer!(char, No.dynamic, 64) buffer;
394         buffer ~= 'a';
395         buffer ~= 'b';
396         buffer ~= 'c';
397         assert(buffer.buf[0..3] == "abc");
398 
399         foreach (char_; buffer)
400         {
401             assert((char_ == 'a') || (char_ == 'b') || (char_ == 'c'));
402         }
403     }
404     {
405         Buffer!(int, Yes.dynamic, 3) buffer;
406         assert(!buffer.buf.length);
407         buffer ~= 1;
408         assert(buffer.buf.length == 3);
409         buffer ~= 2;
410         buffer ~= 3;
411         assert(buffer.front == 1);
412         buffer.popFront();
413         assert(buffer.front == 2);
414         buffer.popFront();
415         assert(buffer.front == 3);
416         buffer.popFront();
417         assert(buffer.empty);
418         buffer.reserve(64);
419         assert(buffer.buf.length == 64);
420         buffer.reserve(63);
421         assert(buffer.buf.length == 64);
422     }
423     {
424         Buffer!(char, No.dynamic, 4) buffer;
425         buffer ~= 'a';
426         buffer ~= 'b';
427         buffer ~= 'c';
428         buffer ~= 'd';
429         assert(buffer.buf == "abcd");
430         assert(buffer.length == 4);
431         buffer.reset();
432         assert(buffer.buf == "abcd");
433         buffer.clear();
434         assert(buffer.buf == typeof(buffer.buf).init);
435     }
436 }
437 
438 
439 // CircularBuffer
440 /++
441     Simple circular-ish buffer for storing items of type `T` that discards elements
442     when the maximum size is reached. Does not use manual memory allocation.
443 
444     It can use a static array internally to store elements on the stack, which
445     imposes a hard limit on how many items can be added, or a dynamic heap one
446     with a resizable buffer.
447 
448     Example:
449     ---
450     CircularBuffer!(int, Yes.dynamic) buf;
451     buf.resize(3);
452     buf.put(1);
453     buf.put(2);
454     buf.put(3);
455     but.put(4);
456     assert(buf.front == 4);
457     assert(buf.buf == [ 4, 2, 3 ]);
458     ---
459 
460     Params:
461         T = Buffer item type.
462         dynamic = Whether to use a dynamic array whose size can be grown at
463             runtime, or to use a static array with a fixed size. Trying to add
464             more elements than there is room for will wrap around and discard elements.
465             Defaults to `No.dynamic`; a static buffer.
466         originalSize = How many items to allocate space for in the case of a
467             static array.
468  +/
469 struct CircularBuffer(T, Flag!"dynamic" dynamic = No.dynamic, size_t originalSize = 16)
470 if (originalSize > 1)
471 {
472 private:
473     static if (dynamic)
474     {
475         // buf
476         /++
477             Internal buffer dynamic array.
478          +/
479         T[] buf;
480     }
481     else
482     {
483         // buf
484         /++
485             Internal buffer static array.
486          +/
487         T[originalSize] buf;
488     }
489 
490     // head
491     /++
492         Head position in the internal buffer.
493      +/
494     size_t head;
495 
496     // tail
497     /++
498         Tail position in the internal buffer.
499      +/
500     size_t tail;
501 
502     // caughtUp
503     /++
504         Whether or not [head] and [tail] point to the same position in the
505         context of a circular array.
506      +/
507     bool caughtUp;
508 
509     // initialised
510     /++
511         Whether or not at least one element has been added.
512      +/
513     bool initialised;
514 
515 public:
516     // front
517     /++
518         Returns the front element.
519 
520         Returns:
521             An item T.
522      +/
523     ref auto front() inout
524     in ((buf.length > 0), "Tried to get `front` from a zero-sized " ~ typeof(this).stringof)
525     {
526         return buf[head];
527     }
528 
529     // put
530     /++
531         Append an item to the buffer.
532 
533         If it would be put beyond the end of the buffer, it will wrap around and
534         truncate old values.
535 
536         Params:
537             item = Item to add.
538      +/
539     void put(T item) pure @safe @nogc nothrow
540     in ((buf.length > 0), "Tried to `put` something into a zero-sized " ~ typeof(this).stringof)
541     {
542         if (initialised) ++head %= buf.length;
543         buf[head] = item;
544         tail = head;
545         caughtUp = true;
546         initialised = true;
547     }
548 
549     // popFront
550     /++
551         Advances the current position to the next item in the buffer.
552      +/
553     void popFront() pure @safe @nogc nothrow
554     in ((buf.length > 0), "Tried to `popFront` a zero-sized " ~ typeof(this).stringof)
555     in (!empty, "Tried to `popFront` an empty " ~ typeof(this).stringof)
556     {
557         if (head == 0)
558         {
559             head = (buf.length + (-1));
560             caughtUp = false;
561         }
562         else
563         {
564             --head;
565         }
566     }
567 
568     static if (dynamic)
569     {
570         // resize
571         /++
572             Resizes the internal buffer to a specified size.
573 
574             Params:
575                 size = New size.
576          +/
577         void resize(const size_t size) pure @safe nothrow
578         {
579             buf.length = size;
580             if (head >= buf.length) head = buf.length +(-1);
581             if (tail >= buf.length) tail = buf.length +(-1);
582         }
583     }
584 
585     // opOpAssign
586     /++
587         Implements `buf ~= someT` (appending) by wrapping `put`.
588 
589         Params:
590             op = Operation type, here specialised to "`~`".
591             more = Item to add.
592      +/
593     void opOpAssign(string op : "~")(const T more) pure @safe @nogc nothrow
594     {
595         return put(more);
596     }
597 
598     // size
599     /++
600         Returns the size of the internal buffer.
601 
602         Returns:
603             Internal buffer size.
604      +/
605     auto size() const inout
606     {
607         return buf.length;
608     }
609 
610     // empty
611     /++
612         Returns whether or not the container is considered empty.
613 
614         Mind that the buffer may well still contain old contents. Use `clear`
615         to zero it out.
616 
617         Returns:
618             `true` if there are items available to get via `front`,
619             `false` if not.
620      +/
621     auto empty() const inout
622     {
623         return !caughtUp && (head == tail);
624     }
625 
626     // save
627     /++
628         Implements Range `save`.
629 
630         Returns:
631             A shallow copy of the container.
632      +/
633     auto save()
634     {
635         return this;
636     }
637 
638     // dup
639     /++
640         Makes a deep(er) duplicate of the container.
641 
642         Returns:
643             A copy of the current container with the internal buffer explicitly `.dup`ed.
644      +/
645     auto dup()
646     {
647         auto copy = this;
648 
649         static if (dynamic)
650         {
651             copy.buf = this.buf.dup;
652         }
653 
654         return copy;
655     }
656 
657     // clear
658     /++
659         Resets the buffer pointers but doesn't clear the contents.
660      +/
661     void reset() pure @safe @nogc nothrow
662     {
663         head = 0;
664         tail = 0;
665     }
666 
667     // clear
668     /++
669         Zeroes out the buffer's elements, getting rid of old contents.
670      +/
671     void clear() pure @safe @nogc nothrow
672     {
673         reset();
674         buf[] = T.init;
675     }
676 }
677 
678 ///
679 unittest
680 {
681     import std.conv : text;
682 
683     {
684         CircularBuffer!(int, Yes.dynamic) buf;
685         buf.resize(3);
686 
687         buf.put(1);
688         assert((buf.front == 1), buf.front.text);
689         buf.put(2);
690         assert((buf.front == 2), buf.front.text);
691         buf.put(3);
692         assert((buf.front == 3), buf.front.text);
693         buf ~= 4;
694         assert((buf.front == 4), buf.front.text);
695         assert((buf.buf[] == [ 4, 2, 3 ]), buf.buf.text);
696         buf ~= 5;
697         assert((buf.front == 5), buf.front.text);
698         buf ~= 6;
699         assert((buf.front == 6), buf.front.text);
700         assert((buf.buf[] == [ 4, 5, 6 ]), buf.buf.text);
701         buf.popFront();
702         buf.popFront();
703         buf.popFront();
704         assert(buf.empty);
705     }
706     {
707         CircularBuffer!(int, No.dynamic, 3) buf;
708         //buf.resize(3);
709 
710         buf.put(1);
711         assert((buf.front == 1), buf.front.text);
712         buf.put(2);
713         assert((buf.front == 2), buf.front.text);
714         buf.put(3);
715         assert((buf.front == 3), buf.front.text);
716         buf ~= 4;
717         assert((buf.front == 4), buf.front.text);
718         assert((buf.buf[] == [ 4, 2, 3 ]), buf.buf.text);
719         buf.popFront();
720         buf.popFront();
721         buf.popFront();
722         assert(buf.empty);
723     }
724     {
725         CircularBuffer!(int, No.dynamic, 2) buf;
726         //buf.resize(2);
727 
728         buf.put(1);
729         assert((buf.front == 1), buf.front.text);
730         buf.put(2);
731         assert((buf.front == 2), buf.front.text);
732         buf.put(3);
733         assert((buf.front == 3), buf.front.text);
734         buf ~= 4;
735         assert((buf.front == 4), buf.front.text);
736         assert((buf.buf[] == [ 3, 4 ]), buf.buf.text);
737         buf.popFront();
738         buf.popFront();
739         assert(buf.empty);
740         //buf.popFront();  // AssertError
741     }
742     {
743         CircularBuffer!(int, No.dynamic, 2) buf;
744         //buf.resize(2);
745 
746         buf.put(1);
747         assert((buf.front == 1), buf.front.text);
748         buf.put(2);
749         assert((buf.front == 2), buf.front.text);
750         buf.put(3);
751         assert((buf.front == 3), buf.front.text);
752         buf ~= 4;
753         assert((buf.front == 4), buf.front.text);
754         assert((buf.buf[] == [ 3, 4 ]), buf.buf.text);
755         auto savedBuf = buf.save();
756         buf.popFront();
757         buf.popFront();
758         assert(buf.empty);
759         assert((savedBuf.front == 4), savedBuf.front.text);
760         savedBuf.popFront();
761         auto savedBuf2 = savedBuf.save();
762         savedBuf.popFront();
763         assert(savedBuf.empty);
764         assert((savedBuf2.front == 3), savedBuf2.front.text);
765         savedBuf2.popFront();
766         assert(savedBuf2.empty);
767     }
768 }
769 
770 
771 // RehashingAA
772 /++
773     A wrapper around a native associative array that you can controllably set to
774     automatically rehash as entries are added.
775 
776     Params:
777         AA = Associative array type.
778         V = Value type.
779         K = Key type.
780  +/
781 struct RehashingAA(AA : V[K], V, K)
782 {
783 private:
784     import std.range.primitives : ElementEncodingType;
785     import std.traits : isIntegral;
786 
787     /++
788         Internal associative array.
789      +/
790     AA aa;
791 
792     /++
793         The number of times this instance has rehashed itself. Private value.
794      +/
795     uint _numRehashes;
796 
797     /++
798         The number of new entries that has been added since the last rehash. Private value.
799      +/
800     uint _newKeysSinceLastRehash;
801 
802     /++
803         The number of keys (and length of the array) when the last rehash took place.
804         Private value.
805      +/
806     size_t _lengthAtLastRehash;
807 
808 public:
809     /++
810         The minimum number of additions needed before the first rehash takes place.
811      +/
812     uint minimumNeededForRehash = 64;
813 
814     /++
815         The modifier by how much more entries must be added before another rehash
816         takes place, with regards to the current [RehashingAA.aa|aa] length.
817 
818         A multiplier of `2.0` means the associative array will be rehashed as
819         soon as its length doubles in size. Must be more than 1.
820      +/
821     double rehashThresholdMultiplier = 1.5;
822 
823     // opIndexAssign
824     /++
825         Assigns a value into the internal associative array. If it created a new
826         entry, then call [maybeRehash] to bump the internal counter and maybe rehash.
827 
828         Example:
829         ---
830         RehashingAA!(int[string]) aa;
831         aa["abc"] = 123;
832         aa["def"] = 456;
833         ---
834 
835         Params:
836             value = Value.
837             key = Key.
838      +/
839     void opIndexAssign(V value, K key)
840     {
841         if (auto existing = key in aa)
842         {
843             *existing = value;
844         }
845         else
846         {
847             aa[key] = value;
848             maybeRehash();
849         }
850     }
851 
852     // opIndex
853     /++
854         Returns the value for the passed key in the internal associative array.
855 
856         Example:
857         ---
858         RehashingAA!(int[string]) aa;
859         aa["abc"] = 123;
860         writeln(aa["abc"]);  // 123
861         ---
862 
863         Params:
864             key = Key.
865 
866         Returns:
867             The value for the key `key`.
868      +/
869     ref auto opIndex(K key)
870     {
871         return aa[key];
872     }
873 
874     // opIndexUnary
875     /++
876         Performs a unary operation on a value in the internal associative array.
877 
878         Example:
879         ---
880         RehashingAA!(int[string]) aa;
881         aa["abc"] = 123;
882         writeln(-aa["abc"]);  // -123
883         ---
884 
885         Params:
886             op = Unary operation as a string.
887             key = Key.
888 
889         Returns:
890             The result of the operation.
891      +/
892     ref auto opIndexUnary(string op)(K key)
893     {
894         mixin("return " ~ op ~ "aa[key];");
895     }
896 
897     // opAssign
898     /++
899         Inherit a native associative array into [RehashingAA.aa|aa].
900 
901         Example:
902         ---
903         RehashingAA!(int[string]) aa;
904         int[string] nativeAA;
905 
906         nativeAA["abc"] = 123;
907         aa = nativeAA;
908         assert(aa["abc"] == 123);
909         ---
910 
911         Params:
912             aa = Other associative array.
913      +/
914     void opAssign(V[K] aa)
915     {
916         this.aa = aa;
917         this.rehash();
918         _numRehashes = 0;
919     }
920 
921     // opIndexOpAssign
922     /++
923         Performs an assingment operation on a value in the internal associative array.
924 
925         Example:
926         ---
927         RehashingAA!(int[int]) aa;
928         aa[1] = 42;
929         aa[1] += 1;
930         assert(aa[1] == 43);
931 
932         aa[1] *= 2;
933         assert(aa[1] == 86);
934         ---
935 
936         Params:
937             op = Assignment operation as a string.
938             value = Value to assign.
939             key = Key.
940      +/
941     void opIndexOpAssign(string op, U)(U value, K key)
942     if (is(U == V) || is(U == ElementEncodingType!V))
943     {
944         mixin("aa[key] " ~ op ~ "= value;");
945         maybeRehash();
946     }
947 
948     // opCast
949     /++
950         Allows for casting this into the base associative array type.
951 
952         Example:
953         ---
954         RehashingAA!(int[string]) aa;
955         aa["abc"] = 123;
956         auto native = cast(int[string])aa;
957         assert(native["abc"] == 123);
958         ---
959 
960         Params:
961             T = Type to cast to, here the same as the type of [RehashingAA.aa|aa].
962 
963         Returns:
964             The internal associative array.
965      +/
966     ref auto opCast(T : AA)() inout
967     {
968         return aa;
969     }
970 
971     // aaOf
972     /++
973         Returns the internal associative array, for when the wrapper is insufficient.
974 
975         Example:
976         ---
977         RehashingAA!(int[string]) aa;
978         static assert(is(typeof(aa.aaOf) == int[string]));
979         ---
980 
981         Returns:
982             The internal associative array.
983      +/
984     ref auto aaOf() inout
985     {
986         return aa;
987     }
988 
989     // remove
990     /++
991         Removes a key from the [RehashingAA.aa|aa] associative array by merely
992         invoking `.remove`.
993 
994         Example:
995         ---
996         RehashingAA!(int[string]) aa;
997         aa["abc"] = 123;
998         assert("abc" in aa);
999 
1000         aa.remove("abc");
1001         assert("abc" !in aa);
1002         ---
1003 
1004         Params:
1005             key = The key to remove.
1006 
1007         Returns:
1008             Whatever `aa.remove(key)` returns.
1009      +/
1010     auto remove(K key)
1011     {
1012         //scope(exit) maybeRehash();
1013         return aa.remove(key);
1014     }
1015 
1016     // maybeRehash
1017     /++
1018         Bumps the internal counter of new keys since the last rehash, and depending
1019         on the resulting value of it, maybe rehashes.
1020 
1021         Returns:
1022             `true` if the associative array was rehashed; `false` if not.
1023      +/
1024     auto maybeRehash()
1025     {
1026         if (++_newKeysSinceLastRehash > minimumNeededForRehash)
1027         {
1028             if (aa.length > (_lengthAtLastRehash * rehashThresholdMultiplier))
1029             {
1030                 this.rehash();
1031                 return true;
1032             }
1033         }
1034 
1035         return false;
1036     }
1037 
1038     // clear
1039     /++
1040         Clears the internal associative array and all counters.
1041      +/
1042     void clear()
1043     {
1044         aa.clear();
1045         _newKeysSinceLastRehash = 0;
1046         _lengthAtLastRehash = 0;
1047         _numRehashes = 0;
1048     }
1049 
1050     // rehash
1051     /++
1052         Rehashes the internal associative array, bumping the rehash counter and
1053         zeroing the keys-added counter. Additionally invokes the [onRehashDg] delegate.
1054 
1055         Returns:
1056             A reference to the rehashed internal array.
1057      +/
1058     ref auto rehash() @system
1059     {
1060         scope(exit) if (onRehashDg) onRehashDg(aa);
1061         _lengthAtLastRehash = aa.length;
1062         _newKeysSinceLastRehash = 0;
1063         ++_numRehashes;
1064         aa.rehash();
1065         return this;
1066     }
1067 
1068     // numRehashes
1069     /++
1070         The number of times this instance has rehashed itself. Accessor.
1071 
1072         Returns:
1073             The number of times this instance has rehashed itself.
1074      +/
1075     auto numRehashes() inout
1076     {
1077         return _numRehashes;
1078     }
1079 
1080     // numKeysAddedSinceLastRehash
1081     /++
1082         The number of new entries that has been added since the last rehash. Accessor.
1083 
1084         Returns:
1085             The number of new entries that has been added since the last rehash.
1086      +/
1087     auto newKeysSinceLastRehash() inout
1088     {
1089         return _newKeysSinceLastRehash;
1090     }
1091 
1092     // opBinaryRight
1093     /++
1094         Wraps `key in aa` to the internal associative array.
1095 
1096         Example:
1097         ---
1098         RehashingAA!(int[string]) aa;
1099         aa["abc"] = 123;
1100         assert("abc" in aa);
1101         ---
1102 
1103         Params:
1104             op = Operation, here "in".
1105             key = Key.
1106 
1107         Returns:
1108             A pointer to the value of the key passed, or `null` if it isn't in
1109             the associative array
1110      +/
1111     auto opBinaryRight(string op : "in")(K key) inout
1112     {
1113         return key in aa;
1114     }
1115 
1116     // byValue
1117     /++
1118         Wraps the internal associative array's `byValue` function.
1119 
1120         Example:
1121         ---
1122         RehashingAA!(int[string]) aa;
1123         aa["abc"] = 123;
1124         aa["def"] = 456;
1125         aa["ghi"] = 789;
1126 
1127         foreach (value; aa.byValue)
1128         {
1129             writeln(value);
1130         }
1131         ---
1132 
1133         Returns:
1134             The Voldemort returned from the associative array's `byValue` function.
1135      +/
1136     auto byValue() inout
1137     {
1138         return aa.byValue();
1139     }
1140 
1141     // byKey
1142     /++
1143         Wraps the internal associative array's `byKey` function.
1144 
1145         Example:
1146         ---
1147         RehashingAA!(int[string]) aa;
1148         aa["abc"] = 123;
1149         aa["def"] = 456;
1150         aa["ghi"] = 789;
1151 
1152         foreach (key; aa.byKey)
1153         {
1154             writeln(key);
1155         }
1156         ---
1157 
1158         Returns:
1159             The Voldemort returned from the associative array's `byKey` function.
1160      +/
1161     auto byKey() inout
1162     {
1163         return aa.byKey();
1164     }
1165 
1166     // values
1167     /++
1168         Wraps the internal associative array's `values` function.
1169 
1170         Example:
1171         ---
1172         RehashingAA!(int[string]) aa;
1173         aa["abc"] = 123;
1174         aa["def"] = 456;
1175         aa["ghi"] = 789;
1176 
1177         auto values = aa.values;  // allocate it once
1178 
1179         // Order cannot be relied upon
1180         foreach (val; [ 123, 456, 789 ])
1181         {
1182             import std.algorithm.searching : canFind;
1183             assert(values.canFind(val));
1184         }
1185         ---
1186 
1187         Returns:
1188             A new dynamic array of all values, as returned by the associative array's
1189             `values` function.
1190      +/
1191     auto values() const
1192     {
1193         return aa.values;
1194     }
1195 
1196     // keys
1197     /++
1198         Wraps the internal associative array's `keys` function.
1199 
1200         Example:
1201         ---
1202         RehashingAA!(int[string]) aa;
1203         aa["abc"] = 123;
1204         aa["def"] = 456;
1205         aa["ghi"] = 789;
1206 
1207         auto keys = aa.keys;  // allocate it once
1208 
1209         // Order cannot be relied upon
1210         foreach (key; [ "abc", "def", "ghi" ])
1211         {
1212             assert(key in aa);
1213         }
1214         ---
1215 
1216         Returns:
1217             A new dynamic array of all keys, as returned by the associative array's
1218             `keys` function.
1219      +/
1220     auto keys() const
1221     {
1222         return aa.keys;
1223     }
1224 
1225     // byKeyValue
1226     /++
1227         Wraps the internal associative array's `byKeyValue` function.
1228 
1229         Example:
1230         ---
1231         RehashingAA!(int[string]) aa;
1232         aa["abc"] = 123;
1233         aa["def"] = 456;
1234         aa["ghi"] = 789;
1235 
1236         foreach (key, value; aa.byKeyValue)
1237         {
1238             writeln(key, " = ", value);
1239         }
1240         ---
1241 
1242         Returns:
1243             A new range of all key-value pairs, as returned by the associative
1244             array's `byKeyValue` function.
1245      +/
1246     auto byKeyValue() inout
1247     {
1248         return aa.byKeyValue();
1249     }
1250 
1251     // length
1252     /++
1253         Returns the length of the internal associative array.
1254 
1255         Returns:
1256             The length of the internal associative array.
1257      +/
1258     auto length() const inout
1259     {
1260         return aa.length;
1261     }
1262 
1263     // dup
1264     /++
1265         Duplicates this. Explicitly copies the internal associative array.
1266 
1267         If `copyState: false` is passed, it will not copy over the internal state
1268         such as the number of rehashes and keys added since the last rehash.
1269 
1270         Example:
1271         ---
1272         RehashingAA!(int[string]) aa;
1273         aa.minimumNeededForRehash = 2;
1274 
1275         aa["abc"] = 123;
1276         aa["def"] = 456;
1277         aa["ghi"] = 789;
1278         assert(aa.numRehashes == 1);
1279 
1280         auto aa2 = aa.dup(copyState: false);
1281         assert(aa2 == aa);
1282         assert(aa2.numRehashes == 1);
1283 
1284         auto aa3 = aa.dup;  //(copyState: false);
1285         assert(aa3 == aa);
1286         assert(aa3.numRehashes == 0);
1287         ---
1288 
1289         Params:
1290             copyState = (Optional) Whether or not to copy over the internal state.
1291 
1292         Returns:
1293             A duplicate of this object.
1294      +/
1295     auto dup(const bool copyState = false)
1296     {
1297         auto copy = copyState ?
1298             this :
1299             typeof(this).init;
1300 
1301         copy.aa = this.aa.dup;
1302         return copy;
1303     }
1304 
1305     // require
1306     /++
1307         Returns the value for the key `key`, inserting `value` lazily if it is not present.
1308 
1309         Example:
1310         ---
1311         RehashingAA!(string[int]) aa;
1312         string hello = aa.require(42, "hello");
1313         assert(hello == "hello");
1314         assert(aa[42] == "hello");
1315         ---
1316 
1317         Params:
1318             key = Key.
1319             value = Value to insert if the key is not present.
1320 
1321         Returns:
1322             The value for the key `key`, or `value` if it was not present.
1323      +/
1324     ref auto require(K key, lazy V value)
1325     {
1326         if (auto existing = key in aa)
1327         {
1328             return *existing;
1329         }
1330         else
1331         {
1332             aa[key] = value;
1333             return value;
1334         }
1335     }
1336 
1337     // get
1338     /++
1339         Retrieves the value for the key `key`, or returns the default `value`
1340         if there was none.
1341 
1342         Example:
1343         ---
1344         RehashingAA!(int[int]) aa;
1345         aa[1] = 42;
1346         aa[2] = 99;
1347 
1348         assert(aa.get(1, 0) == 42);
1349         assert(aa.get(2, 0) == 99);
1350         assert(aa.get(0, 0) == 0);
1351         assert(aa.get(3, 999) == 999);
1352 
1353         assert(0 !in aa);
1354         assert(3 !in aa);
1355         ---
1356      +/
1357     ref auto get(K key, lazy V value)
1358     {
1359         if (auto existing = key in aa)
1360         {
1361             return *existing;
1362         }
1363         else
1364         {
1365             return value;
1366         }
1367     }
1368 
1369     static if (isIntegral!K)
1370     {
1371         /++
1372             Reserves a unique key in the associative array.
1373 
1374             Note: The key type must be an integral type.
1375 
1376             Example:
1377             ---
1378             RehashingAA!(string[int]) aa;
1379 
1380             int i = aa.uniqueKey;
1381             assert(i > 0);
1382             assert(i in aa);
1383             assert(aa[i] == string.init);
1384             ---
1385 
1386             Params:
1387                 min = Optional minimum key value; defaults to `1``.
1388                 max = Optional maximum key value; defaults to `K.max`, where `K` is
1389                     the key type of the passed associative array.
1390                 value = Optional value to assign to the key; defaults to `V.init`,
1391                     where `V` is the value type of the passed associative array.
1392 
1393             Returns:
1394                 A unique key for the passed associative array, for which there is now
1395                 a value of `value`.`
1396 
1397             See_Also:
1398                 [lu.array.uniqueKey]
1399          +/
1400         auto uniqueKey()
1401             (K min = 1,
1402             K max = K.max,
1403             V value = V.init)
1404         {
1405             static import lu.array;
1406             return lu.array.uniqueKey(aa, min, max, value);
1407         }
1408     }
1409 
1410     // update
1411     /++
1412         Updates the value for the key `key` in the internal associative array,
1413         invoking the first of the passed delegate to insert a new value if it
1414         doesn't exist, or the second selegate to modify it in place if it does.
1415 
1416         Note: Doesn't compile with compilers earlier than version 2.088.
1417 
1418         Example:
1419         ---
1420         RehashingAA!(int[int]) aa;
1421 
1422         assert(1 !in aa);
1423 
1424         aa.update(1,
1425             () => 42,
1426             (int i) => i + 1);
1427         assert(aa[1] == 42);
1428 
1429         aa.update(1,
1430             () => 42,
1431             (int i) => i + 1);
1432         assert(aa[1] == 43);
1433         ---
1434 
1435         Params:
1436             key = Key.
1437             createDg = Delegate to invoke to create a new value if it doesn't exist.
1438             updateDg = Delegate to invoke to update an existing value.
1439      +/
1440     static if (__VERSION__ >= 2088L)
1441     void update(U)
1442         (K key,
1443         scope V delegate() createDg,
1444         scope U delegate(K) updateDg)
1445     if (is(U == V) || is(U == void))
1446     {
1447         .object.update(aa, key, createDg, updateDg);
1448     }
1449 
1450     // opEquals
1451     /++
1452         Implements `opEquals` for this type, comparing the internal associative
1453         array with that of another `RehashingAA`.
1454 
1455         Example:
1456         ---
1457         RehashingAA!(string[int]) aa1;
1458         aa1[1] = "one";
1459 
1460         RehashingAA!(string[int]) aa2;
1461         aa2[1] = "one";
1462         assert(aa1 == aa2);
1463 
1464         aa2[2] = "two";
1465         assert(aa1 != aa2);
1466 
1467         aa1[2] = "two";
1468         assert(aa1 == aa2);
1469         ---
1470 
1471         Params:
1472             other = Other `RehashingAA` whose internal associative array to compare
1473                 with the one of this instance.
1474 
1475         Returns:
1476             `true` if the internal associative arrays are equal; `false` if not.
1477      +/
1478     auto opEquals(typeof(this) other)
1479     {
1480         return (aa == other.aa);
1481     }
1482 
1483     // opEquals
1484     /++
1485         Implements `opEquals` for this type, comparing the internal associative
1486         array with a different one.
1487 
1488         Example:
1489         ---
1490         RehashingAA!(string[int]) aa1;
1491         aa1[1] = "one";
1492         aa1[2] = "two";
1493 
1494         string[int] aa2;
1495         aa2[1] = "one";
1496 
1497         assert(aa1 != aa2);
1498 
1499         aa2[2] = "two";
1500         assert(aa1 == aa2);
1501         ---
1502 
1503         Params:
1504             other = Other associative array to compare the internal one with.
1505 
1506         Returns:
1507             `true` if the internal associative arrays are equal; `false` if not.
1508      +/
1509     auto opEquals(AA other)
1510     {
1511         return (aa == other);
1512     }
1513 
1514     // this
1515     /++
1516         Constructor.
1517 
1518         Params:
1519             aa = Associative arary to inherit. Taken by reference for now.
1520      +/
1521     this(AA aa) pure @safe nothrow @nogc
1522     {
1523         this.aa = aa;
1524     }
1525 
1526     // onRehashDg
1527     /++
1528         Delegate called when rehashing takes place.
1529 
1530         Example:
1531         ---
1532         uint counter;
1533 
1534         void dg(ref int[string] aa)
1535         {
1536             ++counter;
1537             writeln("Rehashed!");
1538         }
1539 
1540         RehashingAA!(int[string]) aa;
1541         aa.onRehashDg = &dg;
1542         aa.minimumNeededForRehash = 2;
1543 
1544         aa["abc"] = 123;
1545         aa["def"] = 456;
1546         aa["ghi"] = 789;
1547 
1548         assert(aa.numRehashes == 1);
1549         assert(counter == 1);
1550         ---
1551      +/
1552     void delegate(ref AA) @system onRehashDg;
1553 }
1554 
1555 ///
1556 unittest
1557 {
1558     import std.conv : to;
1559 
1560     {
1561         uint counter;
1562 
1563         void dg(ref int[string] aa)
1564         {
1565             ++counter;
1566         }
1567 
1568         RehashingAA!(int[string]) aa;
1569         aa.onRehashDg = &dg;
1570         aa.minimumNeededForRehash = 2;
1571 
1572         aa["abc"] = 123;
1573         aa["def"] = 456;
1574         assert((aa.newKeysSinceLastRehash == 2), aa.newKeysSinceLastRehash.to!string);
1575         assert((aa.numRehashes == 0), aa.numRehashes.to!string);
1576         aa["ghi"] = 789;
1577         assert((aa.numRehashes == 1), aa.numRehashes.to!string);
1578         assert((aa.newKeysSinceLastRehash == 0), aa.newKeysSinceLastRehash.to!string);
1579         aa.rehash();
1580         assert((aa.numRehashes == 2), aa.numRehashes.to!string);
1581         assert((counter == 2), counter.to!string);
1582 
1583         auto realAA = cast(int[string])aa;
1584         assert("abc" in realAA);
1585         assert("def" in realAA);
1586 
1587         auto alsoRealAA = aa.aaOf;
1588         assert("ghi" in alsoRealAA);
1589         assert("jkl" !in alsoRealAA);
1590 
1591         auto aa2 = aa.dup(copyState: true);
1592         assert((aa2.numRehashes == 2), aa2.numRehashes.to!string);
1593         aa2["jkl"] = 123;
1594         assert("jkl" in aa2);
1595         assert("jkl" !in aa);
1596 
1597         auto aa3 = aa.dup();  //(copyState: false);
1598         assert(!aa3.numRehashes, aa3.numRehashes.to!string);
1599         assert(aa3.aaOf == aa.aaOf);
1600         assert(aa3.aaOf !is aa.aaOf);
1601     }
1602     {
1603         RehashingAA!(int[int]) aa;
1604         aa[1] = 2;
1605         ++aa[1];
1606         assert((aa[1] == 3), aa[1].to!string);
1607         assert((-aa[1] == -3), (-aa[1]).to!string);
1608     }
1609     {
1610         RehashingAA!(int[int]) aa;
1611         aa[1] = 42;
1612         aa[1] += 1;
1613         assert(aa[1] == 43);
1614 
1615         aa[1] *= 2;
1616         assert(aa[1] == 86);
1617     }
1618     {
1619         RehashingAA!(int[string]) aa;
1620         static assert(is(typeof(aa.aaOf()) == int[string]));
1621 
1622         aa["abc"] = 123;
1623         auto native = cast(int[string])aa;
1624         assert(native["abc"] == 123);
1625     }
1626     {
1627         RehashingAA!(int[string]) aa;
1628         aa["abc"] = 123;
1629         aa["def"] = 456;
1630         assert((aa.length == 2), aa.length.to!string);
1631         aa.remove("abc");
1632         assert((aa.length == 1), aa.length.to!string);
1633         aa.remove("def");
1634         assert(!aa.length, aa.length.to!string);
1635     }
1636     {
1637         RehashingAA!(int[string]) aa;
1638         aa["abc"] = 123;
1639         aa["def"] = 456;
1640         aa["ghi"] = 789;
1641 
1642         foreach (value; aa.byValue)
1643         {
1644             import std.algorithm.comparison : among;
1645             assert(value.among!(123, 456, 789), value.to!string);
1646         }
1647     }
1648     {
1649         RehashingAA!(int[string]) aa;
1650         aa["abc"] = 123;
1651         aa["def"] = 456;
1652         aa["ghi"] = 789;
1653 
1654         foreach (key; aa.byKey)
1655         {
1656             assert(key in aa);
1657         }
1658     }
1659     {
1660         RehashingAA!(int[string]) aa;
1661         aa["abc"] = 123;
1662         aa["def"] = 456;
1663         aa["ghi"] = 789;
1664 
1665         auto values = aa.values;  // allocate it once
1666 
1667         // Order cannot be relied upon
1668         foreach (val; [ 123, 456, 789 ])
1669         {
1670             import std.algorithm.searching : canFind;
1671             assert(values.canFind(val));
1672         }
1673     }
1674     {
1675         RehashingAA!(int[string]) aa;
1676         aa["abc"] = 123;
1677         aa["def"] = 456;
1678         aa["ghi"] = 789;
1679 
1680         auto keys = aa.keys;  // allocate it once
1681 
1682         // Order cannot be relied upon
1683         foreach (key; [ "abc", "def", "ghi" ])
1684         {
1685             assert(key in aa);
1686         }
1687     }
1688     {
1689         RehashingAA!(int[string]) aa;
1690         aa["abc"] = 123;
1691         aa["def"] = 456;
1692         aa["ghi"] = 789;
1693 
1694         foreach (kv; aa.byKeyValue)
1695         {
1696             assert(kv.key in aa);
1697             assert(aa[kv.key] == kv.value);
1698         }
1699     }
1700     {
1701         RehashingAA!(string[int]) aa;
1702         string hello = aa.require(42, "hello");
1703         assert(hello == "hello");
1704         assert(aa[42] == "hello");
1705     }
1706     {
1707         RehashingAA!(int[int]) aa;
1708         aa[1] = 42;
1709         aa[2] = 99;
1710 
1711         assert(aa.get(1, 0) == 42);
1712         assert(aa.get(2, 0) == 99);
1713         assert(aa.get(0, 0) == 0);
1714         assert(aa.get(3, 999) == 999);
1715 
1716         assert(0 !in aa);
1717         assert(3 !in aa);
1718     }
1719     static if (__VERSION__ >= 2088L)
1720     {{
1721         RehashingAA!(int[int]) aa;
1722 
1723         assert(1 !in aa);
1724 
1725         aa.update(1,
1726             () => 42,
1727             (int i) => i + 1);
1728         assert(aa[1] == 42);
1729 
1730         aa.update(1,
1731             () => 42,
1732             (int i) => i + 1);
1733         assert(aa[1] == 43);
1734     }}
1735     {
1736         RehashingAA!(string[int]) aa1;
1737         aa1[1] = "one";
1738 
1739         RehashingAA!(string[int]) aa2;
1740         aa2[1] = "one";
1741         assert(aa1 == aa2);
1742 
1743         aa2[2] = "two";
1744         assert(aa1 != aa2);
1745 
1746         aa1[2] = "two";
1747         assert(aa1 == aa2);
1748     }
1749     {
1750         RehashingAA!(string[int]) aa1;
1751         aa1[1] = "one";
1752         aa1[2] = "two";
1753 
1754         string[int] aa2;
1755         aa2[1] = "one";
1756 
1757         assert(aa1 != aa2);
1758 
1759         aa2[2] = "two";
1760         assert(aa1 == aa2);
1761     }
1762     {
1763         RehashingAA!(string[int]) aa;
1764         int i = aa.uniqueKey;
1765         assert(i > 0);
1766         assert(i in aa);
1767         assert(aa[i] == string.init);
1768     }
1769 }
1770 
1771 
1772 // MutexedAA
1773 /++
1774     An associative array and a [core.sync.mutex.Mutex|Mutex]. Wraps associative
1775     array operations in mutex locks.
1776 
1777     Example:
1778     ---
1779     MutexedAA!(string[int]) aa;
1780     aa.setup();  // important!
1781 
1782     aa[1] = "one";
1783     aa[2] = "two";
1784     aa[3] = "three";
1785 
1786     auto hasOne = aa.has(1);
1787     assert(hasOne);
1788     assert(aa[1] == "one");
1789 
1790     assert(aa[2] == "two");
1791 
1792     auto three = aa.get(3);
1793     assert(three == "three");
1794 
1795     auto four = aa.get(4, "four");
1796     assert(four == "four");
1797 
1798     auto five = aa.require(5, "five");
1799     assert(five == "five");
1800     assert(aa[5] == "five");
1801 
1802     auto keys = aa.keys;
1803     assert(keys.canFind(1));
1804     assert(keys.canFind(5));
1805     assert(!keys.canFind(6));
1806 
1807     auto values = aa.values;
1808     assert(values.canFind("one"));
1809     assert(values.canFind("four"));
1810     assert(!values.canFind("six"));
1811 
1812     aa.rehash();
1813     ---
1814 
1815     Params:
1816         AA = Associative array type.
1817         V = Value type.
1818         K = Key type.
1819  +/
1820 struct MutexedAA(AA : V[K], V, K)
1821 {
1822 private:
1823     import std.range.primitives : ElementEncodingType;
1824     import std.traits : isIntegral;
1825     import core.sync.mutex : Mutex;
1826 
1827     /++
1828         [core.sync.mutex.Mutex|Mutex] to lock the associative array with.
1829      +/
1830     shared Mutex mutex;
1831 
1832 public:
1833     /++
1834         The internal associative array.
1835      +/
1836     shared AA aa;
1837 
1838     /++
1839         Sets up this instance. Does nothing if it has already been set up.
1840 
1841         Instantiates the [mutex] and minimally initialises the associative array
1842         by assigning and removing a dummy value.
1843      +/
1844     void setup() nothrow
1845     {
1846         if (mutex) return;
1847 
1848         mutex = new shared Mutex;
1849         (cast()mutex).lock_nothrow();
1850 
1851         if (K.init !in cast(AA)aa)
1852         {
1853             (cast(AA)aa)[K.init] = V.init;
1854             (cast(AA)aa).remove(K.init);
1855         }
1856 
1857         (cast()mutex).unlock_nothrow();
1858     }
1859 
1860     /++
1861         Returns whether or not this instance has been set up.
1862 
1863         Returns:
1864             Whether or not the [mutex] was instantiated, and thus whether this
1865             instance has been set up.
1866      +/
1867     auto isReady() inout
1868     {
1869         return (mutex !is null);
1870     }
1871 
1872     /++
1873         `aa[key] = value` array assign operation, wrapped in a mutex lock.
1874 
1875         Example:
1876         ---
1877         MutexedAA!(string[int]) aa;
1878         aa.setup();  // important!
1879 
1880         aa[1] = "one";
1881         aa[2] = "two";
1882         ---
1883 
1884         Params:
1885             value = Value.
1886             key = Key.
1887 
1888         Returns:
1889             The value assigned.
1890      +/
1891     auto opIndexAssign(V value, K key)
1892     in (mutex, typeof(this).stringof ~ " has null Mutex")
1893     {
1894         (cast()mutex).lock_nothrow();
1895         (cast(AA)aa)[key] = value;
1896         (cast()mutex).unlock_nothrow();
1897         return value;
1898     }
1899 
1900     /++
1901         `aa[key]` array retrieve operation, wrapped in a mutex lock.
1902 
1903         Example:
1904         ---
1905         MutexedAA!(string[int]) aa;
1906         aa.setup();  // important!
1907 
1908         // ...
1909 
1910         string one = aa[1];
1911         writeln(aa[2]);
1912         ---
1913 
1914         Params:
1915             key = Key.
1916 
1917         Returns:
1918             The value assigned.
1919      +/
1920     auto opIndex(K key)
1921     in (mutex, typeof(this).stringof ~ " has null Mutex")
1922     {
1923         (cast()mutex).lock_nothrow();
1924         auto value = (cast(AA)aa)[key];
1925         (cast()mutex).unlock_nothrow();
1926         return value;
1927     }
1928 
1929     /++
1930         Returns whether or not the passed key is in the associative array.
1931 
1932         Example:
1933         ---
1934         MutexedAA!(string[int]) aa;
1935         aa.setup();  // important!
1936 
1937         aa[1] = "one";
1938         assert(aa.has(1));
1939         ---
1940 
1941         Params:
1942             key = Key.
1943 
1944         Returns:
1945             `true` if the key is in the associative array; `false` if not.
1946      +/
1947     auto has(K key)
1948     in (mutex, typeof(this).stringof ~ " has null Mutex")
1949     {
1950         (cast()mutex).lock_nothrow();
1951         auto exists = (key in cast(AA)aa) !is null;
1952         (cast()mutex).unlock_nothrow();
1953         return exists;
1954     }
1955 
1956     /++
1957         `aa.remove(key)` array operation, wrapped in a mutex lock.
1958 
1959         Example:
1960         ---
1961         MutexedAA!(string[int]) aa;
1962         aa.setup();  // important!
1963 
1964         aa[1] = "one";
1965         assert(aa.has(1));
1966 
1967         aa.remove(1);
1968         assert(!aa.has(1));
1969         ---
1970 
1971         Params:
1972             key = Key.
1973 
1974         Returns:
1975             Whatever `aa.remove(key)` returns.
1976      +/
1977     auto remove(K key)
1978     in (mutex, typeof(this).stringof ~ " has null Mutex")
1979     {
1980         (cast()mutex).lock_nothrow();
1981         auto value = (cast(AA)aa).remove(key);
1982         (cast()mutex).unlock_nothrow();
1983         return value;
1984     }
1985 
1986     static if (isIntegral!K)
1987     {
1988         /++
1989             Reserves a unique key in the associative array.
1990 
1991             Note: The key type must be an integral type.
1992 
1993             Example:
1994             ---
1995             MutexedAA!(string[int]) aa;
1996             aa.setup();  // important!
1997 
1998             int i = aa.uniqueKey;
1999             assert(i > 0);
2000             assert(aa.has(i));
2001             assert(aa[i] == string.init);
2002             ---
2003 
2004             Params:
2005                 min = Optional minimum key value; defaults to `1``.
2006                 max = Optional maximum key value; defaults to `K.max`, where `K` is
2007                     the key type of the passed associative array.
2008                 value = Optional value to assign to the key; defaults to `V.init`,
2009                     where `V` is the value type of the passed associative array.
2010 
2011             Returns:
2012                 A unique key for the passed associative array, for which there is now
2013                 a value of `value`.`
2014 
2015             See_Also:
2016                 [lu.array.uniqueKey]
2017          +/
2018         auto uniqueKey()
2019             (K min = 1,
2020             K max = K.max,
2021             V value = V.init)
2022         in (mutex, typeof(this).stringof ~ " has null Mutex")
2023         {
2024             static import lu.array;
2025 
2026             (cast()mutex).lock_nothrow();
2027             auto key = lu.array.uniqueKey(*(cast(AA*)&aa), min, max, value);
2028             (cast()mutex).unlock_nothrow();
2029             return key;
2030         }
2031     }
2032 
2033     /++
2034         Implements `opEquals` for this type, comparing the internal associative
2035         array with that of another `MutexedAA`.
2036 
2037         Example:
2038         ---
2039         MutexedAA!(string[int]) aa1;
2040         aa1.setup();  // important!
2041         aa1[1] = "one";
2042 
2043         MutexedAA!(string[int]) aa2;
2044         aa2.setup();  // as above
2045         aa2[1] = "one";
2046         assert(aa1 == aa2);
2047 
2048         aa2[2] = "two";
2049         assert(aa1 != aa2);
2050 
2051         aa1[2] = "two";
2052         assert(aa1 == aa2);
2053         ---
2054 
2055         Params:
2056             other = Other `MutexedAA` whose internal associative array to compare
2057                 with the one of this instance.
2058 
2059         Returns:
2060             `true` if the internal associative arrays are equal; `false` if not.
2061      +/
2062     auto opEquals(typeof(this) other)
2063     in (mutex, typeof(this).stringof ~ " has null Mutex")
2064     {
2065         (cast()mutex).lock_nothrow();
2066         auto isEqual = (cast(AA)aa == cast(AA)(other.aa));
2067         (cast()mutex).unlock_nothrow();
2068         return isEqual;
2069     }
2070 
2071     /++
2072         Implements `opEquals` for this type, comparing the internal associative
2073         array with a different one.
2074 
2075         Example:
2076         ---
2077         MutexedAA!(string[int]) aa1;
2078         aa1.setup();  // important!
2079         aa1[1] = "one";
2080         aa1[2] = "two";
2081 
2082         string[int] aa2;
2083         aa2[1] = "one";
2084 
2085         assert(aa1 != aa2);
2086 
2087         aa2[2] = "two";
2088         assert(aa1 == aa2);
2089         ---
2090 
2091         Params:
2092             other = Other associative array to compare the internal one with.
2093 
2094         Returns:
2095             `true` if the internal associative arrays are equal; `false` if not.
2096      +/
2097     auto opEquals(AA other)
2098     in (mutex, typeof(this).stringof ~ " has null Mutex")
2099     {
2100         (cast()mutex).lock_nothrow();
2101         auto isEqual = (cast(AA)aa == other);
2102         (cast()mutex).unlock_nothrow();
2103         return isEqual;
2104     }
2105 
2106     /++
2107         Rehashes the internal associative array.
2108 
2109         Example:
2110         ---
2111         MutexedAA!(string[int]) aa;
2112         aa.setup();  // important!
2113 
2114         aa[1] = "one";
2115         aa[2] = "two";
2116         aa.rehash();
2117         ---
2118 
2119         Returns:
2120             A reference to the rehashed internal array.
2121      +/
2122     auto rehash()
2123     in (mutex, typeof(this).stringof ~ " has null Mutex")
2124     {
2125         (cast()mutex).lock_nothrow();
2126         auto rehashed = (cast(AA)aa).rehash();
2127         (cast()mutex).unlock_nothrow();
2128         return rehashed;
2129     }
2130 
2131     /++
2132         Clears the internal associative array.
2133 
2134         Example:
2135         ---
2136         MutexedAA!(string[int]) aa;
2137         aa.setup();  // important!
2138 
2139         aa[1] = "one";
2140         aa[2] = "two";
2141         assert(aa.has(1));
2142 
2143         aa.clear();
2144         assert(!aa.has(2));
2145         ---
2146      +/
2147     void clear()
2148     in (mutex, typeof(this).stringof ~ " has null Mutex")
2149     {
2150         (cast()mutex).lock_nothrow();
2151         (cast(AA)aa).clear();
2152         (cast()mutex).unlock_nothrow();
2153     }
2154 
2155     /++
2156         Returns the length of the internal associative array.
2157 
2158         Example:
2159         ---
2160         MutexedAA!(string[int]) aa;
2161         aa.setup();  // important!
2162 
2163         assert(aa.length == 0);
2164         aa[1] = "one";
2165         aa[2] = "two";
2166         assert(aa.length == 2);
2167         ---
2168 
2169         Returns:
2170             The length of the internal associative array.
2171      +/
2172     auto length()
2173     in (mutex, typeof(this).stringof ~ " has null Mutex")
2174     {
2175         (cast()mutex).lock_nothrow();
2176         auto length = (cast(AA)aa).length;
2177         (cast()mutex).unlock_nothrow();
2178         return length;
2179     }
2180 
2181     /++
2182         Returns the value for the key `key`, inserting `value` lazily if it is not present.
2183 
2184         Example:
2185         ---
2186         MutexedAA!(string[int]) aa;
2187         aa.setup();  // important!
2188 
2189         assert(!aa.has(42));
2190         string hello = aa.require(42, "hello");
2191         assert(hello == "hello");
2192         assert(aa[42] == "hello");
2193         ---
2194 
2195         Params:
2196             key = Key.
2197             value = Lazy value.
2198 
2199         Returns:
2200             The value for the key `key`, or `value` if there was no value there.
2201      +/
2202     auto require(K key, lazy V value)
2203     in (mutex, typeof(this).stringof ~ " has null Mutex")
2204     {
2205         V retval;
2206 
2207         (cast()mutex).lock_nothrow();
2208         if (auto existing = key in cast(AA)aa)
2209         {
2210             retval = *existing;
2211         }
2212         else
2213         {
2214             (cast(AA)aa)[key] = value;
2215             retval = value;
2216         }
2217 
2218         (cast()mutex).unlock_nothrow();
2219         return retval;
2220     }
2221 
2222     /++
2223         Returns a new dynamic array of all the keys in the internal associative array.
2224 
2225         Example:
2226         ---
2227         MutexedAA!(int[int]) aa;
2228         aa.setup();  // important!
2229         aa[1] = 42;
2230         aa[2] = 99;
2231 
2232         auto keys = aa.keys;
2233         assert(keys.canFind(1));
2234         assert(keys.canFind(2));
2235         assert(!keys.canFind(3));
2236         ---
2237 
2238         Returns:
2239             A new `K[]` of all the AA keys.
2240      +/
2241     auto keys()
2242     in (mutex, typeof(this).stringof ~ " has null Mutex")
2243     {
2244         (cast()mutex).lock_nothrow();
2245         auto keys = (cast(AA)aa).keys;  // allocates a new array
2246         (cast()mutex).unlock_nothrow();
2247         return keys;
2248     }
2249 
2250     /++
2251         Returns a new dynamic array of all the values in the internal associative array.
2252 
2253         Example:
2254         ---
2255         MutexedAA!(int[int]) aa;
2256         aa.setup();  // important!
2257         aa[1] = 42;
2258         aa[2] = 99;
2259 
2260         auto values = aa.values;
2261         assert(values.canFind(42));
2262         assert(values.canFind(99));
2263         assert(!values.canFind(0));
2264         ---
2265 
2266         Returns:
2267             A new `V[]` of all the AA values.
2268      +/
2269     auto values()
2270     in (mutex, typeof(this).stringof ~ " has null Mutex")
2271     {
2272         (cast()mutex).lock_nothrow();
2273         auto values = (cast(AA)aa).values;  // as above
2274         (cast()mutex).unlock_nothrow();
2275         return values;
2276     }
2277 
2278     /++
2279         Retrieves the value for the key `key`, or returns the default `value`
2280         if there was none.
2281 
2282         Example:
2283         ---
2284         MutexedAA!(int[int]) aa;
2285         aa.setup();  // important!
2286         aa[1] = 42;
2287         aa[2] = 99;
2288 
2289         assert(aa.get(1, 0) == 42);
2290         assert(aa.get(2, 0) == 99);
2291         assert(aa.get(0, 0) == 0);
2292         assert(aa.get(3, 999) == 999);
2293 
2294         assert(!aa.has(0));
2295         assert(!aa.has(3));
2296         ---
2297 
2298         Params:
2299             key = Key.
2300             value = Lazy default value.
2301 
2302         Returns:
2303             The value for the key `key`, or `value` if there was no value there.
2304      +/
2305     auto get(K key, lazy V value)
2306     in (mutex, typeof(this).stringof ~ " has null Mutex")
2307     {
2308         (cast()mutex).lock_nothrow();
2309         auto existing = key in cast(AA)aa;
2310         auto retval = existing ? *existing : value;
2311         (cast()mutex).unlock_nothrow();
2312         return retval;
2313     }
2314 
2315     /++
2316         Updates the value for the key `key` in the internal associative array,
2317         invoking the first of the passed delegate to insert a new value if it
2318         doesn't exist, or the second selegate to modify it in place if it does.
2319 
2320         Note: Doesn't compile with compilers earlier than version 2.088.
2321 
2322         Example:
2323         ---
2324         MutexedAA!(int[int]) aa;
2325         aa.setup();  // important!
2326 
2327         assert(!aa.has(1));
2328 
2329         aa.update(1,
2330             () => 42,
2331             (int i) => i + 1);
2332         assert(aa[1] == 42);
2333 
2334         aa.update(1,
2335             () => 42,
2336             (int i) => i + 1);
2337         assert(aa[1] == 43);
2338         ---
2339 
2340         Params:
2341             key = Key.
2342             createDg = Delegate to invoke to create a new value if it doesn't exist.
2343             updateDg = Delegate to invoke to update an existing value.
2344      +/
2345     static if (__VERSION__ >= 2088L)
2346     void update(U)
2347         (K key,
2348         scope V delegate() createDg,
2349         scope U delegate(K) updateDg)
2350     if (is(U == V) || is(U == void))
2351     in (mutex, typeof(this).stringof ~ " has null Mutex")
2352     {
2353         (cast()mutex).lock_nothrow();
2354         .object.update((*(cast(AA*)&aa)), key, createDg, updateDg);
2355         (cast()mutex).unlock_nothrow();
2356     }
2357 
2358     /++
2359         Implements unary operations by mixin strings.
2360 
2361         Example:
2362         ---
2363         MutexedAA!(int[int]) aa;
2364         aa.setup();  // important!
2365 
2366         aa[1] = 42;
2367         assert(-aa[1] == -42);
2368         ---
2369 
2370         Params:
2371             op = Operation, here a unary operator.
2372             key = Key.
2373 
2374         Returns:
2375             The result of the operation.
2376      +/
2377     auto opIndexUnary(string op)(K key)
2378     //if (isIntegral!V)
2379     in (mutex, typeof(this).stringof ~ " has null Mutex")
2380     {
2381         (cast()mutex).lock_nothrow();
2382         mixin("auto value = " ~ op ~ "(cast(AA)aa)[key];");
2383         (cast()mutex).unlock_nothrow();
2384         return value;
2385     }
2386 
2387     /++
2388         Implements index assign operations by mixin strings.
2389 
2390         Example:
2391         ---
2392         MutexedAA!(int[int]) aa;
2393         aa.setup();  // important!
2394 
2395         aa[1] = 42;
2396         aa[1] += 1;
2397         assert(aa[1] == 43);
2398 
2399         aa[1] *= 2;
2400         assert(aa[1] == 86);
2401         ---
2402 
2403         Params:
2404             op = Operation, here an index assign operator.
2405             value = Value.
2406             key = Key.
2407      +/
2408     void opIndexOpAssign(string op, U)(U value, K key)
2409     if (is(U == V) || is(U == ElementEncodingType!V))
2410     in (mutex, typeof(this).stringof ~ " has null Mutex")
2411     {
2412         (cast()mutex).lock_nothrow();
2413         mixin("(*(cast(AA*)&aa))[key] " ~ op ~ "= value;");
2414         (cast()mutex).unlock_nothrow();
2415     }
2416 }
2417 
2418 ///
2419 unittest
2420 {
2421     {
2422         MutexedAA!(string[int]) aa1;
2423         assert(!aa1.isReady);
2424         aa1.setup();
2425         assert(aa1.isReady);
2426         aa1.setup();  // extra setups ignored
2427 
2428         MutexedAA!(string[int]) aa2;
2429         aa2.setup();
2430 
2431         aa1[42] = "hello";
2432         aa2[42] = "world";
2433         assert(aa1 != aa2);
2434 
2435         aa1[42] = "world";
2436         assert(aa1 == aa2);
2437 
2438         aa2[99] = "goodbye";
2439         assert(aa1 != aa2);
2440     }
2441     {
2442         MutexedAA!(string[int]) aa;
2443         aa.setup();
2444 
2445         assert(!aa.has(42));
2446         aa.require(42, "hello");
2447         assert((aa[42] == "hello"), aa[42]);
2448 
2449         bool set1;
2450         assert(!aa.has(99));
2451         string world1 = aa.require(99, { set1 = true; return "world"; }());
2452         assert(set1);
2453         assert((world1 == "world"), world1);
2454         assert((aa[99] == "world"), aa[99]);
2455 
2456         bool set2;
2457         string world2 = aa.require(99, { set2 = true; return "goodbye"; }());
2458         assert(!set2);
2459         assert((world2 != "goodbye"), world2);
2460         assert((aa[99] != "goodbye"), aa[99]);
2461     }
2462     {
2463         import std.concurrency : Tid, send, spawn;
2464         import std.conv : to;
2465         import core.time : MonoTime, seconds;
2466 
2467         static immutable timeout = 1.seconds;
2468 
2469         static void workerFn(MutexedAA!(string[int]) aa)
2470         {
2471             static void _assert(
2472                 lazy bool condition,
2473                 const string message = "unittest failure",
2474                 const string file = __FILE__,
2475                 const uint line = __LINE__)
2476             {
2477                 if (!condition)
2478                 {
2479                     import std.format : format;
2480                     import std.stdio : writeln;
2481 
2482                     enum pattern = "core.exception.AssertError@%s(%d): %s";
2483                     immutable assertMessage = pattern.format(file, line, message);
2484                     writeln(assertMessage);
2485                     assert(0, assertMessage);
2486                 }
2487             }
2488 
2489             _assert(aa.isReady, "MutexedAA passed to worker was not set up properly");
2490 
2491             bool halt;
2492 
2493             while (!halt)
2494             {
2495                 import std.concurrency : OwnerTerminated, receiveTimeout;
2496                 import std.variant : Variant;
2497 
2498                 immutable receivedSomething = receiveTimeout(timeout,
2499                     (bool _)
2500                     {
2501                         halt = true;
2502                     },
2503                     (int i)
2504                     {
2505                         _assert((aa.length == i-1), "Incorrect MutexedAA length before insert");
2506                         aa[i] = i.to!string;
2507                         _assert((aa.length == i), "Incorrect MutexedAA length after insert");
2508                     },
2509                     (OwnerTerminated _)
2510                     {
2511                         halt = true;
2512                     },
2513                     (Variant v)
2514                     {
2515                         import std.stdio : writeln;
2516                         writeln("MutexedAA unit test worker received unknown message: ", v);
2517                         halt = true;
2518                     }
2519                 );
2520 
2521                 if (!receivedSomething) return;
2522             }
2523         }
2524 
2525         MutexedAA!(string[int]) aa;
2526         aa.setup();
2527 
2528         auto worker = spawn(&workerFn, aa);
2529         immutable start = MonoTime.currTime;
2530 
2531         foreach (/*immutable*/ i; 1..10)  // start at 1 to enable length checks in worker
2532         {
2533             worker.send(i);
2534             aa.setup();
2535             auto present = aa.has(i);
2536 
2537             while (!present && (MonoTime.currTime - start) < timeout)
2538             {
2539                 import core.thread : Thread;
2540                 import core.time : msecs;
2541 
2542                 static immutable briefWait = 2.msecs;
2543                 Thread.sleep(briefWait);
2544                 present = aa.has(i);
2545             }
2546 
2547             assert(present, "MutexedAA unit test worker timed out responding to " ~ i.to!string);
2548             assert((aa[i] == i.to!string), aa[i]);
2549         }
2550 
2551         worker.send(true);  // halt
2552     }
2553     {
2554         import std.algorithm.searching : canFind;
2555 
2556         MutexedAA!(int[int]) aa;
2557         aa.setup();
2558 
2559         aa[1] = 42;
2560         aa[2] = 99;
2561         assert(aa.length == 2);
2562 
2563         auto keys = aa.keys;
2564         assert(keys.canFind(1));
2565         assert(keys.canFind(2));
2566         assert(!keys.canFind(3));
2567 
2568         auto values = aa.values;
2569         assert(values.canFind(42));
2570         assert(values.canFind(99));
2571         assert(!values.canFind(0));
2572 
2573         assert(aa.get(1, 0) == 42);
2574         assert(aa.get(2, 0) == 99);
2575         assert(aa.get(0, 0) == 0);
2576         assert(aa.get(3, 999) == 999);
2577     }
2578     {
2579         MutexedAA!(int[int]) aa1;
2580         aa1.setup();
2581 
2582         aa1[1] = 42;
2583         aa1[2] = 99;
2584 
2585         int[int] aa2;
2586 
2587         aa2[1] = 42;
2588         assert(aa1 != aa2);
2589 
2590         aa2[2] = 99;
2591         assert(aa1 == aa2);
2592 
2593         ++aa2[2];
2594         assert(aa2[2] == 100);
2595 
2596         aa2[1] += 1;
2597         assert(aa2[1] == 43);
2598 
2599         aa2[1] -= 1;
2600         assert(aa2[1] == 42);
2601 
2602         aa2[1] *= 2;
2603         assert(aa2[1] == 84);
2604 
2605         int i = -aa2[1];
2606         assert(i == -84);
2607     }
2608     {
2609         MutexedAA!(char[][int]) aa;
2610         aa.setup();
2611 
2612         aa[1] ~= 'a';
2613         aa[1] ~= 'b';
2614         aa[1] ~= 'c';
2615         assert(aa[1] == "abc".dup);
2616 
2617         aa[1] ~= [ 'd', 'e', 'f' ];
2618         assert(aa[1] == "abcdef".dup);
2619     }
2620     {
2621         MutexedAA!(int[int]) aa;
2622         aa.setup();
2623 
2624         immutable key = aa.uniqueKey;
2625         assert(key > 0);
2626 
2627         assert(aa.has(key));
2628         assert(aa[key] == int.init);
2629         aa.remove(key);
2630         assert(!aa.has(key));
2631 
2632         immutable key2 = aa.uniqueKey(1, 2, -1);
2633         assert(key2 == 1);
2634         assert(aa.has(key2));
2635         assert(aa[key2] == -1);
2636     }
2637     static if (__VERSION__ >= 2088L)
2638     {{
2639         MutexedAA!(int[int]) aa;
2640         aa.setup();
2641 
2642         assert(!aa.has(1));
2643 
2644         aa.update(1,
2645             () => 42,
2646             (int i) => i + 1);
2647         assert(aa.has(1));
2648         assert(aa[1] == 42);
2649 
2650         aa.update(1,
2651             () => 42,
2652             (int i) => i + 1);
2653         assert(aa[1] == 43);
2654     }}
2655 }