Isolated by example
Rikki Cattermole via Digitalmars-d
digitalmars-d at puremagic.com
Fri May 2 00:25:31 PDT 2014
On Friday, 2 May 2014 at 06:51:49 UTC, deadalnix wrote:
> First the original post I made on this forum :
> http://forum.dlang.org/thread/kluaojijixhwigoujeip@forum.dlang.org#post-kluaojijixhwigoujeip:40forum.dlang.org
>
> Now some sample code/explanation to get it better.
>
> Isolated in a proposal adapted from an experiment made in C#
> for D. It introduces a new qualifier. The qualifier is
> necessary on function signatures (inference is possible to some
> extent, like for pure functions), object/struct fields and
> globals. It is inferred on local variables (but can be
> explicited if one wish).
>
> An isolated is in an 'island'. The 'island' is implicit and
> tracked by the compiler. We have one immutable and one shared
> island. We have one TL island per thread. And we can have an
> infinity of isolated island.
>
> An isolated is consumed when:
> - it is returned
> - it is passed as argument
> - it is assigned to another island
>
> When an isolated goes out of scope without being consumed, the
> compiler can free the whole island:
>
> void foo() {
> A a = new A(); // a is isolated if A's ctor allows.
>
> // a is not consumed. The compiler can insert memory freeing.
> }
>
> As we can see, it allows the compiler to do some freeing for us
> to reduce GC pressure. Manu why aren't you already here
> cheering ?
>
> When an isolated is consumed, the island it is in is merged
> into the island that consumes it. All reference to the island
> become write only until next write.
>
> void foo() {
> A a = new A(); // a is isolated
> immutable b = a; // a's island is merged into immutable
>
> // a's island has been consumed. a is not readable at this
> point.
> // a.foo() // Error
> a = new A(); // OK
> a.foo(); // OK, we have written in a.
> }
>
> So far, we saw that isolated helps to construct
> const/immutable/shared objects and can be used by the compiler
> to insert free.
>
> isolated also help to bridge the RC world and the GC world.
>
> struct RC(T) is(isReferenceType!T) {
> private T mystuff;
>
> this(isolated T stuff) {
> mystuff = stuff;
> }
>
> // All code to do ref counting goes here...
> }
>
> Here, the RC struct must be constructed with an isolated. To do
> so, the isolated have to be passed as argument: it is consumed.
> As a result, the RC struct can be sure that it has the only
> usable reference to stuff that is around.
>
> Now some concurrency goodies:
>
> void foo() {
> auto tid = spawn(&spawnedFunc, thisTid);
>
> A a = new A();
> send(tid, a); // OK, a is an isolated.
>
> // a can't be used here anymore as it is consumed.
> // You can simply pass isolated around across thread safely.
> }
>
> Now that is pretty sweet. First we don't have to do the crazy
> and unsafe dance of "cast to shared and cast back to me" and
> this is actually safe. Go's type system do is not safe across
> channel, that puts us ahead in one of the things go does best.
>
> std.parallelism can also benefit from this. There is also
> several benefit when the optimizer knows about isolated
> (different island do not alias each other).
>
> I hope the idea get across better with some sample code and
> will be considered. As sample code shows, isolated do not need
> to be specified explicitly often. User not annotating can get a
> lot of benefit out of the concept right away.
I've been thinking about something similar as being an 'obvious'
idea.
It to me seems rather a good idea.
More information about the Digitalmars-d
mailing list