On 10/18/18 2:55 PM, Manu wrote:
On Thu, Oct 18, 2018 at 7:20 AM Steven Schveighoffer via Digitalmars-d
<digitalmars-d@puremagic.com> wrote:
On 10/18/18 10:11 AM, Simen Kjærås wrote:
On Thursday, 18 October 2018 at 13:35:22 UTC, Steven Schveighoffer wrote:
struct ThreadSafe
{
private int x;
void increment()
{
++x; // I know this is not shared, so no reason to use atomics
}
void increment() shared
{
atomicIncrement(&x); // use atomics, to avoid races
}
}
But this isn't thread-safe, for the exact reasons described elsewhere in
this thread (and in fact, incorrectly leveled at Manu's proposal).
Someone could write this code:
void foo() {
ThreadSafe* a = new ThreadSafe();
shareAllOver(a);
Error: cannot call function shareAllOver(shared(ThreadSafe) *) with type
ThreadSafe *
And here you expect a user to perform an unsafe-cast (which they may
not understand), and we have no language semantics to enforce the
transfer of ownership. How do you assure that the user yields the
thread-local instance?
No, I expect them to do:
auto a = new shared(ThreadSafe)();
I think requiring the cast is un-principled in every way that D values.
No cast is required. If you have shared data, it's shared. If you have
thread local data, it's unshared. Allocate the data the way you expect
to use it.
It's only if you intend to turn unshared data into shared data where you
need an unsafe cast.
It's not even as difficult as immutable, because you can still modify
shared data. For instance, the shared constructor doesn't have to have
special rules about initialization, it can just assume shared from the
beginning.
-Steve