 |
Changeset 5298
- 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
| r4949 |
r5298 |
|
| 48 | 48 | extern (C) void gc_removeRoot( void* p ); |
|---|
| 49 | 49 | 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); |
|---|
| 50 | 54 | } |
|---|
| 51 | 55 | |
|---|
| … | … | |
| 442 | 446 | } |
|---|
| 443 | 447 | |
|---|
| | 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 | |
|---|
| 444 | 480 | /** |
|---|
| 445 | 481 | * returns the amount to allocate to keep some extra space |
|---|
| … | … | |
| 450 | 486 | * elSize = size of one element |
|---|
| 451 | 487 | */ |
|---|
| 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 | } |
|---|
| 458 | 492 | |
|---|
| 459 | 493 | |
|---|
| 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 | | |
|---|
| 476 | 494 | /** |
|---|
| 477 | 495 | * returns the amount to allocate to keep some extra space |
|---|
| … | … | |
| 485 | 503 | * minBits = minimum number of bits of newlength |
|---|
| 486 | 504 | */ |
|---|
| 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 | { |
|---|
| 490 | 507 | static size_t log2(size_t c) |
|---|
| 491 | 508 | { |
|---|
| 492 | 509 | // could use the bsr bit op |
|---|
| 493 | 510 | size_t i=1; |
|---|
| 494 | | while(c >>= 1){ |
|---|
| 495 | | ++i; |
|---|
| 496 | | } |
|---|
| | 511 | while(c >>= 1) |
|---|
| | 512 | ++i; |
|---|
| 497 | 513 | return i; |
|---|
| 498 | 514 | } |
|---|
| | 515 | |
|---|
| | 516 | size_t newext = 0; |
|---|
| | 517 | size_t newcap = newlength*elSize; |
|---|
| 499 | 518 | long mult = 100 + a*(minBits+b) / (log2(newlength)+b); |
|---|
| 500 | | |
|---|
| 501 | 519 | newext = elSize*cast(size_t)(((newcap * mult)+99) / 100); |
|---|
| 502 | 520 | newcap = newext > newcap ? newext : newcap; // just to handle overflows |
|---|
| r4971 |
r5298 |
|
| 218 | 218 | _gc.removeRange( p ); |
|---|
| 219 | 219 | } |
|---|
| | 220 | |
|---|
| | 221 | extern (C) void* gc_weakpointerCreate( Object r ) |
|---|
| | 222 | { |
|---|
| | 223 | return _gc.weakpointerCreate(r); |
|---|
| | 224 | } |
|---|
| | 225 | |
|---|
| | 226 | extern (C) void gc_weakpointerDestroy( void* wp ) |
|---|
| | 227 | { |
|---|
| | 228 | _gc.weakpointerDestroy(wp); |
|---|
| | 229 | } |
|---|
| | 230 | |
|---|
| | 231 | extern (C) Object gc_weakpointerGet( void* wp ) |
|---|
| | 232 | { |
|---|
| | 233 | return _gc.weakpointerGet(wp); |
|---|
| | 234 | } |
|---|
| r4971 |
r5298 |
|
| 88 | 88 | |
|---|
| 89 | 89 | 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); |
|---|
| 90 | 94 | |
|---|
| 91 | 95 | alias void delegate( void*, void* ) scanFn; |
|---|
| … | … | |
| 1339 | 1343 | stats.freelistsize = flsize; |
|---|
| 1340 | 1344 | } |
|---|
| | 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 | } |
|---|
| 1341 | 1431 | } |
|---|
| 1342 | 1432 | |
|---|
| r3880 |
r5298 |
|
| 164 | 164 | |
|---|
| 165 | 165 | } |
|---|
| | 166 | |
|---|
| | 167 | //weakpointers are simply the pointers itself |
|---|
| | 168 | extern (C) void* gc_weakpointerCreate( Object r ) |
|---|
| | 169 | { |
|---|
| | 170 | return cast(void*)r; |
|---|
| | 171 | } |
|---|
| | 172 | |
|---|
| | 173 | extern (C) void gc_weakpointerDestroy( void* wp ) |
|---|
| | 174 | { |
|---|
| | 175 | |
|---|
| | 176 | } |
|---|
| | 177 | |
|---|
| | 178 | extern (C) Object gc_weakpointerGet( void* wp ) |
|---|
| | 179 | { |
|---|
| | 180 | return cast(Object)wp; |
|---|
| | 181 | } |
|---|
Download in other formats:
|
 |
 |
|
 |
Copyright © 2006-2012 Tango. All Rights Reserved. | Page Width:
Static or
Dynamic