GC behavior and Allocators
safety0ff via Digitalmars-d
digitalmars-d at puremagic.com
Sun Jul 6 02:23:56 PDT 2014
On Sunday, 6 July 2014 at 04:58:42 UTC, Brian Schott wrote:
>
> So something like this would work?
>
> void* GCAwareRealloc(void* ptr, size_t size)
> {
> import core.thread;
> void* r;
> thread_enterCriticalRegion();
> scope (exit) thread_exitCriticalRegion();
> r = realloc(ptr, size);
> // Assuming that addRange performs an update of size
> GC.addRange(r, size);
> return r;
> }
No, it can cause a deadlock:
Thread 1: thread_enterCriticalRegion();
Thread 2: Takes GC lock.
Thread 1: Tries to take GC lock to add range, but it has to wait.
Thread 2: triggers a collection -> thread_suspendAll().
Thread 2 waits on thread 1 to exit critical section, thread 1
waits on thread 2 to release GC lock.
So the best we can do at the moment is:
void* GCAwareRealloc(void* ptr, size_t size)
{
void* r;
GC.disable;
scope (exit) GC.enable;
GC.removeRange(ptr);
r = realloc(ptr, size);
GC.addRange(r, size);
return r;
}
With your proposed enhancement we get:
void* GCAwareRealloc(void* ptr, size_t size)
{
void* r;
GC.disable;
scope (exit) GC.enable;
r = realloc(ptr, size);
if (r != ptr)
GC.removeRange(ptr);
GC.addRange(r, size); // if r == ptr, only updates size
return r;
}
Which executes a little faster because we sometimes do 1 less GC
range operation (plus 1 less GC lock.)
More information about the Digitalmars-d
mailing list