COW vs. in-place.
Reiner Pope
reiner.pope at gmail.com
Mon Jul 31 23:12:04 PDT 2006
Dave wrote:
> None of the const/immutability ideas will take care of having to "copy
> on write"; they were all more-or-less just ways of enforcing COW so
> there wouldn't be mistakes.
Argh, that's what all of my proposals are about. See:
rocheck in 'YACP -- Yet Another Const Proposal' on digitalmars.D
'constness for arrays' by xs0 on digitalmars.D
'what's wrong with just a runtime-checked const'? on digitalmars.D.learn
These all explore a way to make array functions work optimally in all
cases. The rocheck proposal (the most recent one) would look as follows:
rocheck char[] toupper(rocheck char[] input)
{ foreach (i, c; input)
{ if (islower(c))
{ char[] temp = input.ensureWritable; // ensureWritable
checks whether it is mutable and copies if not
temp[i] = chartoupper(c);
input = temp; // if we did indeed duplicate, then make sure we now
use the duplicated one
}
}
return input;
}
// Another alternative: faster, but more code
rocheck char[] toupper(rocheck char[] input)
{ foreach (i, c; input)
{ if (islower(c))
{ char[] temp = input.ensureWritable;
foreach (inout c2; temp[i..$])
{ if (islower(c2)) c2 = toupper(c2);
}
return temp;
}
}
return input;
}
// Now look what we can do:
char[] foo = "hello".dup;
foo = toupper(foo).ensureWritable;
// Ensurewritable is a null-op here, because there is never a const
reference. It's only there to please the const checking of the compiler
readonly char[] bar = baz.getName();
foo = toupper(bar).ensureWritable;
// if toupper modifies, then it will dup it (since bar is readonly). Iff
not, then ensureWritable will dup it. This way, we ensure exactly one
duplication, which is as required.
readonly char[] asdf = CIP1(CIP2(CIP3(bar)));
/// CIP1, 2 and 3 are rocheck functions like toupper above. If none of
them modify, then no duplication takes place. If one of them does, then
only one duplication takes place.
Having it integrated into the language is more powerful, because it
actually works with const checking and makes the syntax cleaner.
Consider how you would get the same efficiency with the last statement
using the CIP enum when just modifying the library:
CIP1, CIP2 and CIP3 would all need signatures as follows:
char[] CIP1(char[] input, inout CIP cipness) {...}
It would be inout so that you can tell it about the input, and it can
tell you about the output. If you don't know the ownership of the
output, you will get unnecessary dups. Here is how you would emulate the
last line of the rocheck sample code:
CIP temp = CIP.COW;
char[] bar; // We mustn't modify this
bar = CIP1(bar, temp); // bar *might* be modifiable inplace, but only
temp knows
bar = CIP2(bar, temp);
bar = CIP3(bar, temp);
// We still don't know whether bar is the original, unmodifiable one, or
not. However, temp can tell us.
This code is much more verbose than one built into the language.
Cheers,
Reiner
More information about the Digitalmars-d
mailing list