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);

}

Reply via email to