what to do with postblit on the heap?

Michel Fortin michel.fortin at michelf.com
Tue Jun 21 08:18:26 PDT 2011


On 2011-06-21 09:24:29 -0400, so <so at so.so> said:

> On Tue, 21 Jun 2011 15:25:40 +0300, Michel Fortin  
> <michel.fortin at michelf.com> wrote:
> 
>> Actually, this should be the equivalent:
>> 
>> 	import std.algorithm;
>> 
>> 	S tmp;
>> 	arr ~= move(tmp);
>> 
>> While there is no doubt that 'moving' a struct can often be used as an  
>> optimization without changing the semantics, if you want the @disabled  
>> attribute to be useful on the postblit constructor then the language  
>> needs to define when its semantics require 'moving' data and whey then  
>> require 'copying' data, it can't let that only to the choice of the  
>> optimizer.
>> 
>> Things might be clearer if we had a move operator, but instead we have 
>> a  'move' function. There is only one case where I think we can assume 
>> to  have move semantics: when a temporary (a rvalue) is assigned to  
>> somewhere. That's also all that's needed for the 'move' function to  
>> work. And that is broken currently when it comes to array appending.
> 
> It should be something else because move(tmp) in std.algorithm takes by 
>  reference and returns by value by actually moving it, because of the 
> value  semantics in D, that the ability to differentiate value from 
> reference it  doesn't need any other syntax because this is much better.
> 
> I think it is pretty neat, yet i still have some trouble understanding 
> its  effect here.
> 
> S tmp;
> arr ~= move(tmp); // would make an unnecessary copy.
> 
> Move should do some kind of a magic there and treat its argument like a 
>  value, and return it.

Actually, no copy is needed. Move takes the argument by ref so it can 
obliterates it. Obliteration consists of replacing its bytes with those 
in S.init. That way if you have a smart pointer, it gets returned 
without having to update the reference count (since the source's 
content has been destroyed). It was effectively be moved, not copied.

Note 1: Currently 'move' obliterates the source only if the type has a 
destructor or a postblit. I think it should always do it, but without 
inlining that might be a performance bottleneck.

Note 2: Making move efficient in the case of appending might require a 
total rework of how the compiler interacts with the runtime. And I 
don't think you can optimize away all blitting unless the move function 
was treated specially by the compiler (or became a special operator).

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list