Escaping the Tyranny of the GC: std.rcstring, first blood

Manu via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 24 19:16:22 PDT 2014


On 25 September 2014 08:54, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
> On 9/24/14, 3:34 PM, Manu via Digitalmars-d wrote:
>>
>> On 25 September 2014 07:17, Andrei Alexandrescu via Digitalmars-d
>> <digitalmars-d at puremagic.com> wrote:
>>>
>>> On 9/24/14, 1:15 PM, Manu via Digitalmars-d wrote:
>>>>
>>>>
>>>> Something like (whatever syntax you like):
>>>>
>>>> int^ rcInt; // refcounted pointer to an int
>>>> MyStruct^ rcStruct; // refcounted pointer to a struct
>>>> MyStruct s; // normal value-type struct, but if the struct has
>>>> opInc/opDec, the RC handling code in the compiler can implicitly
>>>> generate calls to opInc/opDec on assignment, which will allow the
>>>> struct to manage itself.
>>>
>>>
>>>
>>> You're getting confused here, postblit and destructor take care of that.
>>
>>
>> No they don't. It's not a ref counting mechanism, the compiler can't
>> elide those calls.
>
>
> It can.

Elaborate? I could be doing anything to the effect of refcounting, and
it could be interleaved with anything else performed by those
functions...


>> It's what I use now, and it's as good at C++, but we can do much
>> better than that.
>
>
> D's copy semantics are different from C++'s.

I don't see how that influences this.


>>>> Not sure how to express an RC dynamic array... int[^] rcArray? Anyway,
>>>> syntax is whatever it is, I think this approach is what makes sense to
>>>> me though.
>>>
>>>
>>>
>>> Whatever syntax I like? Awesome! How about:
>>>
>>> RefCounted!int rcInt; // refcounted pointer to an int
>>> RefCounted!MyStruct rcStruct; // refcounted pointer to a struct
>>> RefCounted!(int[]) rcArray; // refcounted array
>>>
>>> The irony is the first two already work with the semantics you need, but
>>> apparently I've had difficulty convincing you to try them and report
>>> back.
>>> My work on RCString has also gone ignored by you, although it's exactly
>>> stuff that you're asking for.
>>
>>
>> It all feels backwards to me.
>
>
> So it's not whatever syntax I like? Make up your mind.

This isn't syntax distinction, it's a whole approach.


>> You've completely alienated me from the
>> discussion. I've given up, but I am watching with interest.
>
>
> How do you mean that?

I think it's safe to say I've been the most vocal participant on this
topic for more than half a decade now (6 years maybe?).
Suddenly there is motion, and it goes precisely the opposite direction
that I have been hoping for all this time.
That's fine, I'm very happy there is motion. I'm just clearly not the customer.

I'll be extremely happy to be proven wrong, but I don't feel like I
have an awful lot to add.
I hope it gets to a place I'm happy with, but I find it hard to get on
this train, I'm just not excited by this direction at all.

I specifically don't want shared_ptr<> and std::string, which is where
it seems to be going.


>> I'm not interested in a library solution until I know if, and how the
>> compiler will optimise it... in which case it's not a library solution
>> anymore, so why make the implementation a lib?
>
>
> This can't be serious. So you're not looking at any prototype because it's
> not optimized up to wazoo?

I'm completely serious, but not for the reason you paraphrased.
You're suggesting that this is supported by the language somehow? I
have no idea how that works, and that's what I'm interested in.
We all already have RC libs of our own.


>> @nogc users will use this stuff EXCLUSIVELY. There is already more
>> than enough attribution in D, I *WILL NOT* wrap everything in my
>> program with RefCounted!(). I will continue to invent my own solutions
>> in every instance, and we will live the same reality as C++; where
>> everyone has their own implementations, and none of them are
>> compatible.
>
>
> But in C++ you'd use shared_ptr<T> all the time.

I would never use shared_ptr<> for all the same reasons.


> Your position is completely irrational. Frankly it looks you're bullshitting your way through the whole
> conversation. Whenever anyone puts you in the position of making a positive
> contribution, you run away for something else to whine about.

Whatever. I'll resist the urge to respond similarly ad hominem.

I've made my position on shared_ptr<> clear on so many occasions. I'm
not interested in a D implementation of shared_ptr<>.
I'm not alone, it's not a tool that people use in my industry; most
companies I know even have rigid policies against stl and/or boost.

What contribution am I supposed to make?
I'm not a language developer, I don't want to be. I'm a customer/end
user, that's the relationship I want. I have code to write and I'm
sick of C++, that's why I'm here.
I'm also a strong advocate for D, giving lots of demonstrations,
lecture/presentations, and time/energy within my industry and local
community.
I have in the past had significant involvement in this NG and IRC.
I also influenced a major commercial company to adopt D.
I don't feel my contribution is worthless, or can be summarised as you
so nicely did.

I complain about things that hinder my work. That's what I care about.
You'll notice that I rarely get involved or excited about fancy
futuristic language constructs or library stuff, I am almost entirely
task oriented, and if something is causing chronic friction between me
and getting my work done, then I raise that as an issue.

In terms of 'positive contribution', whatever that means exactly in
this context, all I have ever really managed to achieve around here is
to be a catalyst for action on a few particularly important issues
that affect myself and my industry.
Many of these have been addressed, and that's awesome. I find the
frequency of language related problems has reduced significantly; most
of my current problems are practical (tooling, etc).


>> Call it a bikeshed, whatever. I'm certain this is the practical reality.
>>
>> I have tried RefCounted extensively in the past. Mangling my types
>> like that caused lots of problems, heaps of is(T == RefCounted!U, U)
>> started appearing throughout my code, and incompatibility with
>> existing libraries.
>
>
> Existing libraries won't be helped by adding new functions.
>
> What issues did you have with RefCounted? Why do you keep on coming back to
> "it's mangling my types"?

It's unsightly, interferes with the type system (every time I want T,
I need to check if it's wrapped, and then unwrap it), compromises
debugging experience, runs particularly poorly in non-optimised
builds.

For instance: __traits(allMembers, T) == tuple("RefCountedStore",
"_refCounted", "refCountedStore", "__ctor", "__postblit", "__dtor",
"opAssign", "refCountedPayload")
That's not what the user expects. In such an imaginary context, there
is probably already a 'static if(isPointer!T)' branch, which recurses
with PointerTarget!T. Such is likely to exist in libs, and I expect it
would be handled transparent if RC were a type of pointer.


> Why do you need heaps of is(...)?

Because that's how you find T from RefCounted!T. It's not uncommon to
want to know what type you're dealing with.
I expect things like PointerTarget, isPointer, etc, would be enhanced
to support RC pointers in the event they were to exist.
They don't support RefCounted, and I'm not even sure that really makes
sense, because as I've said before, RefCounted!T is conceptually
backwards; ie, T is a kind of RefCounted, rather than refcounted being
a kind of pointer.

> What is it that you're trying to solve, that only a solution you're unable to specify can fix?

I'd like RC pointers parallel to GC pointers, since I think we've
established in the past that there is no chance we will ever replace
the GC with something like GC backed ARC across the board.

I don't recall trying to specify a solution, just suggesting an
approach that feels natural to me, and is similarly implemented in
other languages.


>> Perhaps the most annoying thing about a library implementation though
>> is the debuginfo baggage. It's extremely frustrating dealing with
>> things that are wrapped up like RefCounted while debugging.
>
>
> How do you debug code using shared_ptr?

I don't, for the same reasons.


>> You can't
>> evaluate the thing anymore, stepping through your code leads you
>> through countless library stubs and indirections. You lose the ability
>> to just read a symbol name without fuss, you need to make your
>> callstack window half the screen wide to see what you're looking at.
>>
>> I'm also not convinced meaningful refcounting can be implemented
>> before we have scope(T) working properly. I think we should be
>> addressing that first.
>
>
> That may as well be true.

Shall we declare this a decisive area of development and start a conversation?
I particularly liked the proposal in the other thread, until it
transformed into a storage class.


More information about the Digitalmars-d mailing list