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