On 23.09.2014 02:15, Oscar Martin wrote:
With some/a lot of work and a little help compiler (currently it
indicates by a flag if a class/structure contains pointers/references to
other classes/structures, it could increase this support to indicate
which fields are pointers/references)

https://github.com/rainers/druntime/gcx_precise2

we could implement a
semi-incremental-generational-copying GC-conservative like:

    http://www.hboehm.info/gc/
or
    http://www.ravenbrook.com/project/mps/

Being incremental, they try to minimize the "stop-the-world" phase. But
even with an advanced GC, as programs become more complex and use more
memory, pause time also increases. See for example (I know it's not
normal case, but in a few years ...)

As others have already mentioned, incremental GCs need read/write barriers. There is currently resistence to implementing these in the compiler, the alternative in the library is using page protection, but this is very coarse.

"semi-incremental-generational-copying" is probably asking to much in one step ;-)


http://blog.mgm-tp.com/2014/04/controlling-gc-pauses-with-g1-collector

(*) What if:
- It is forbidden for "__gshared" have references/pointers to objects
allocated by the GC (if the compiler can help with this prohibition,
perfect, if not the developer have to know what he is doing)
- "shared" types are not allocated by the GC (they could be reference
counted or manually released or ...)

shared objects will eventually contain references to other objects that you don't want to handle manually (e.g. string). That means you will have to add the memory range of the shared object to some GC for scanning. Back to square one...

- "immutable" types are no longer implicitly "shared"

In short, the memory accessible from multiple threads is not managed by
the GC.

Is the compiler meant to help via the type system? I don't think this works as AFAIK the recommended way to work with shared objects is to cast away shared after synchronizing on some mutex:

class C
{
        void doWork() { /*...*/ }

        void doSharedWork() shared
        {
                synchronized(someMutex)
                {
                        C self = cast(C)this;
                        self.doWork();
                }
        }
}

Maybe I missed other patterns to use shared (apart from atomics on primitive types). Are there any?


With these restrictions each thread would have its "I_Allocator", whose
default implementation would be an
incremental-generational-semi-conservative-copying GC, with no
inteference with any of the other program threads (it should be
responsible only for the memory reserved for that thread). Other
implementations of "I_Allocator" could be based on Andrei's allocators.
With "setThreadAllocator" (similar to current gc_setProxy) you could
switch between the different implementations if you need. Threads with
critical time requirements could work with an implementation of
"I_Allocator" not based on the GC. It would be possible simulate scoped
classes:

{
     setThreadAllocator(I_Allocator_pseudo_stack)
     scope(exit) {
         I_Allocator_pseudo_stack.deleteAll();
         setThreadAllocator(I_Allocator_gc);
     }
     auto obj = MyClass();
     ...
     // Destructor are called and memory released
}


There is a DIP by Walter with similar functionality: http://wiki.dlang.org/DIP46

Reply via email to