making COW and ownership

Dan dbdavidson at yahoo.com
Wed Nov 21 07:06:34 PST 2012


On Wednesday, 21 November 2012 at 04:23:56 UTC, Era Scarecrow 
wrote:
>  Here's a quick thrown together example of what I'm talking 
> about.

I think I see where you are going. After the copy creation of 
new_ca you have two objects referencing exactly the same data. It 
doesn't show it, but the benefit is that a whole bunch of reading 
can be going on against two handles to the same data without 
conflict (i.e. before the first assignment 'new_ca[i] = 200+i;' 
and you have delayed work. I think for this to be effective or 
sane you have to lock all the doors of change. So, for example, 
you would need 'data' to be private, otherwise data could be 
changed without successfully triggering the copy via 
opAssignIndex. Also, if ca itself were changed after the 
assignment to new_ca, but before mutation on new_ca got its copy 
then both would see that change, which is probably not desired.

An alternative might be to use the const system. Assume that the 
whole lot of reading is going on in multiple pieces of code - 
different functions. Just give them the original bit array as 
const. Then they can not write to it directly, but can read from 
it. Eventually when they need to mutate they would need to copy 
just before beginning mutation. The const system helps, but what 
is missing is a way to copy a const object. No way exists yet - 
but I'm proposing and have a 'gdup' that does for this case. Any 
comments on it appreciated.

https://github.com/patefacio/d-help/blob/master/doc/canonical.pdf
https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d

The idea is that the transitive nature of const in D is perfect 
for providing those copy on write semantics without any extra 
work if you can copy the const object when needed.

Thanks
Dan

--------------------------------------------------
import std.stdio;
import std.conv;
import opmix.mix;

struct COWArray(T) {
   private T[] data;
   this(int i) {
     data.length = i;
   }
   inout(T) opIndex(int i) inout pure nothrow {
     return data[i];
   }

   ref COWArray opIndexAssign(T value, int i) pure {
     data[i] = value;
     return this;
   }
}

void give_away_ref(T)(ref const(COWArray!T) ca) {
   // Do lots of reading

   auto new_ca = ca.gdup;

   writeln("\nNew section: ");
   foreach(i; 0 .. 4) {
     new_ca[i] = 200 + i;
     writeln(new_ca);
   }
}

unittest {
   auto ca = COWArray!int(4);

   writeln("\nOriginal:");
   foreach(i; 0 .. 4) {
     ca[i] = 10 + i;
     writeln(ca);
   }

   give_away_ref(ca);

   writeln("\nPost processing:");
   writeln(ca);

}


More information about the Digitalmars-d-learn mailing list