On Tuesday, 13 May 2014 at 19:50:52 UTC, Rainer Schuetze wrote:


On 13.05.2014 13:09, "Marc Schütz" <[email protected]>" wrote:
On Tuesday, 13 May 2014 at 06:06:40 UTC, Rainer Schuetze wrote:


On 12.05.2014 13:53, "Marc Schütz" <[email protected]>" wrote:

I'm surprised that you didn't include:

3. Thread-local GC, isolated zones (restricting where references to objects of a particular heap can be placed), exempting certain threads
from GC completely, ...

This comes up from time to time, but to me it is very blurry how this
can work in reality.

Considering how "shared" is supposed to be used to be useful (do some
locking, then cast away "shared") there is no guarantee by the
language that any object is actually thread local (no references from other threads). Working with immutable (e.g. strings) is shared by
design.

Yes, but only a part of the data is shared. I suspect the majority of the data in typical programs will be thread-local. If you use a message passing model, you can improve that even further (though it requires a way to move an object to another thread's heap). This way, you can - in
the best case - avoid the shared heap completely.

Possible, but this is with a language without shared data (including immutable), not D. Safely transferring a large object tree from one thread to another will be very expensive. If you try to optimize that, the D compiler won't help you to guarantee memory safety.

It certainly requires a few modifications to the language. That's why I think the current discussions about uniqueness, scope, isolated are so important, because it would fit together very well with memory management concepts like ARC, isolated heaps, and safety. For example, if the uniqueness concept that Walter recently added to DMD were not only temporary (only used for implicit conversion to immutable, AFAIU), but a real, permanent type modifier, transferring such a tree can be made safe at practically no runtime costs, apart from notifying the GC about the changed ownership. (No copying needs to happen, because the important thing for thread-local heaps is actually just in which thread references to objects can be stored, not necessarily that the actual objects are placed into physically distinct heaps.)


Actually I don't have much experience with "shared" (I usually use __gshared if I need a shared global). Maybe I understand the idea better if you show what happens with this code when run with thread local GC:

class C { C next; }

shared(C) list;

C newC()
{
        return new C; // allocated on the local heap?

Yes, because it doesn't say "new shared(C)".

}       

void prependToList(C c)
{
        synchronized(list)
        {
                C lst = cast(C) list;
                c.next = lst;  // anything special happening here?
                list = cast(shared(C)) c;  // and here?

The casts are a problem. You're basically lying to the compiler, so this cannot work. Instead, it should be something like:

    auto newC() {
        return new isolated(C);
    }

    void prependToList(isolated(C) c) {
        synchronized(list) {
            // transfer to shared heap
            // afterwards, c is no longer usable ("consumed")
            shared(C) tmp = c.makeShared();
            tmp.next = list;
            list = tmp;
        }
    }

This uses the "isolated" concept suggested by deadalnix here:
http://forum.dlang.org/thread/[email protected]?page=1

        }
}

void callMeFromMultipleThreads()
{
        prependToList(newC());
}

Reply via email to