Very limited shared promotion
Ola Fosheim Grøstad
ola.fosheim.grostad at gmail.com
Wed Jun 19 11:48:44 UTC 2019
On Wednesday, 19 June 2019 at 10:50:45 UTC, Jonathan M Davis
wrote:
> I don't follow. What do you mean by obtain write access? If
> you're talking about shared, scope doesn't care.
Yes, my formulation wasn't clear. What I meant was "what would
be the best way to write an OO-database interface where you can
request read/write access to an object or a set of objects?".
From what has been said in this thread I imagine that the
database would hand out a "scope"-qualified reference of some
sort that prevents the lock from lingering after the scope has
been exited.
Is "shared" the basic mechanism that one ought to use to write
robust thread safe APIs in D?
So, maybe you would get something like this when requesting
objects from an in-memory database:
- Obtaining a write-locked-object: returned as a "scoped
unshared" reference-type.
- Obtaining a read-locked-object: returned as a "scoped
immutable" reference-type.
I am just trying to figure out what the provided mechanisms could
be useful for, and what the missing bits might be. What does it
enable? What does it not enable? In terms of API design, static
type checking and "dynamic reference counting of locks".
How does it affect the ability to call into libraries that was
never written with multi-threading in mind? What can go wrong if
you do so? Etc.
> Actually, using scope when you don't need to would be a serious
> problem. For instance, scope does _not_ interact well with
> range-based code. The typical thing for a lot of range-based
> functions to do is to take the argument, wrap it in a struct
> that's a new range, and return it, whereas if the parameter
> were scope, then you couldn't put the argument or any reference
> to it in the struct.
Ah. But this could be resolved if "scope" kept count of the block
level you are at?
You would just need an implicit scope-level count. So the level
where a reference were turned into "scoped" would be level 0,
whenever it is transferred to a new scope it would have +1 added
to its level.
> Walter is against data flow analysis in most cases largely
> because when language semantics depend on it, you have to
> specify exactly how the data flow analysis works, and it's
> never clear exactly how far you should go with it. He routinely
> shoots down features that would require data flow analysis.
I think it might be possible to reuse existing code though, if
you just generate a suitable graf from the internal
representation in the compiler.
There is a generic theoretical conception for data flow analysis
called Monotone Frameworks.
https://www.cs.cmu.edu/~aplatzer/course/Compilers/27-monframework.pdf
> I have no clue how feasible that would be. I'm also not sure
> what benefit there would be in telling the compiler that a
> piece of code guarantees something that the compiler doesn't
> already check for.
The code gen has to know where the sequencing points are, but
maybe it could do better with more information. I guess
sequencing can be fixed by casting, but there might be other
things you want to verify. E.g.: does references escape, are
functions idempotent…
I believe the generic idea is the right one for a language like D:
There are many concurrency paradigms, it will be difficult to
pick one over another since hardware keeps changing and use
contexts are different.
So if you can move concurrency to libraries, and also provide
crude verification of correctness (or at least reduce the number
of common mistakes), then people can write different concurrency
frameworks and experiment.
One problem with concurrent languages like Pony and Chapel, that
assume a particular paradigm, is that they make assumptions about
the hardware architecture.
It is not at all obvious that the
unified-memory-with-manycores-architecture will win out over the
next decade. Event today that seems to be primarily a server
architecture.
The current client/embedded architecture appears to be a small
handfull of cores with many specialised hardware units with
library support.
So I spot a diverging trend there. But it is hard to predict
where the market will head in the next decade. Will the
architecture be unified again by CPUs absorbing what
co-processors do, or will it move more towards a heterogeneous
distributed architecture (many independent units with local
memory)?
D's focus on single threaded programming is fairly reasonable in
terms of being able to adapt to many types of hardware in a way
that fits how most programmers approach programming today.
So, it might be reasonable to figure out how to enable
concurrency libraries that provide verification mechanisms (like
escape analysis/guarantees) rather than special casing language
features.
> It has been proposed in the past that folks wanted to use UDAs
> to indicate stuff that was somehow then checked by the
> compiler, but I don't know exactly what the expectation there
> was. Certainly, there are bound to be things that we could do
> along those lines, but a concrete proposal would be necessary.
Yes. So one should think about what kind of basic mechanisms one
would want to be able to implement as std-library features. And
what prevents that from being possible and effective/robust.
> Honestly, given how D's type system works, I don't think that
> it's really possible to do anything substantially different
> from C++ as far the built-in concurrency stuff goes.
Doing better than C++ is important though. C++ was conceived
before concurrency became pressing (C++ was designed at a time
when multiple cores was prohibitively expensive), so concurrency
is C++'s big weakness. The concurrency shortcomings of C++ is
also why people create languages like Chapel. So, I'd have to
agree with Manu that it is important to get this right, but it is
also difficult to get right, so one should not rush it.
> considerable improvement over C++. Regardless, before we can be
> sure of nicer features that we might be able to build on top of
> shared, we first need to get the low level aspects sorted out.
One has to do both. It is absolutely necessary to specify all
the use cases that should be present in a solid concurrency
standard library before deciding on the shared semantics.
D has to break out of the evolutionary type system design cycle
so that the type system design does not get amended with special
casing and counter-intuitive exceptions after release.
Ola.
More information about the Digitalmars-d
mailing list