 |
Changeset 1975
- Timestamp:
- 03/28/07 14:45:48
(2 years ago)
- Author:
- sean
- Message:
Another fix for the Fiber memory leak discussed in this thread:
http://www.dsource.org/projects/tango/forums/topic/73
The Fiber's contained Thread.Context struct is now dynamic to allow Fibers to be cleaned up by the GC when all user-level references to them disappear.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r1973 |
r1975 |
|
| 1989 | 1989 | import tango.stdc.posix.unistd; // for sysconf |
|---|
| 1990 | 1990 | import tango.stdc.posix.sys.mman; // for mmap |
|---|
| 1991 | | import tango.stdc.posix.stdlib; // for malloc, valloc |
|---|
| | 1991 | import tango.stdc.posix.stdlib; // for malloc, valloc, free |
|---|
| 1992 | 1992 | |
|---|
| 1993 | 1993 | version( AsmX86_Win32 ) {} else |
|---|
| … | … | |
| 2292 | 2292 | ~this() |
|---|
| 2293 | 2293 | { |
|---|
| | 2294 | // NOTE: A live reference to this object will exist on its associated |
|---|
| | 2295 | // stack from the first time its call() method has been called |
|---|
| | 2296 | // until its execution completes with State.TERM. Thus, the only |
|---|
| | 2297 | // times this dtor should be called are either if the fiber has |
|---|
| | 2298 | // terminated (and therefore has no active stack) or if the user |
|---|
| | 2299 | // explicitly deletes this object. The latter case is an error |
|---|
| | 2300 | // but is not easily tested for, since State.HOLD may imply that |
|---|
| | 2301 | // the fiber was just created but has never been run. There is |
|---|
| | 2302 | // not a compelling case to create a State.INIT just to offer a |
|---|
| | 2303 | // means of ensuring the user isn't violating this object's |
|---|
| | 2304 | // contract, so for now this requirement will be enforced by |
|---|
| | 2305 | // documentation only. |
|---|
| 2294 | 2306 | freeStack(); |
|---|
| 2295 | 2307 | } |
|---|
| … | … | |
| 2572 | 2584 | in |
|---|
| 2573 | 2585 | { |
|---|
| 2574 | | assert( !m_pmem ); |
|---|
| | 2586 | assert( !m_pmem && !m_ctxt ); |
|---|
| 2575 | 2587 | } |
|---|
| 2576 | 2588 | body |
|---|
| … | … | |
| 2579 | 2591 | sz += PAGESIZE - 1; |
|---|
| 2580 | 2592 | sz -= sz % PAGESIZE; |
|---|
| | 2593 | |
|---|
| | 2594 | // NOTE: This instance of Thread.Context is dynamic so Fiber objects |
|---|
| | 2595 | // can be collected by the GC so long as no user level references |
|---|
| | 2596 | // to the object exist. If m_ctxt were not dynamic then its |
|---|
| | 2597 | // presence in the global context list would be enough to keep |
|---|
| | 2598 | // this object alive indefinitely. An alternative to allocating |
|---|
| | 2599 | // room for this struct explicitly would be to mash it into the |
|---|
| | 2600 | // base of the stack being allocated below. However, doing so |
|---|
| | 2601 | // requires too much special logic to be worthwhile. |
|---|
| | 2602 | m_ctxt = new Thread.Context; |
|---|
| 2581 | 2603 | |
|---|
| 2582 | 2604 | static if( is( typeof( VirtualAlloc ) ) ) |
|---|
| … | … | |
| 2672 | 2694 | } |
|---|
| 2673 | 2695 | |
|---|
| 2674 | | Thread.add( &m_ctxt ); |
|---|
| | 2696 | Thread.add( m_ctxt ); |
|---|
| 2675 | 2697 | } |
|---|
| 2676 | 2698 | |
|---|
| … | … | |
| 2680 | 2702 | // |
|---|
| 2681 | 2703 | final void freeStack() |
|---|
| | 2704 | in |
|---|
| | 2705 | { |
|---|
| | 2706 | assert( m_pmem && m_ctxt ); |
|---|
| | 2707 | } |
|---|
| | 2708 | body |
|---|
| 2682 | 2709 | { |
|---|
| 2683 | 2710 | // NOTE: Since this routine is only ever expected to be called from |
|---|
| 2684 | 2711 | // the dtor, pointers to freed data are not set to null. |
|---|
| 2685 | 2712 | |
|---|
| 2686 | | Thread.remove( &m_ctxt ); |
|---|
| | 2713 | // NOTE: m_ctxt is guaranteed to be alive because it is held in the |
|---|
| | 2714 | // global context list. |
|---|
| | 2715 | Thread.remove( m_ctxt ); |
|---|
| 2687 | 2716 | |
|---|
| 2688 | 2717 | static if( is( typeof( VirtualAlloc ) ) ) |
|---|
| … | … | |
| 2702 | 2731 | free( m_pmem ); |
|---|
| 2703 | 2732 | } |
|---|
| | 2733 | delete m_ctxt; |
|---|
| 2704 | 2734 | } |
|---|
| 2705 | 2735 | |
|---|
| … | … | |
| 2830 | 2860 | |
|---|
| 2831 | 2861 | |
|---|
| 2832 | | Thread.Context m_ctxt; |
|---|
| | 2862 | Thread.Context* m_ctxt; |
|---|
| 2833 | 2863 | size_t m_size; |
|---|
| 2834 | 2864 | void* m_pmem; |
|---|
| … | … | |
| 2888 | 2918 | *oldp = getStackTop(); |
|---|
| 2889 | 2919 | volatile tobj.m_lock = true; |
|---|
| 2890 | | tobj.pushContext( &m_ctxt ); |
|---|
| | 2920 | tobj.pushContext( m_ctxt ); |
|---|
| 2891 | 2921 | |
|---|
| 2892 | 2922 | fiber_switchContext( oldp, newp ); |
|---|
| r1968 |
r1975 |
|
| 193 | 193 | +/ |
|---|
| 194 | 194 | |
|---|
| | 195 | /+ |
|---|
| 195 | 196 | /** |
|---|
| 196 | 197 | * Create instance of class specified by classname. |
|---|
| … | … | |
| 209 | 210 | return null; |
|---|
| 210 | 211 | } |
|---|
| | 212 | +/ |
|---|
| 211 | 213 | } |
|---|
| 212 | 214 | |
|---|
| … | … | |
| 235 | 237 | } |
|---|
| 236 | 238 | } |
|---|
| 237 | | |
|---|
| 238 | 239 | |
|---|
| 239 | 240 | /** |
|---|
| … | … | |
| 243 | 244 | struct Interface |
|---|
| 244 | 245 | { |
|---|
| 245 | | ClassInfo classinfo; /// .classinfo for this interface (not for containing class) |
|---|
| | 246 | ClassInfo classinfo; /// .classinfo for this interface (not for containing class) |
|---|
| 246 | 247 | void *[] vtbl; |
|---|
| 247 | 248 | ptrdiff_t offset; /// offset to Interface 'this' from Object 'this' |
|---|
| … | … | |
| 308 | 309 | } |
|---|
| 309 | 310 | |
|---|
| 310 | | |
|---|
| 311 | 311 | /** |
|---|
| 312 | 312 | * Array of pairs giving the offset and type information for each |
|---|
| … | … | |
| 318 | 318 | TypeInfo ti; /// TypeInfo for this member |
|---|
| 319 | 319 | } |
|---|
| 320 | | |
|---|
| 321 | 320 | |
|---|
| 322 | 321 | /** |
|---|
| r1968 |
r1975 |
|
| 20 | 20 | //final void notifyRegister(void delegate(Object) dg); |
|---|
| 21 | 21 | //final void notifyUnRegister(void delegate(Object) dg); |
|---|
| | 22 | /+ |
|---|
| | 23 | attachCleanupHook |
|---|
| | 24 | detachCleanupHook |
|---|
| | 25 | |
|---|
| | 26 | attachCleanupMonitor |
|---|
| | 27 | detachCleanupMonitor |
|---|
| | 28 | |
|---|
| | 29 | callOnCleanup |
|---|
| | 30 | notifyOnCleanup |
|---|
| | 31 | |
|---|
| | 32 | hookObjectLifetime |
|---|
| | 33 | unhookObjectLifetime |
|---|
| | 34 | |
|---|
| | 35 | hookObjectCleanup |
|---|
| | 36 | unhookObjectCleanup |
|---|
| 22 | 37 | |
|---|
| 23 | 38 | version( DigitalMars ) |
|---|
| … | … | |
| 25 | 40 | static Object factory(char[] classname); |
|---|
| 26 | 41 | } |
|---|
| | 42 | +/ |
|---|
| 27 | 43 | } |
|---|
| 28 | 44 | |
|---|
| … | … | |
| 31 | 47 | ClassInfo classinfo; |
|---|
| 32 | 48 | void*[] vtbl; |
|---|
| 33 | | ptrdiff_t offset; // offset to Interface 'this' from Object 'this' |
|---|
| | 49 | ptrdiff_t offset; // offset to Interface 'this' from Object 'this' |
|---|
| 34 | 50 | } |
|---|
| 35 | 51 | |
|---|
| 36 | 52 | class ClassInfo : Object |
|---|
| 37 | 53 | { |
|---|
| 38 | | byte[] init; // class static initializer |
|---|
| 39 | | char[] name; // class name |
|---|
| 40 | | void*[] vtbl; // virtual function pointer table |
|---|
| | 54 | byte[] init; // class static initializer |
|---|
| | 55 | char[] name; // class name |
|---|
| | 56 | void*[] vtbl; // virtual function pointer table |
|---|
| 41 | 57 | Interface[] interfaces; |
|---|
| 42 | 58 | ClassInfo base; |
|---|
| … | … | |
| 44 | 60 | void(*classInvariant)(Object); |
|---|
| 45 | 61 | uint flags; |
|---|
| 46 | | // 1: // IUnknown |
|---|
| 47 | | // 2: // has no possible pointers into GC memory |
|---|
| 48 | | // 4: // has offTi[] member |
|---|
| 49 | | // 8: // has constructors |
|---|
| | 62 | // 1: // IUnknown |
|---|
| | 63 | // 2: // has no possible pointers into GC memory |
|---|
| | 64 | // 4: // has offTi[] member |
|---|
| | 65 | // 8: // has constructors |
|---|
| 50 | 66 | void* deallocator; |
|---|
| 51 | 67 | OffsetTypeInfo[] offTi; |
|---|
| 52 | 68 | version( DigitalMars ) |
|---|
| 53 | 69 | { |
|---|
| 54 | | void* defaultConstructor; // default Constructor |
|---|
| | 70 | void* defaultConstructor; |
|---|
| 55 | 71 | |
|---|
| 56 | 72 | static ClassInfo find(char[] classname); |
|---|
| … | … | |
| 75 | 91 | void[] init(); |
|---|
| 76 | 92 | uint flags(); |
|---|
| 77 | | // 1: // has possible pointers into GC memory |
|---|
| | 93 | // 1: // has possible pointers into GC memory |
|---|
| 78 | 94 | OffsetTypeInfo[] offTi(); |
|---|
| 79 | 95 | } |
|---|
Download in other formats:
|
 |
 |
|
 |
Copyright © 2006-2008 Tango. All Rights Reserved. | Page Width:
Static or
Dynamic