Proposal 2: Exceptions and @nogc
MysticZach via Digitalmars-d
digitalmars-d at puremagic.com
Tue Apr 11 10:24:48 PDT 2017
On Sunday, 9 April 2017 at 20:14:24 UTC, Walter Bright wrote:
> On 4/9/2017 1:16 AM, Daniel N wrote:
>> ... but why not go all the way, making it "always" refcounted?
>> (for any "new E",
>> not emplace).
>
> Backwards compatibility, for one. For another, a general
> mechanism for safe refcounting of classes has eluded us.
Hi guys. Hey Walter. So, about this point. On the lifetime study
thread, http://forum.dlang.org/post/56301A8C.1060808@erdani.com ,
the following two problems were stated by Andrei, but I don't
think they were adequately addressed in the subsequent posts:
===
Widget global;
@rc class Widget {
int x;
void fun() {
global = null;
++x;
}
}
void main() {
global = new Widget;
global.fun();
}
In this example, if global has a refcount==1 upon entering fun(),
the assignment "global = null" deletes the Widget object and ++x
accesses dangling memory.
I should add here another pattern that turned problematic for our
older attempts in DIP74:
C c = new C();
foo(c);
int foo(scope C d) {
c = new C(); // c's old instance gets deleted
return d.i; // oops! d is invalid
}
===
So here's my analysis of both these problems.
When calling a function, the reference count for an object must
increase by the total number of aliases created by the call —
*minus the ones lost*. Globals are special in this regard,
because access to them is not lost in the called function. Local
variables, however, are lost to the called function — they cannot
be accessed except through the new alias they receive as a
parameter. Thus, only globals must modify the reference count
when passed.
Thinking about this is made easier if we turn all accessible
aliases into function parameters. For this, we need to consider
the set of globals as a hidden parameter to the function. Any
global is therefore already passed to all functions. If we pass
it again via parameter, that amounts to two aliases, thus two
references. The same logic applies, 1. to duplicating any given
variable in the argument list, e.g. "fun(c, c);", 2. to
duplicating the hidden 'this' parameter, 3. to recognizing and
outer function's stack frame as an additional alias.
All these can be verified at compile time. Also, it is optimistic
regarding the most common case, i.e. passing a local does not
require increasing the reference count.
--Zach
More information about the Digitalmars-d
mailing list