[Dlang-study] [lifetime] Initial thoughts on lifetime management

Michel Fortin michel.fortin at michelf.ca
Thu Oct 29 07:33:26 PDT 2015


Le 28 oct. 2015 à 20:47, Timon Gehr <timon.gehr at gmx.ch> a écrit :

> On 10/29/2015 01:35 AM, Michel Fortin wrote:
>> Le 28 oct. 2015 à 18:39, Timon Gehr <timon.gehr at gmx.ch> a écrit :
>> 
>>> Actually, we do not need #references <= count.
>>> It's just (#references > 0) -> (count > 0).
>>> (The converse should also hold, but then #references has to include cyclic references.)
>> 
>> There's still some value in knowing that the total number of references is 1 and not something higher.
>> 
>> Swift has `isUniquelyReferenced` you can use to implement copy-on-write value types in a thread-safe way.
>> I'm not entirely sure why they can guaranty uniqueness for Swift classes; it looks like they can't when
>> it comes to Objective-C classes.
> 
> Good point. However, it seems somewhat costly to support for classes that don't need it.

I think I understand how Swift's `isUniquelyReferenced` works. It's not costly. It's also quite clever. I'll rewrite the function signature to its D equivalent for this discussion:

	bool isUniquelyReferenced(ref Object o);

This function simply returns true if the counter for "o" is 1. Note that the parameter is 'ref' to avoid the counter being incremented when passing the object to the function. It is also imperative that you do NOT make it 'const ref' if you want the function to work in the presence of the optimizer. By telling the compiler in the function signature that it might mutate the variable, it prevents opInc/opDec elision from occurring in the caller's context. I'll try to illustrate.

Say you have this code:

	auto o{+1} = new O(){-1};
	isUniquelyReferenced(o);
	o{-1}; // end of scope

Here you can elide the {-1} and {+1} on the first line and the reference count is reliably 1, falling to zero at the end of the scope. `isUniquelyReferenced` returns true.

	auto o = new O();
	isUniquelyReferenced(o);
	o{-1}; // end of scope

Now let's add a second reference:

	auto o = new O();
	auto p{+1} = o;
	isUniquelyReferenced(o);
	p{-1}; // end of scope
	o{-1};

Here it might seem that you could elide the p{+1} and p{-1} because it's the same value as o, and o outlives it. But no: the compiler does not know knows whether o's value will outlive p because `isUniquelyReferenced` takes a mutable reference to o. So you can't elide the opInc/opDec for p, the reference count reaches 2, and `isUniquelyReferenced` returns false.

If you removed the call to `isUniquelyReferenced`, then it would optimize like this:

	auto o = new O();
	auto p = o;
	o{-1}; // end of scope

Ingenious.


-- 
Michel Fortin
michel.fortin at michelf.ca
https://michelf.ca




More information about the Dlang-study mailing list