June 28, 2017
On Wednesday, 28 June 2017 at 11:21:07 UTC, Moritz Maxeiner wrote:
> On Wednesday, 28 June 2017 at 09:16:22 UTC, Guillaume Piolat wrote:
>> So far everyone is ignoring my example when A needs B to be destroyed. This happens as soon as you use DerelictUtil for example.
>
> I thought I had (implicitly): B needs to be `@disable finalize`.

So in the current language, doesn't exist?
June 28, 2017
On Wednesday, 28 June 2017 at 11:34:17 UTC, Moritz Maxeiner wrote:
> Requirement: Do not allocate using the GC
> Option 1) Use structs with `@disable this`, `@disable this(this)`, and a destructor that checks whether the resource reference is != invalid resource reference before trying to release.
> Option 2) Use classes with simple constructor/destructor layout.
> If you want to integrate a check that the requirement holds (with either class or struct), put `if (gc_inFinalizer) throw SomeError` into the class/struct destructor

I don't get it.
It's completely possible to use the full power of GC and be deterministic.
I'm out of this very _confused_ discussion.
June 28, 2017
On Wednesday, 28 June 2017 at 12:28:28 UTC, Guillaume Piolat wrote:
> On Wednesday, 28 June 2017 at 11:21:07 UTC, Moritz Maxeiner wrote:
>> On Wednesday, 28 June 2017 at 09:16:22 UTC, Guillaume Piolat wrote:
>>> So far everyone is ignoring my example when A needs B to be destroyed. This happens as soon as you use DerelictUtil for example.
>>
>> I thought I had (implicitly): B needs to be `@disable finalize`.
>
> So in the current language, doesn't exist?

I thought that was the premise of the discussion?
That the GC *currently* invokes the "destructors" as finalizers and that *currently* the only way to avoid that is calling `destroy` on them manually beforehand (since destructors won't be called twice on a single object).
June 28, 2017
On Wednesday, 28 June 2017 at 09:16:22 UTC, Guillaume Piolat wrote:

>
> So far everyone is ignoring my example when A needs B to be destroyed. This happens as soon as you use DerelictUtil for example.

What's the issue with DerelictUtil?
June 28, 2017
On Wednesday, 28 June 2017 at 13:02:04 UTC, Mike Parker wrote:
> On Wednesday, 28 June 2017 at 09:16:22 UTC, Guillaume Piolat wrote:
>
>>
>> So far everyone is ignoring my example when A needs B to be destroyed. This happens as soon as you use DerelictUtil for example.
>
> What's the issue with DerelictUtil?

https://forum.dlang.org/post/pmulowxpikjjffkrscct@forum.dlang.org

Not an issue with DerelictUtil, an issue with the strategy of closing resources in GC with this case.

Derelict loaders work-around this by not unloading shared libraries so the GC won't unload shared libs before the resources related to the shared library are freed.

https://github.com/DerelictOrg/DerelictAL/blob/master/source/derelict/openal/dynload.d#L366


June 28, 2017
On Wednesday, 28 June 2017 at 12:33:24 UTC, Guillaume Piolat wrote:
> On Wednesday, 28 June 2017 at 11:34:17 UTC, Moritz Maxeiner wrote:
>> Requirement: Do not allocate using the GC
>> Option 1) Use structs with `@disable this`, `@disable this(this)`, and a destructor that checks whether the resource reference is != invalid resource reference before trying to release.
>> Option 2) Use classes with simple constructor/destructor layout.
>> If you want to integrate a check that the requirement holds (with either class or struct), put `if (gc_inFinalizer) throw SomeError` into the class/struct destructor
>
> I don't get it.

You asked for a "_simple_ story about resource release" and the above two options provide that IMHO.

> It's completely possible to use the full power of GC and be deterministic.

Sure, but it's not "simple". With D's GC as the memory allocator you can currently have
(1) non-deterministic memory management and non-deterministic object lifetimes:
    Use `new` or `std.experimental.allocator.make!(std.experimental.allocator.gc_allocator.GCAllocator)` for allocation&construction.
    The GC will finalize objects with no pointers to them non-deterministically and deallocate the memory after their respective finalization.
(2) non-deterministic memory management and deterministic object lifetimes:
    Construct the objects as with (1), but destruct them by calling `destroy` on them outside of a collection cycle (i.e. when they, and all their members are still considered "live" by the GC).
    The GC will collect the memory non-deterministically after there are no more pointers to it.
    Warning: You are responsible for ensuring that the GC will never see an undestroyed object in the collection cycle, because it might try to finalize (call its `~this`) it.
             You can protect yourself against such finalization attempts by putting `if (gc_inFinalizer) throw Error("Bug! I forgot to destruct!")` in the objects' respective destructors.
(3) deterministic memory management and deterministic object lifetimes:
    Construct the objects as with (1), but destruct&deallocate them by calling `std.experimental.allocator.dispose!(std.experimental.allocator.gc_allocator.GCAllocator)`on them outside of a collection cycle.
    The GC will not do anything for those objects.
    Same warning as (2) applies.

> I'm out of this very _confused_ discussion.

I'm honestly not sure what's confusing about it.
June 28, 2017
On Wednesday, 28 June 2017 at 13:19:37 UTC, Guillaume Piolat wrote:

> https://forum.dlang.org/post/pmulowxpikjjffkrscct@forum.dlang.org
>
> Not an issue with DerelictUtil, an issue with the strategy of closing resources in GC with this case.
>
> Derelict loaders work-around this by not unloading shared libraries so the GC won't unload shared libs before the resources related to the shared library are freed.
>
> https://github.com/DerelictOrg/DerelictAL/blob/master/source/derelict/openal/dynload.d#L366

Yeah, the loaders all used to needlessly unload the shared libraries in a static destructor. The fact that they don't anymore isn't to avoid any GC/destructor issues, but because there's no point in unloading the libraries when the system is going to do it anyway.
June 28, 2017
On Tuesday, 27 June 2017 at 09:54:19 UTC, John Burton wrote:
> I'm coming from a C++ background so I'm not too used to garbage collection and it's implications. I have a function that creates a std.socket.Socket using new and connects to a tcp server, and writes some stuff to it. I then explicitly close the socket, and the socket object goes out of scope.
>

> Am I doing this right? Or is there a better way to do this in D?
>
> Thanks.


For my use case here, I'm increasingly thinking that just calling the underlying 'C' socket and send calls is better. No need for anything complicated at all for my actual program :)

June 29, 2017
On Wednesday, 28 June 2017 at 15:55:41 UTC, John Burton wrote:
> On Tuesday, 27 June 2017 at 09:54:19 UTC, John Burton wrote:
>> I'm coming from a C++ background so I'm not too used to garbage collection and it's implications. I have a function that creates a std.socket.Socket using new and connects to a tcp server, and writes some stuff to it. I then explicitly close the socket, and the socket object goes out of scope.
>>
>
>> Am I doing this right? Or is there a better way to do this in D?
>>
>> Thanks.
>
>
> For my use case here, I'm increasingly thinking that just calling the underlying 'C' socket and send calls is better. No need for anything complicated at all for my actual program :)

One final piece of advice as this thread seemed to have gone off the rails a bit. You can always put a `scope(exit) socket.close();` after you create the socket. This will ensure that the socket will be closed once the scope is exited no matter what... almost, anyway. If an Error is thrown no stack unwinding is done but at this point your program is in an unrecoverable state anyway and you have a lot more to worry about than a socket that hasn't been closed.
1 2 3 4
Next ›   Last »