1 module nxt.address;
2 
3 /** Address as an unsigned integer aligned to a byte alignment `alignment_`.
4  *
5  * Used as key, value or element instead of a pointer in `FlatHashMap` to
6  * prevent triggering of `gc_addRange` and `gc_removeRange`.
7  *
8  * TODO: is `holeValue` suitably chosen?
9  *
10  * See_Also: https://en.wikipedia.org/wiki/Data_structure_alignment
11  */
12 struct AlignedAddress(uint alignment_)
13 if (alignment_ == 1 ||
14 	alignment_ == 2 ||
15 	alignment_ == 4 ||
16 	alignment_ == 8 ||
17 	alignment_ == 16 ||
18 	alignment_ == 32)
19 {
20     enum alignment = alignment_; ///< Alignment in bytes.
21 
22     /// Null value.
23     static immutable typeof(this) nullValue = typeof(this).init;
24 
25     /// Hole/Deletion value. Prevent hole bitmap from being used.
26     static immutable typeof(this) holeValue = typeof(this)(_addr.max);
27 
28     /// Get hash of `this`, with extra fast computation for the small case.
29     @property hash_t toHash() const scope @trusted pure nothrow @nogc
30     {
31         pragma(inline, true);
32         debug checkAlignment();
33         static if (alignment == 1)
34             const hash = _addr; // as is
35         else static if (alignment == 2)
36             const hash = _addr >> 1;
37         else static if (alignment == 4)
38             const hash = _addr >> 2;
39         else static if (alignment == 8)
40             const hash = _addr >> 3;
41         else static if (alignment == 16)
42             const hash = _addr >> 4;
43         else static if (alignment == 32)
44             const hash = _addr >> 5;
45         else
46             static assert(0, "Unsupported alignment");
47         // TODO: activate import nxt.hash_functions : lemireHash64;
48         import core.internal.hash : hashOf;
49         return hashOf(cast(void*)hash); // TODO: is `cast(void*)` preferred here?
50     }
51 
52 	/// Check alignment.
53     private debug void checkAlignment() const scope @safe pure nothrow @nogc
54     {
55         assert((_addr & (alignment-1)) == 0,
56                "Address is not aligned to " ~ alignment.stringof);
57     }
58 
59     size_t _addr;				///< Actual pointer address as unsigned integer.
60     alias _addr this;
61 }
62 
63 ///
64 @safe pure nothrow @nogc unittest             // cannot be @nogc when `opIndex` may throw
65 {
66 	alias A = AlignedAddress!1;
67     import nxt.nullable_traits : hasNullValue, isNullable;
68     static assert(hasNullValue!A);
69     static assert(isNullable!A);
70 }