On Tuesday, 11 December 2012 at 12:52:03 UTC, Dan wrote:

For me it did not compile (No constructor for payload), maybe you had a ctor for Payload? I think opAssign is not necessary - if I remove it it still seems to work since default opAssign calls postblit. I added the ctor, removed opAssign and put it here: http://dpaste.dzfl.pl/6ecfe675

Other than that - is there still a subtle bug?

Thanks,
Dan

Strange, it had compiled for me this morning. Wonder what happened...

Anyways, this just highlights one of D's inconsistencies:
Payload  a = Payload(1, 1); //Legal
Payload* p1 = new Payload(1, 1); //Illegal???
Payload* p2 = [Payload(1, 1)].ptr; //Dirty workaround.

Yeah... You can use the "dirty workaround": http://dpaste.dzfl.pl/c0258f66

Anyways, opAssign is *definitely* necessary. Without it, assignment would be equivalent to aliasing, and you wouldn't have actual COW (both instances would end up modified). What's more, if the current object had a handle on another payload, you wouldn't release it, causing it to duplicate for no reason (but that's moot considering COW is already broken). In my example, it works because no-one actually *calls* opAssign.

The bug is this (on topic)
//----
S s2 = S(2);
S s0 = S();
s0 = s2; //Crap.
//----
Here, you aren't actually calling "this(int = 0)". Nope. What you are actually calling is... nothing! This means s0 does not have an actual payload. This means that in theory, on every write, you need to check the count... and check there is actually a payload there first :D ! Yay extra useless checks and increased lazy initialization on every call!

There is a fair amount of boilerplate bookeeping. What if the struct had two, three, or more maps

Depends on the required granularity. I'd say ideally, you'd put all three maps in the same "Payload" struct, so things would not actually be more complicated.

If you try to make each map individually COW, it would only be slightly more complex. You *would* take a further performance hit having to call "ensureUnique" on *each* map every modifying call. Furthermore, you may also take a performance hit in terms of locality of reference. But that'd be WAY premature to really worry about.

What you have to keep in mind is that a "triple COW" design would only make sense if you have functions that modify one of your 3 maps. If they are always modified together, it'd make no sense to use "triple COW".

//----
When everything is said and done, most of that code can be templated, or mixed-in.

Reply via email to