shared - i need it to be useful

Simen Kjærås simen.kjaras at gmail.com
Sun Oct 21 15:09:32 UTC 2018


On Sunday, 21 October 2018 at 12:45:43 UTC, Stanislav Blinov 
wrote:
> On Sunday, 21 October 2018 at 05:47:14 UTC, Manu wrote:
>> On Sat, Oct 20, 2018 at 10:10 AM Stanislav Blinov via 
>> Digitalmars-d <digitalmars-d at puremagic.com> wrote:
>
>>> Synchronized with what? You still have `a`, which isn't 
>>> `shared` and doesn't require any atomic access or 
>>> synchronization. At this point it doesn't matter if it's an 
>>> int or a struct. As soon as you share `a`, you can't just 
>>> pretend that reading or writing `a` is safe.
>
>> `b` can't read or write `a`... accessing `a` is absolutely 
>> safe.
>
> It's not, with or without your proposal. The purpose of sharing 
> `a` into `b` is to allow someone to access `*a` in a threadsafe 
> way (but un- at safe, as it *will* require casting away `shared` 
> from `b`). That is what's making keeping an unshared reference 
> `a` un- at safe: whoever accesses `*a` in their @trusted 
> implementations via `*b` can't know that `*a` is being 
> (@safe-ly!) accessed in a non-threadsafe way at the same time.

Then someone has not done their job. Since the pieces of code 
that will actually use the un- at safe building blocks at the bottom 
are few and far between, it is reasonable to assume that an 
expert will be writing this code, and that such code be placed in 
a separate module where all access to the shared type is 
controlled.

It seems you expect regular users to have calls to atomicOp!"++" 
scattered all over their code. I find this an unreasonable 
expectation, and fully agree that this will lead to problems.


>> Someone must do something unsafe to undermine your 
>> threadsafety... and
>> if you write unsafe code and don't know what you're doing, 
>> there's
>> nothing that can help you.
>
> Ergo, it follows that anyone that is making an implicit cast 
> from mutable to shared better know what they're doing, which 
> mere mortal users (not "experts") might not. I.e. it's a way to 
> giving a loaded gun to someone who never held a weapon before.

No.


>> Close does not promise threadsafety itself (but of course, it 
>> doesn't violate read/write's promise, or the program is 
>> invalid).
>
> Yep, and that's the issue. It SHALL NOT violate threadsafety, 
> but it can't promise such in any way :(

Can you demonstrate any system that can promise something like 
that? (apart from all-immutable)


>> read and write will appropriately check their file-open state 
>> each time they perform their actions.
>
> Why? The only purpose of giving someone a `shared` reference is 
> to give a reference to an open file. `shared` references can't 
> do anything with the file but read and write, they would expect 
> to be able to do so.

Because otherwise it's not thread-safe. Exactly as you point out, 
the owner could call closeFile before some other thread was 
finished writing. If the implementer of FileHandle fails to take 
this into account, then no, it's not thread-safe.


>> I'm going to assume that `shareWithThreads()` was implemented  
>> by an
>> 'expert' who checked the function results for errors. It was 
>> detected that the reads/write failed, and an error "failed to 
>> read file" was emit, then the function returned promptly.
>> The uncertainty of what happens in this program is however
>> `shareWithThreads()` handles read/write emitting an error.
>
> But you can only find out about these errors in 
> `waitForThreads`, the very call that the user "forgot" to make!

Of course not. You can throw exceptions, you could add a 
destructor that reports on these errors, you could set an error 
flag somewhere and check that every now and then. The fact that 
you've managed to write a horribly broken API under MP and can't 
see a way to do better inside that system does not necessarily 
mean the problem is with MP.

--
   Simen


More information about the Digitalmars-d mailing list