digitalmars.D.learn - Validity of cast(void*)size_t.max
- =?UTF-8?B?Tm9yZGzDtnc=?= (5/5) Feb 27 2018 Is `cast(void*)size_t.max` always an invalid address?
- Steven Schveighoffer (6/9) Feb 27 2018 You mean, can it point at valid data? Possibly, but likely not. In my
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/5) Feb 27 2018 It's already used to indicate that a slot is free. :)
- Steven Schveighoffer (3/8) Feb 27 2018 cast(void*)1 is likely to be unused.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (4/14) Feb 27 2018 And to be sure, one can have an actual object that represents nullness
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/7) Feb 28 2018 Are there any pros to this pattern compared to just using `null`
- Kagamin (2/4) Feb 28 2018 When null is already used to mean something else.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/12) Feb 28 2018 Instead of checking explicitly against null later on, you simply use the...
- Kagamin (4/5) Feb 28 2018 And since there was a word about class, cast(Class)cast(void*)1
- Steven Schveighoffer (9/14) Feb 28 2018 Oh, and it has a horrible message! Says you can't cast void * to Class.
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/4) Mar 02 2018 Is this preferred performance-wise over `cast(void*)(size_t.max)`?
- Steven Schveighoffer (11/15) Mar 02 2018 No, it just works, as opposed to, um... not working ;)
- =?UTF-8?B?Tm9yZGzDtnc=?= (28/29) Mar 05 2018 Thanks, how do I store it as enum or static immutable struct
- Steven Schveighoffer (9/39) Mar 05 2018 Weird, I would have expected to be able to map addresses at compile
- =?UTF-8?B?Tm9yZGzDtnc=?= (13/16) Mar 05 2018 I still can't evaluate at compile-though...
- Steven Schveighoffer (4/24) Mar 05 2018 No, I mean you call holeKey at *runtime*. Inlined, it's just returning a...
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/5) Mar 05 2018 A compile-time constant visible to the optimizer?
- Stefan Koch (4/9) Mar 05 2018 Yes indeed. For gdc and ldc the optimisation is guranteed and I
- Steven Schveighoffer (14/23) Mar 05 2018 Note, I think the error is bogus, you should be able to create
- Kagamin (6/9) Mar 05 2018 I'd do them as extern variables, it wouldn't be nice to have them
- Steven Schveighoffer (5/14) Mar 06 2018 I hadn't thought of that. It's probably a better solution than pointers.
Is `cast(void*)size_t.max` always an invalid address? Is so, could it be used to indicate removed/delete elements in hash tables with open addressing and a key type being either a pointer or class? And will it work correctly with the GC?
Feb 27 2018
On 2/27/18 9:13 AM, Nordlöw wrote:Is `cast(void*)size_t.max` always an invalid address?You mean, can it point at valid data? Possibly, but likely not. In my past as an embedded developer, a lot of times the interrupt vectors are stored at the end of address space.Is so, could it be used to indicate removed/delete elements in hash tables with open addressing and a key type being either a pointer or class?Why not use null? -Steve
Feb 27 2018
On Tuesday, 27 February 2018 at 16:31:51 UTC, Steven Schveighoffer wrote:Why not use null? -SteveIt's already used to indicate that a slot is free. :)
Feb 27 2018
On 2/27/18 11:37 AM, Nordlöw wrote:On Tuesday, 27 February 2018 at 16:31:51 UTC, Steven Schveighoffer wrote:cast(void*)1 is likely to be unused. -SteveWhy not use null?It's already used to indicate that a slot is free. :)
Feb 27 2018
On 02/27/2018 11:56 AM, Steven Schveighoffer wrote:On 2/27/18 11:37 AM, Nordlöw wrote:And to be sure, one can have an actual object that represents nullness and use its pointer. (Similar to "the null object pattern".) AliOn Tuesday, 27 February 2018 at 16:31:51 UTC, Steven Schveighoffer wrote:cast(void*)1 is likely to be unused. -SteveWhy not use null?It's already used to indicate that a slot is free. :)
Feb 27 2018
On Tuesday, 27 February 2018 at 20:14:01 UTC, Ali Çehreli wrote:And to be sure, one can have an actual object that represents nullness and use its pointer. (Similar to "the null object pattern".) AliAre there any pros to this pattern compared to just using `null` in D?
Feb 28 2018
On Wednesday, 28 February 2018 at 19:22:12 UTC, Nordlöw wrote:Are there any pros to this pattern compared to just using `null` in D?When null is already used to mean something else.
Feb 28 2018
On 02/28/2018 11:22 AM, Nordlöw wrote:On Tuesday, 27 February 2018 at 20:14:01 UTC, Ali Çehreli wrote:Instead of checking explicitly against null later on, you simply use the object and it has no side-effects. I've probably never used it myself but it sounds nice if it's applicable. :) AliAnd to be sure, one can have an actual object that represents nullness and use its pointer. (Similar to "the null object pattern".) AliAre there any pros to this pattern compared to just using `null` in D?
Feb 28 2018
On Tuesday, 27 February 2018 at 19:56:44 UTC, Steven Schveighoffer wrote:cast(void*)1 is likely to be unused.And since there was a word about class, cast(Class)cast(void*)1 won't compile :)
Feb 28 2018
On 2/28/18 3:00 PM, Kagamin wrote:On Tuesday, 27 February 2018 at 19:56:44 UTC, Steven Schveighoffer wrote:Oh, and it has a horrible message! Says you can't cast void * to Class. Which you can do, but apparently not if the compiler can tell if it's an integer you are casting from. This does work: auto x = cast(Object)((cast(size_t *)null) + 1); I used size_t instead of ubyte, because it will avoid any weird bus errors on certain platforms. You'll just get a segfault. -Stevecast(void*)1 is likely to be unused.And since there was a word about class, cast(Class)cast(void*)1 won't compile :)
Feb 28 2018
On Wednesday, 28 February 2018 at 20:07:50 UTC, Steven Schveighoffer wrote:auto x = cast(Object)((cast(size_t *)null) + 1);Is this preferred performance-wise over `cast(void*)(size_t.max)`?
Mar 02 2018
On 3/2/18 3:26 PM, Nordlöw wrote:On Wednesday, 28 February 2018 at 20:07:50 UTC, Steven Schveighoffer wrote:No, it just works, as opposed to, um... not working ;) I think the compiler senses you are trying to do something foolish (even though that's not the case), and prevents you from doing it. For some reason it doesn't care about it if it starts out as a pointer. If both worked, or even cast(void *)(size_t.sizeof) worked, then the performance would be the same, as you are casting a constant. What you are looking for is a sentinel to check against. Either works OK. As I said before, items in the zero page are not going to be mapped by the OS. I'm not sure about size_t.max. -Steveauto x = cast(Object)((cast(size_t *)null) + 1);Is this preferred performance-wise over `cast(void*)(size_t.max)`?
Mar 02 2018
On Wednesday, 28 February 2018 at 20:07:50 UTC, Steven Schveighoffer wrote:auto x = cast(Object)((cast(size_t *)null) + 1);Thanks, how do I store it as enum or static immutable struct member? In trusted pure unittest { class C { int value; } C x; C y = cast(C)((cast(size_t*)null) + 1); // indicates a lazily deleted key struct S { enum C hole1 = cast(C)((cast(size_t*)null) + 1); // TODO make work static immutable C hole2 = cast(C)((cast(size_t*)null) + 1); // TODO make work } } both `enum` and static` immutable` member declarations fail to compile with the same errors: Error: cannot perform pointer arithmetic on non-arrays at compile time Error: cannot perform pointer arithmetic on non-arrays at compile time My only possible solution so far is to return the expression from an inline member function which I guess cannot be optimized as good as comparing to a compile-time value.
Mar 05 2018
On 3/5/18 6:41 AM, Nordlöw wrote:On Wednesday, 28 February 2018 at 20:07:50 UTC, Steven Schveighoffer wrote:Weird, I would have expected to be able to map addresses at compile time, I suppose the way you could work it is: pragma(inline, true) C lazyDeleted() pure nothrow trusted { return cast(C)((cast(size_t*)null) + 1); } Then you can simply use this like it was an enum or immutable. It should go away in terms of a function call. -Steveauto x = cast(Object)((cast(size_t *)null) + 1);Thanks, how do I store it as enum or static immutable struct member? In trusted pure unittest { class C { int value; } C x; C y = cast(C)((cast(size_t*)null) + 1); // indicates a lazily deleted key struct S { enum C hole1 = cast(C)((cast(size_t*)null) + 1); // TODO make work static immutable C hole2 = cast(C)((cast(size_t*)null) + 1); // TODO make work } } both `enum` and static` immutable` member declarations fail to compile with the same errors: Error: cannot perform pointer arithmetic on non-arrays at compile time Error: cannot perform pointer arithmetic on non-arrays at compile time My only possible solution so far is to return the expression from an inline member function which I guess cannot be optimized as good as comparing to a compile-time value.
Mar 05 2018
On Monday, 5 March 2018 at 12:41:06 UTC, Steven Schveighoffer wrote:pragma(inline, true) C lazyDeleted() pure nothrow trusted { return cast(C)((cast(size_t*)null) + 1); }I still can't evaluate at compile-though... enum holeKeyOffset = 0x1; pragma(inline, true) static K holeKey() trusted pure nothrow nogc { return cast(K)((cast(size_t*)null) + holeKeyOffset); } enum _ = holeKey; fails as Error: cannot perform pointer arithmetic on non-arrays at compile time
Mar 05 2018
On 3/5/18 9:01 AM, Nordlöw wrote:On Monday, 5 March 2018 at 12:41:06 UTC, Steven Schveighoffer wrote:No, I mean you call holeKey at *runtime*. Inlined, it's just returning a constant, so it should reduce to a constant. -Stevepragma(inline, true) C lazyDeleted() pure nothrow trusted { return cast(C)((cast(size_t*)null) + 1); }I still can't evaluate at compile-though... enum holeKeyOffset = 0x1; pragma(inline, true) static K holeKey() trusted pure nothrow nogc { return cast(K)((cast(size_t*)null) + holeKeyOffset); } enum _ = holeKey; fails as Error: cannot perform pointer arithmetic on non-arrays at compile time
Mar 05 2018
On Monday, 5 March 2018 at 16:07:49 UTC, Steven Schveighoffer wrote:No, I mean you call holeKey at *runtime*. Inlined, it's just returning a constant, so it should reduce to a constant.A compile-time constant visible to the optimizer?
Mar 05 2018
On Monday, 5 March 2018 at 18:04:20 UTC, Nordlöw wrote:On Monday, 5 March 2018 at 16:07:49 UTC, Steven Schveighoffer wrote:Yes indeed. For gdc and ldc the optimisation is guranteed and I am quite dmd can do this as well. As long as you don't have too many statements.No, I mean you call holeKey at *runtime*. Inlined, it's just returning a constant, so it should reduce to a constant.A compile-time constant visible to the optimizer?
Mar 05 2018
On 3/5/18 1:08 PM, Stefan Koch wrote:On Monday, 5 March 2018 at 18:04:20 UTC, Nordlöw wrote:Note, I think the error is bogus, you should be able to create hard-coded addresses of data at compile time -- I'm not sure how you would do hardware registers otherwise. Another possibility I thought of: struct Dummy { size_t nullValue; void *holeKey; } enum holeKey = &(cast(Dummy *)null).holeKey; But this fails as well Error: dereference of null pointer null -SteveOn Monday, 5 March 2018 at 16:07:49 UTC, Steven Schveighoffer wrote:Yes indeed. For gdc and ldc the optimisation is guranteed and I am quite dmd can do this as well. As long as you don't have too many statements.No, I mean you call holeKey at *runtime*. Inlined, it's just returning a constant, so it should reduce to a constant.A compile-time constant visible to the optimizer?
Mar 05 2018
On Monday, 5 March 2018 at 18:28:43 UTC, Steven Schveighoffer wrote:Note, I think the error is bogus, you should be able to create hard-coded addresses of data at compile time -- I'm not sure how you would do hardware registers otherwise.I'd do them as extern variables, it wouldn't be nice to have them as pointers. extern int reg1; And use linker option to define address: --defsym reg1=0x1111
Mar 05 2018
On 3/6/18 1:08 AM, Kagamin wrote:On Monday, 5 March 2018 at 18:28:43 UTC, Steven Schveighoffer wrote:I hadn't thought of that. It's probably a better solution than pointers. However, I would expect D to have a proper way to do this without resorting to linker tricks. -SteveNote, I think the error is bogus, you should be able to create hard-coded addresses of data at compile time -- I'm not sure how you would do hardware registers otherwise.I'd do them as extern variables, it wouldn't be nice to have them as pointers. extern int reg1; And use linker option to define address: --defsym reg1=0x1111
Mar 06 2018