Worst ideas/features in programming languages?
deadalnix
deadalnix at gmail.com
Fri Oct 15 23:58:34 UTC 2021
On Friday, 15 October 2021 at 21:55:55 UTC, SealabJaster wrote:
> On Friday, 15 October 2021 at 16:44:57 UTC, deadalnix wrote:
>> Then end result in practice is that almost everything uses the
>> GC, and that @safe and @nogc are almost useless.
>
> Is there anything we can do to start addressing this, and the
> other woes people have brought up?
>
> The answer is likely no, so I foresee these same things popping
> up over and over and over again with no resolution since we
> seem to have dug ourselves into a corner.
Well at some point we need to make choices about the invariant we
want and stick with them.
Considering D's values, I'd say the solution that make sense is
to allocate using the GC, have an ownership system on top of it
that can free most things safely. You'll note that is is possible
to build a GC that is as fast as malloc free (for instance, I was
able to build a GC on top of jemalloc, and the only thing I had
to add is one hashmap store when allocating chunk of size bigger
than 4MB. this happens almost never and when it does, memory
allocation is usually not the problem as simply filling these 4MB
with literally anything is far more work than the work the
allocator does (to be 100% fair, this doesn't work with all
mallocs, a tcmalloc style structure wouldn't cut it for instance,
but jemalloc is notorious to be one of the fastest and bestest so
we are not making a big concession).
So using a GC instead of malloc/free is very much viable. In
fact, because we know if something is shared or not, I bet we can
do something that is even faster than traditional mallocs.
So we allocate on the GC, always and use ownership on top of it.
Ownership should allow you to express common
allocation/disposition patterns, and when you can't, either you
leak to the GC, or you free explicitly, which is unsafe.
That require repurposing @nogc as preventing leaking from the
ownership system to the GC rather than allocating on the GC -
which in itself is no problem if the allocations are freed
properly.
There are a ton of added benefit that come attached to this if
done properly, like solving a ton of problems with shared.
Even tricky situations such as @nogc exception become trivial in
that model. Consider:
```d
void foo() {
// Allocate the exception using the GC. The exception is
// an owned(Exception), and the corresponding overload from
// the runtime is called.
// Ownership of the exception is transferred to the runtime.
// The ownership system didn't lose track of the exception, so
// foo can be @nogc .
throw new Exception();
}
void bar() {
try {
foo();
} catch(Exception e) {
// The ownership of the Exception is transferred back to
the
// user's code. The Exception doesn't leave the catch
block,
// so it can be freed automatically without the user
having to
// do anything.
// In practice, that require the runtime to provide the
// exception handler with knowledge of the exception being
// owned or not and a runtime check, so that, if it is
owned
// it is freed.
// bar can also be @nogc , because either the exception
is owned
// in which case it is freed and no leak occurred, or the
exception
// is not owned, in which case the leak happened
somewhere else.
// In that case, this somewhere else cannot be @nogc .
}
}
```
You'll note that the ownership system does not need to be as rich
as Rust's, because there is always the option to fallback on the
GC or on unsafe constructs.
More information about the Digitalmars-d
mailing list