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 }