Want reasonable reference counting? Disable automatic sharing of immutable
Stanislav Blinov
stanislav.blinov at gmail.com
Sat Nov 13 20:01:16 UTC 2021
On Saturday, 13 November 2021 at 14:34:43 UTC, Steven
Schveighoffer wrote:
> Whether it does this or pushes it off to another thread is
> incidental. The running of finalizers is a function of the GC,
> not the caller.
:)
> The part you are not getting is that this is not something
> being called by the pure code, it's being run by the GC.
```d
import someLibrary;
// someLibrary defines a module-global
// int threadLocal;
void main()
{
someLibrary.threadLocal = () pure nothrow {
return someLibrary.blah(42);
} ();
auto old = someLibrary.threadLocal;
auto someInts = () pure { return new int[1000]; } ();
assert(someLibrary.threadLocal == old);
}
```
That assert may fail. Or you may even crash before getting to it,
and not with an `OutOfMemoryError`, but with a `FinalizeError`,
depending to the value of `threadLocal`. Or it can be totally
fine if the GC doesn't collect. What am I not getting?..
> Imagine it like a context switch to another thread that runs
> the GC code, and then switches back to the pure code.
If I imagine that, the assert above should always hold. Because
there should be no way that imaginary "another thread" would
access main thread's `threadLocal`. Somehow, reality contradicts
imagination.
> In fact, the GC could do this ALREADY, because it could use one
> of the other threads that it has paused do the collection. But
> it doesn't really make any difference conceptually which thread
> runs it. One of those other threads could be in the middle of a
> pure function.
Could be != is.
> It's similar to running some kernel code, or signal code --
> it's initiated by a separate entity, in this case the GC.
>
>> Unless that changed and GC isn't doing that anymore, that's a
>> bug that's been open for some years now.
>
> It should be closed as invalid. Which bug is that?
https://issues.dlang.org/show_bug.cgi?id=19316
Feel free to close it as invalid, if the code above either:
- dies with an OutOfMemoryError
- passes the assert
regardless of value of `threadLocal`.
`someLibrary` can be this for testing:
```d
module someLibrary;
int threadLocal;
class Good
{
int calc(int input) pure nothrow { return input * 2; }
}
class Bad {
int calc(int input) pure nothrow { return input + 14; }
~this() {
// I agree with Walter, dtors should always be nothrow,
// alas current language allows this
if (threadLocal == 56) throw new Exception("ugh");
threadLocal = 0;
}
}
int blah(int input) pure nothrow {
if (input <= 25)
return (new Good).calc(input);
else
return (new Bad).calc(input);
}
```
Contrived? Maybe. Feel free to substitute `threadLocal` with
`errno`, and make a syscall in `Bad.~this`.
More information about the Digitalmars-d
mailing list