Are D classes proper reference types?

kinke noone at nowhere.com
Fri Jun 25 07:01:31 UTC 2021


On Friday, 25 June 2021 at 06:09:17 UTC, Ola Fosheim Grøstad 
wrote:
> On Thursday, 24 June 2021 at 07:28:56 UTC, kinke wrote:
>> Yes, class *refs* are always pointers. *scope* classes are 
>> deprecated (I don't think I've ever seen one); with `scope c = 
>> new Object`, you can have the compiler allocate a class 
>> *instance* on the stack for you, but `c` is still a *ref*.
>
> But the user code cannot depend on it being stack allocated? So 
> I could replace the Object reference with a reference counting 
> pointer and put the counter at a negative offset?

Well AFAIK it's mandated by the language, so an RC scheme 
replacing such allocations by heap ones seems like a definite 
step backwards - it's a useful pattern, and as Stefan pointed 
out, definitely in use. You could still stack-allocate but 
accommodate for the counter prefix in the compiler.

>> `emplace` doesn't allocate, you have to pass the memory 
>> explicitly.
>
> This is more of a problem. I was thinking about arrays that 
> provide an emplace method, then one could replace emplace with 
> heap allocation. I guess it isn't really possible to make 
> `emplace` with custom memory work gracefully with reference 
> counting with ref count at negative offset.

It's certainly possible as it's a library thing; some existing 
code may assume the returned reference to point to the beginning 
of the passed memory though (where there'd be your counter). What 
you'd definitely need to adjust is `__traits(classInstanceSize)`, 
accomodating for the extra counter prefix.
There's very likely existing code out there which doesn't use 
druntime's emplace[Initializer], but does it manually.

>> A class *instance* can also live in the static data segment 
>> (`static immutable myStaticObject = new Object;`);
>
> But it isn't required to? It certainly wouldn't work with 
> reference counting if it is stored in read only memory...

Not required to AFAIK, but if it's not statically allocated, 
you'd need to allocate it at runtime via some module or CRT ctor. 
It's probably easier to have the compiler put it into static but 
writable memory, so that you can mess with the counter.

---

All in all, I think a more interesting/feasible approach would be 
abusing the monitor field of extern(D) classes for the reference 
counter. It's the 2nd field (of pointer size) of each class 
instance, directly after the vptr (pointer to vtable). I think 
all monitor access goes through a druntime call, so you could 
hook into there, disallowing any regular monitor access, and put 
this (AFAIK, seldomly used) monitor field to some good use.


More information about the Digitalmars-d-learn mailing list