Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changeset 5298

Show
Ignore:
Timestamp:
01/14/10 17:25:35 (2 years ago)
Author:
kris
Message:

tentative support for weak-references, courtesy of wm4

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tango/core/Memory.d

    r4949 r5298  
    4848    extern (C) void gc_removeRoot( void* p ); 
    4949    extern (C) void gc_removeRange( void* p ); 
     50 
     51    extern(C) Object gc_weakpointerGet (void* wp); 
     52    extern(C) void*  gc_weakpointerCreate (Object r); 
     53    extern(C) void   gc_weakpointerDestroy (void* wp); 
    5054} 
    5155 
     
    442446    } 
    443447     
     448 
     449    /** 
     450     * Create a weak pointer to the given object. 
     451     * Returns a pointer to an opaque struct allocated in C memory. 
     452     */ 
     453    static void* weakPointerCreate( Object o ) 
     454    { 
     455        return gc_weakpointerCreate (o); 
     456    } 
     457 
     458 
     459    /** 
     460     * Destroy a weak pointer returned by weakpointerCreate(). 
     461     * If null is passed, nothing happens. 
     462     */ 
     463    static void weakPointerDestroy( void* p ) 
     464    { 
     465        return gc_weakpointerDestroy (p); 
     466    } 
     467 
     468 
     469    /** 
     470     * Query a weak pointer and return either the object passed to 
     471     * weakpointerCreate, or null if it was free'd in the meantime. 
     472     * If null is passed, null is returned. 
     473     */ 
     474    static Object weakPointerGet( void* p ) 
     475    { 
     476        return gc_weakpointerGet (p); 
     477    } 
     478 
     479 
    444480    /** 
    445481    * returns the amount to allocate to keep some extra space 
     
    450486    * elSize = size of one element 
    451487    */ 
    452     size_t growLength(size_t newlength,size_t elSize=1){ 
    453         size_t newcap = newlength*elSize; 
    454         size_t newext = 0; 
    455         const size_t b=0; // flatness factor, how fast the extra space decreases with array size 
    456         const size_t a=100; // allocate at most a% of the requested size as extra space (rounding will change this) 
    457         const size_t minBits=1; // minimum bit size 
     488    static size_t growLength (size_t newlength, size_t elSize=1) 
     489    {    
     490        return growLength (newlength, elSize, 100, 0, 1); 
     491    } 
    458492     
    459493 
    460         static size_t log2plusB(size_t c) 
    461         { 
    462             // could use the bsr bit op 
    463             size_t i=b+1; 
    464             while(c >>= 1){ 
    465                 ++i; 
    466             } 
    467             return i; 
    468         } 
    469         long mult = 100 + a*(minBits+b) / log2plusB(newlength); 
    470  
    471         newext = elSize*cast(size_t)(((newcap * mult)+99) / 100); 
    472         newcap = newext > newcap ? newext : newcap; // just to handle overflows 
    473         return newcap; 
    474     } 
    475      
    476494    /** 
    477495    * returns the amount to allocate to keep some extra space 
     
    485503    * minBits = minimum number of bits of newlength 
    486504    */ 
    487     size_t growLength(size_t newlength, size_t elSize,size_t a, size_t b=0,size_t minBits=1){ 
    488         size_t newcap = newlength*elSize; 
    489         size_t newext = 0; 
     505    static size_t growLength (size_t newlength, size_t elSize, size_t a, size_t b=0, size_t minBits=1) 
     506    { 
    490507        static size_t log2(size_t c) 
    491508        { 
    492509            // could use the bsr bit op 
    493510            size_t i=1; 
    494             while(c >>= 1){ 
    495                 ++i; 
    496             } 
     511            while(c >>= 1) 
     512                  ++i; 
    497513            return i; 
    498514        } 
     515 
     516        size_t newext = 0; 
     517        size_t newcap = newlength*elSize; 
    499518        long mult = 100 + a*(minBits+b) / (log2(newlength)+b); 
    500  
    501519        newext = elSize*cast(size_t)(((newcap * mult)+99) / 100); 
    502520        newcap = newext > newcap ? newext : newcap; // just to handle overflows 
  • trunk/tango/core/rt/gc/basic/gc.d

    r4971 r5298  
    218218    _gc.removeRange( p ); 
    219219} 
     220 
     221extern (C) void* gc_weakpointerCreate( Object r ) 
     222{ 
     223    return _gc.weakpointerCreate(r); 
     224} 
     225 
     226extern (C) void gc_weakpointerDestroy( void* wp ) 
     227{ 
     228    _gc.weakpointerDestroy(wp); 
     229} 
     230 
     231extern (C) Object gc_weakpointerGet( void* wp ) 
     232{ 
     233    return _gc.weakpointerGet(wp); 
     234} 
  • trunk/tango/core/rt/gc/basic/gcx.d

    r4971 r5298  
    8888 
    8989    extern (C) void rt_finalize( void* p, bool det = true ); 
     90 
     91    alias void delegate(Object) DEvent; 
     92    extern (C) void rt_attachDisposeEvent(Object h, DEvent e); 
     93    extern (C) bool rt_detachDisposeEvent(Object h, DEvent e); 
    9094 
    9195    alias void delegate( void*, void* ) scanFn; 
     
    13391343        stats.freelistsize = flsize; 
    13401344    } 
     1345 
     1346    /******************* weak-reference support *********************/ 
     1347 
     1348    //call locked if necessary 
     1349    private T locked(T)(in T delegate() code)  
     1350    { 
     1351        if (thread_needLock) 
     1352            synchronized(gcLock) return code(); 
     1353        else 
     1354           return code(); 
     1355    } 
     1356 
     1357    private struct WeakPointer  
     1358    { 
     1359        Object reference; 
     1360 
     1361        void ondestroy(Object r)  
     1362        { 
     1363            assert(r is reference); 
     1364            //lock for memory consistency (parallel readers) 
     1365            // 
     1366            //also ensures that weakpointerDestroy can be called while another 
     1367            //thread is freeing the reference with "delete"                     
     1368            locked!(void)({ reference = null; }); 
     1369        } 
     1370    } 
     1371 
     1372    /** 
     1373     * Create a weak pointer to the given object. 
     1374     * Returns a pointer to an opaque struct allocated in C memory. 
     1375     */ 
     1376    void* weakpointerCreate( Object r ) 
     1377    { 
     1378        if (r) 
     1379           { 
     1380           //must be allocated in C memory 
     1381           //1. to hide the reference from the GC 
     1382           //2. the GC doesn't scan delegates added by rt_attachDisposeEvent for references 
     1383           auto wp = cast(WeakPointer*)(.malloc(WeakPointer.sizeof)); 
     1384           if (!wp) 
     1385               onOutOfMemoryError(); 
     1386           *wp = WeakPointer.init; 
     1387           wp.reference = r; 
     1388           rt_attachDisposeEvent(r, &wp.ondestroy); 
     1389           return wp; 
     1390           } 
     1391        return null; 
     1392    } 
     1393 
     1394    /** 
     1395     * Destroy a weak pointer returned by weakpointerCreate(). 
     1396     * If null is passed, nothing happens. 
     1397     */ 
     1398    void weakpointerDestroy( void* p ) 
     1399    { 
     1400        if (p)         
     1401           { 
     1402           auto wp = cast(WeakPointer*)p; 
     1403           //must be extra careful about the GC or parallel threads finalizing the 
     1404           //reference at the same time 
     1405           locked!(void)({ 
     1406                   if (wp.reference) 
     1407                       rt_detachDisposeEvent(wp.reference, &wp.ondestroy); 
     1408                  }); 
     1409           .free(wp); 
     1410           } 
     1411    } 
     1412 
     1413    /** 
     1414     * Query a weak pointer and return either the object passed to 
     1415     * weakpointerCreate, or null if it was free'd in the meantime. 
     1416     * If null is passed, null is returned. 
     1417     */ 
     1418    Object weakpointerGet( void* p ) 
     1419    { 
     1420        if (p) 
     1421           { 
     1422           //NOTE: could avoid the lock by using Fawzi style GC counters 
     1423           // but that'd require core.sync.Atomic and lots of care about memory consistency 
     1424           // it's an optional optimization 
     1425           //see http://dsource.org/projects/tango/browser/trunk/user/tango/core/Lifetime.d?rev=5100#L158 
     1426           return locked!(Object)({ 
     1427                  return (cast(WeakPointer*)p).reference; 
     1428                  }); 
     1429           } 
     1430    } 
    13411431} 
    13421432 
  • trunk/tango/core/rt/gc/stub/gc.d

    r3880 r5298  
    164164 
    165165} 
     166 
     167//weakpointers are simply the pointers itself 
     168extern (C) void* gc_weakpointerCreate( Object r ) 
     169{ 
     170    return cast(void*)r; 
     171} 
     172 
     173extern (C) void gc_weakpointerDestroy( void* wp ) 
     174{ 
     175 
     176} 
     177 
     178extern (C) Object gc_weakpointerGet( void* wp ) 
     179{ 
     180    return cast(Object)wp; 
     181}