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@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-@safe, as it *will* require casting away `shared`
from `b`). That is what's making keeping an unshared reference
`a` un-@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-@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