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