Discussion Thread: DIP 1040--Copying, Moving, and Forwarding--Community Review Round 1
Walter Bright
newshound2 at digitalmars.com
Sat Mar 20 09:06:34 UTC 2021
On 3/18/2021 12:50 PM, deadalnix wrote:
> So, what do we want to do with move constructors anyways? Can't we just move the
> struct field by field recursively and be done with it? Yes, and I'd argue there
> is a problem if this isn't enough for 95% of the cases. Which leads to the two
> use cases I was able to identify:
> - Non movable struct. It is important that such a struct doesn't move. For
> instance, when the struct is some sort of header or a larger data segment.
> Another example is a struct that represent some kind of guard that needs to see
> its construction/destruction done in order. This can be achieved by disabling
> the move constructor, whatever the move constructor is defined as. It is fairly
> easy to realize such use case, the move constructor simply needs to exist at all.
Ok.
> - Movable struct that require some form of bookkeeping. For these cases, a
> postblit would work with one exception: interior pointers.
This bookkeeping was the motivation for #DIP1014:
"For example, D structs also may not use the constructor/destructor to register
themselves with a global registry that keeps track of all instances in the
system, e.g. via a linked list. This also severely limits the ability to store
delegates that reference the struct instance from outside the struct."
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1014.md
Marking the struct as immovable would resolve this problem, too.
> What I refers as interior pointers are struct containing pointer to elements
> which are within the struct itself. While this idiom exist, it is vanishingly
> rare and becoming rarer over time. The main reason for this is that memory has
> become slower, computation faster, and pointer larger, which in turn lead people
> to use "relative pointers", namely pointer defined as an offset from this.
> Unless is is expected that the struct may be more than 4GB in size - which is
> always the case, then it's all good. The extra addition required is well worth
> the memory saved (and increase hit rate in the cache that result from it). See
> https://www.youtube.com/watch?v=G3bpj-4tWVU for instance on how the swift
> runtime started using such techniques.
I didn't know this. This is good info.
> I'll be blunt, once these techniques are known, I've actually never encountered
> a case of interior pointers that would not be solved by disabling move
> altogether. I'm not pretending it doesn't exist, but I've never seen it. It
> simply doesn't make sense to sacrifice any of the above mentioned requirement
> for it, even it turns out this is really needed, because, well, this is the edge
> case of the edge case, and while enabling it might be an option, throwing away
> thing which are good in the general case for it just doesn't make sense.
>
> I suspect that even then, making the struct unmovable and then definition custom
> method to move it manually would do the trick just fine. But just in case, here
> is what I propose: simply add an intrinsic, such as `void* __pre_move_address()`
> that can be called in the postblit, returning the address of the premove object.
> Any object using it would, of course, discard 4/ and not be usable as a value
> and instead always be passed by reference at the ABI level. This is the least
> constraining requirement to break, because it impact exclusively performances
> and never correctness like 1/ or 5/ would. However, considering it is possible
> to it custom once you disable move, I strongly suspect the bang is not worth the
> effort.
This is more or less what DIP1014 proposed.
More information about the Digitalmars-d
mailing list