Time to kill T() as (sometimes) working T.init alias ?

monarch_dodra monarchdodra at gmail.com
Mon Dec 10 23:19:06 PST 2012


On Tuesday, 11 December 2012 at 03:09:53 UTC, Dan wrote:
> On Tuesday, 11 December 2012 at 01:47:38 UTC, Walter Bright 
> wrote:
>> On 12/10/2012 10:40 AM, Dan wrote:
>>> For something as simple as this would you introduce COW?
>>
>> Yes.
>
> Any D examples showing the pattern in action with structs? I 
> did not see anything in the index of TDPL on COW except one 
> reference regarding strings. If it is a better approach I would 
> like to know more about how it is done and the trade-offs. Some 
> of the responses refer to having to check on every access, so 
> is that not tough to manage?
>
> Thanks
> Dan

Here is a example of using COW for a simple object that wraps
nothing more than an int:

//----
struct S
{
      static struct Payload
      {
          size_t count;
          int val;
      }
      Payload* payload;

      this(int i = 0)
      {payload = new Payload(1, i);}

      this(this)
      {++payload.count;}
      ~this()
      {--payload.count;}

      void opAssign(S other)
      {
          --payload.count;
          payload = other.payload;
          ++payload.count;
      }

      int get()
      {return payload.val;}

      void set(int i)
      {
          dupeIfNeeded();
          payload.val = i;
      }
      void dupeIfNeeded()
      {
          if (payload.count > 1)
          {
              writeln("payload duplication");
              --payload.count;
              payload = new Payload(1);
          }
      }
}

void main()
{
      S s1 = 5;
      S s2 = s1;
      writeln("before set");
      s2.set(4);
      writeln("after set");
}
//----
The basic idea is that on every write, you check the payload
count, and if it is not 1, then you duplicate the payload.

This means you only pay for the copy when you *actually* need it.

Drawbaks from this approach include:
1. Needs actual code.
2. NOT actually cheap: The counter goes up, and down, on each and
every copy/destruction/pass: Requires a destructor and a postblit
for RAII.
3 Implements deep ownership (*)

*Imo, this is the worst part of COW for a language like D. In
theory, you could just allocate your payload, and let the GC and
default copy take care of everything else, and move on with your
life. COW is (IMO) a c++ relic. Not only is this approach easy,
but it is *also* efficient. If you *do* need actual object
duplication, then you can implement "dup".

//---------------------------------------
BTW: There is a subtle bug in this code. Can you spot it ;) ?


More information about the Digitalmars-d mailing list