April 17, 2017
On Sunday, 16 April 2017 at 17:00:25 UTC, Jack Stouffer wrote:

> So we can say that D has buggy RAII. Claiming that D doesn't have RAII is equally false.

To me, that's a basic misunderstanding of what RAII mean. RAII, to me, means you wrap your resource in a container, and then can just go ahead and forget about releasing it. As such, saying that D has RAII, but they only work most of the time means that the core functionality that RAII provides is simply not working.

There are other languages out there that have unreliable destructors. Java has them. Python has them. No one will use them.

D's destructors are in much better shape than either Java's or Python's, but let's take a simple survey: Does anyone here use RAII in D? Please step forward.

Please go over your scope(exit)s and tell me that 70% of them (and I'm being generous here, I'm guessing actual number is closer to 95%) are *not* release of resources acquired in the same scope. If they are, then you are in a position where RAII would have made your code cleaner and simpler, but you chose not to use it.

scope(exit) is a much cleaner solution than a finally clause, but not as clean as RAII. If the language supports RAII, how come people are not using it?

Shachar
April 17, 2017
On Monday, 17 April 2017 at 11:14:47 UTC, Shachar Shemesh wrote:
> On Sunday, 16 April 2017 at 17:00:25 UTC, Jack Stouffer wrote:
>
>> So we can say that D has buggy RAII. Claiming that D doesn't have RAII is equally false.
>
> To me, that's a basic misunderstanding of what RAII mean. RAII, to me, means you wrap your resource in a container, and then can just go ahead and forget about releasing it. As such, saying that D has RAII, but they only work most of the time means that the core functionality that RAII provides is simply not working.
>
> There are other languages out there that have unreliable destructors. Java has them. Python has them. No one will use them.
>
> D's destructors are in much better shape than either Java's or Python's, but let's take a simple survey: Does anyone here use RAII in D? Please step forward.


D would have the ability to have a nice container that would do RAII (for classes since for structs, __dtors are called automatically) but such a thing doesn't exist in the standard library. For example in Delphi or FPC standard libs there's the TObjectList class that can be set to delete the instances stored in the list (but there's still the obligation to explicitly free the list itself). D could do even better:

An interesting fact: for the members that are plain structs (not new-ed struct), __fieldDtor automatically calls the __xdtor of the structs. __fieldDtor  is itself called automatically, so

- make a `struct ObjectContainer {}` (basically it would be an array)
- in this ObjectContainer, add a member function that adds new "owned" resources (e.g `T addNew(T,A...)(A a){items ~= make!T(Mallocator.instance, a); return items.last;}`)
- in the ObjectContainer `~this()`, add code that loop the resources and dispose() them.

Resources will be automatically freed:

class/struct Stuff
{
    ObjectContainer resources;
}

when a Stuff goes out of scope or is released, this happens:

Stuff.__fieldDtor() -> ObjectContainer.__xdtor() -> foreach(r; resources) r.__xdtor.

So there's definitively the features to do RAII in D but they are not usable "out-of-the-box", one has to code his specialized containers.

> scope(exit) is a much cleaner solution than a finally clause, but not as clean as RAII.

Actually for local variables and other temporaries I personally don't care much about RAII. I even think that in this case I can let the GC managing the junks.

> If the language supports RAII, how come people are not using it?

Because the default management is done by the GC and the GC works. Mixing RAII and GC can lead to unexpected results. Put a GC-managed member (e.g a string) in a RAII-managed aggregate and then, at a time, the GC will think that the member is not used anymore and it frees it.

___
note about the ObjectContainer: it can be very easy to do actually, using std.array.Array and "alias this". No need to code a full container.
April 17, 2017
On Monday, 17 April 2017 at 11:14:47 UTC, Shachar Shemesh wrote:
> On Sunday, 16 April 2017 at 17:00:25 UTC, Jack Stouffer wrote:
>
>> So we can say that D has buggy RAII. Claiming that D doesn't have RAII is equally false.
>
> To me, that's a basic misunderstanding of what RAII mean. RAII, to me, means you wrap your resource in a container, and then can just go ahead and forget about releasing it. As such, saying that D has RAII, but they only work most of the time means that the core functionality that RAII provides is simply not working.

RAII !== containers. Containers will not release resources for types that are themselves don't do so via their destructor. You can have a vector<FILE*>, and it will dutifully release it's own memory, but won't close the files.

Containers are library types. RAII is a language feature. How on Earth in this discussion the two became interchanged?

> There are other languages out there that have unreliable destructors. Java has them. Python has them. No one will use them.
>
> D's destructors are in much better shape than either Java's or Python's, but let's take a simple survey: Does anyone here use RAII in D? Please step forward.

I do. Phobos does. vibe.d does. Many other projects do.

> Please go over your scope(exit)s and tell me that 70% of them (and I'm being generous here, I'm guessing actual number is closer to 95%) are *not* release of resources acquired in the same scope. If they are, then you are in a position where RAII would have made your code cleaner and simpler, but you chose not to use it.

Writing a whole new struct just to release one specific resource once is neither cleaner nor simpler.

> scope(exit) is a much cleaner solution than a finally clause, but not as clean as RAII. If the language supports RAII, how come people are not using it?

If it is more convenient to use scope(exit) than to introduce a new type, I don't see why the latter should be considered. At least until the need for the same scope(exit) is encountered more than once. Not to mention there are also scope(success|failure) that simply cannot be achieved with destructors.

D supports ("has") RAII idiom, period. Whether or how it is used by various libraries does not in any way augment that fact.
April 17, 2017
On Monday, April 17, 2017 11:14:47 Shachar Shemesh via Digitalmars-d wrote:
> scope(exit) is a much cleaner solution than a finally clause, but not as clean as RAII. If the language supports RAII, how come people are not using it?

Well, if you're talking managing memory, most folks just use the GC. And for the rest, I think that RAII does get used fairly frequently (e.g. std.stdio.File uses it), but largely, RAII is only going to get used when some resource is going to need to be passed around or managed in the same way in several places, because otherwise, it's simpler to just put a scope(exit) statement in there than to declare a type. And the programs that do use RAII are simply buggy in the cases where constructors don't clean up properly when an exception is thrown. For a lot of code, it really doesn't matter (e.g. they simply aren't at any real risk of an exception being thrown during construction), and even in code where it does matter, it could easily be missed, especially if exceptions aren't thrown often. Certainly, this topic comes up infrequently enough that I really don't think that all that many folks are using scope(exit) instead of RAII simply because of the bug with constructors. I'd guess that most folks aren't even aware that it's an issue.

Now, I totally agree that https://issues.dlang.org/show_bug.cgi?id=14246 is a serious issue that needs to be fixed and that some software is going to have some major issues as long as it uses RAII and that bug exists. But because D does not rely as heavily on RAII as C++ does, and RAII works correctly in many cases (particularly if an exception is not thrown during construction), a lot of code can be written which happens to use RAII without being buggy or without the bug being caught. It's when you start relying heavily on RAII that you're more likely to notice it. If RAII were completely broken, I suspect that this would have been a higher priority and would have been fixed ages ago. But because RAII mostly works, this problem has managed to go sufficiently under the radar that it's never become as high a priority as it arguably should be, and it hasn't yet been fixed like it should have been.

- Jonathan M Davis

April 17, 2017
On Monday, 17 April 2017 at 02:56:00 UTC, Jerry wrote:
> Okay, only one container, and happens to be most simple basic one. The others aren't nogc and some of them are even classes. Not only that, Array wasn't @nogc until about a month ago.
>
> No idea what you mean about goal posts. Do you mean it's not an issue worth discussing? You made a false claim, and you still you are still persisting in it as if having a single container be @nogc solves the entire issue.

The first question was whether D had RAII or not. When it was shown that D does have RAII, then the goal posts were moved back to D needing RAII containers that cleaned up their elements on scope exit. When it was shown that D absolutely has RAII containers (that clean up all resources including GC ones on scope exit) then the goal posts were moved back yet again to the containers needed to be @nogc containers. This is despite the fact that @nogc has nothing to do with RAII and is just something people want for convenience.

We are now nowhere near the original topic. I'll cut this off at the knees and say If you want @nogc RAII containers that work with std.allocator then just use https://github.com/economicmodeling/containers
April 17, 2017
On Monday, 17 April 2017 at 15:10:59 UTC, Jack Stouffer wrote:
> On Monday, 17 April 2017 at 02:56:00 UTC, Jerry wrote:
>> Okay, only one container, and happens to be most simple basic one. The others aren't nogc and some of them are even classes. Not only that, Array wasn't @nogc until about a month ago.
>>
>> No idea what you mean about goal posts. Do you mean it's not an issue worth discussing? You made a false claim, and you still you are still persisting in it as if having a single container be @nogc solves the entire issue.
>
> The first question was whether D had RAII or not. When it was shown that D does have RAII, then the goal posts were moved back to D needing RAII containers that cleaned up their elements on scope exit. When it was shown that D absolutely has RAII containers (that clean up all resources including GC ones on scope exit) then the goal posts were moved back yet again to the containers needed to be @nogc containers. This is despite the fact that @nogc has nothing to do with RAII and is just something people want for convenience.

It has everything to do with @nogc, if it isn't @nogc then it is using the garbage collector and even if it is using Destroy() it is still invoking the GC and something is still going to have to be freed by the GC, even if that class is empty. You can't say it is RAII if it is using the GC, that's just nonsense. So it is not just for convenience.

Not to mention for some reason Array's internal implementation is ref counted. If you want ref counted arrays you should do RefCounted!(Array!T). Std.containers is just a giant mess.

I wasn't part of the other discussion, what the hell is the point of having a discussion if you can't change the subject.

> We are now nowhere near the original topic. I'll cut this off at the knees and say If you want @nogc RAII containers that work with std.allocator then just use https://github.com/economicmodeling/containers

I feel like if your solution is, don't use Phobo's containers here use this person's that isn't updating it anymore of questionable quality. Then I feel like you are agreeing with me that phobos containers suck. Oh and it looks like hackerpilot is responsible for merging pull request, lovely.
April 17, 2017
On Monday, 17 April 2017 at 15:24:26 UTC, Jerry wrote:

> It has everything to do with @nogc, if it isn't @nogc then it is using the garbage collector and even if it is using Destroy() it is still invoking the GC and something is still going to have to be freed by the GC, even if that class is empty. You can't say it is RAII if it is using the GC, that's just nonsense. So it is not just for convenience.

On the contrary. All RAII does is establish a relation between resource lifetime and another resource's (e.g. object's) lifetime. It doesn't necessarily have to be limited to any particular scope.

> Not to mention for some reason Array's internal implementation is ref counted. If you want ref counted arrays you should do RefCounted!(Array!T). Std.containers is just a giant mess.

The "some reason" is mutable slices.

> I feel like if your solution is, don't use Phobo's containers here use this person's that isn't updating it anymore of questionable quality. Then I feel like you are agreeing with me that phobos containers suck. Oh and it looks like hackerpilot is responsible for merging pull request, lovely.

Yes, std.container does need quite a bit of love. That doesn't mean that D doesn't have RAII or that it's RAII support is somehow deficient.
April 17, 2017
On Monday, 17 April 2017 at 16:06:20 UTC, Stanislav Blinov wrote:
>
> Yes, std.container does need quite a bit of love. That doesn't mean that D doesn't have RAII or that it's RAII support is somehow deficient.

Of course the reason it doesn't get more love is well-known here. Walter and Andrei want to get safe RC working first.
April 17, 2017
On Monday, 17 April 2017 at 16:06:20 UTC, Stanislav Blinov wrote:
> On Monday, 17 April 2017 at 15:24:26 UTC, Jerry wrote:
>
>> It has everything to do with @nogc, if it isn't @nogc then it is using the garbage collector and even if it is using Destroy() it is still invoking the GC and something is still going to have to be freed by the GC, even if that class is empty. You can't say it is RAII if it is using the GC, that's just nonsense. So it is not just for convenience.
>
> On the contrary. All RAII does is establish a relation between resource lifetime and another resource's (e.g. object's) lifetime. It doesn't necessarily have to be limited to any particular scope.

So what happens when the resource outlives the object's lifetime. That's exactly what is happening when you are using the garbage collector. That's exactly the case with the containers in phobos. So calling them RAII container is just incorrect. You are using two techniques that do the same thing. Call it pure RAII containers if you want, for containers that only use RAII and the current implementation that is GC'd RAII/deterministic destructor containers.

>> Not to mention for some reason Array's internal implementation is ref counted. If you want ref counted arrays you should do RefCounted!(Array!T). Std.containers is just a giant mess.
>
> The "some reason" is mutable slices.

Not really, slices aren't included in the ref counting. So if the array object is detroyed, the slices are no longer valid. You have to deal with the same issue, with or without ref counting. You manually have to ensure the array outlives the slice, and that the slices aren't invalidated by an operation like resize.

>> I feel like if your solution is, don't use Phobo's containers here use this person's that isn't updating it anymore of questionable quality. Then I feel like you are agreeing with me that phobos containers suck. Oh and it looks like hackerpilot is responsible for merging pull request, lovely.
>
> Yes, std.container does need quite a bit of love. That doesn't mean that D doesn't have RAII or that it's RAII support is somehow deficient.

I was never arguing that it didn't. Jack said it had RAII containers, which it doesn't. The standard library containers are shiat.
April 17, 2017
On Monday, 17 April 2017 at 21:20:42 UTC, Jerry wrote:

> So what happens when the resource outlives the object's lifetime.

Then RAII rule is violated.

> That's exactly what is happening when you are using the garbage collector.

Correction, that is what *may* happen in some cases when you are using GC.

> That's exactly the case with the containers in phobos. So calling them RAII container is just incorrect.

I never said they were. You see, you were stating that in order for them to become such, they should be @nogc, which is simply not true. @nogc disallows GC calls, nothing more. You *can* have a RAII type that calls into GC. In fact, you can wrap a class reference into a struct that calls new in constructor and destroy in desctructor, and have a scoped lifetime for class instances that way. But such a struct's constructor and destructor cannot be @nogc.

>>> Not to mention for some reason Array's internal implementation is ref counted. If you want ref counted arrays you should do RefCounted!(Array!T). Std.containers is just a giant mess.
>>
>> The "some reason" is mutable slices.
>
> Not really, slices aren't included in the ref counting.

Yes, they are.

> So if the array object is detroyed, the slices are no longer valid.

The underlying storage is destroyed once the last reference dies, not when Array's destructor is called.

> You have to deal with the same issue, with or without ref counting. You manually have to ensure the array outlives the slice...

No.

> and that the slices aren't invalidated by an operation like resize.

That is true.

My argument was, from the start, that assessing the *language* RAII capability has nothing to do with *library* containers or the (lack of) use of @nogc attribute.