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