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