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