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

Changeset 1975

Show
Ignore:
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
  • trunk/lib/common/tango/core/Thread.d

    r1973 r1975  
    19891989        import tango.stdc.posix.unistd;   // for sysconf 
    19901990        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 
    19921992 
    19931993        version( AsmX86_Win32 ) {} else 
     
    22922292    ~this() 
    22932293    { 
     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. 
    22942306        freeStack(); 
    22952307    } 
     
    25722584    in 
    25732585    { 
    2574         assert( !m_pmem ); 
     2586        assert( !m_pmem && !m_ctxt ); 
    25752587    } 
    25762588    body 
     
    25792591        sz += PAGESIZE - 1; 
    25802592        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; 
    25812603 
    25822604        static if( is( typeof( VirtualAlloc ) ) ) 
     
    26722694        } 
    26732695 
    2674         Thread.add( &m_ctxt ); 
     2696        Thread.add( m_ctxt ); 
    26752697    } 
    26762698 
     
    26802702    // 
    26812703    final void freeStack() 
     2704    in 
     2705    { 
     2706        assert( m_pmem && m_ctxt ); 
     2707    } 
     2708    body 
    26822709    { 
    26832710        // NOTE: Since this routine is only ever expected to be called from 
    26842711        //       the dtor, pointers to freed data are not set to null. 
    26852712 
    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 ); 
    26872716 
    26882717        static if( is( typeof( VirtualAlloc ) ) ) 
     
    27022731            free( m_pmem ); 
    27032732        } 
     2733        delete m_ctxt; 
    27042734    } 
    27052735 
     
    28302860 
    28312861 
    2832     Thread.Context m_ctxt; 
     2862    Thread.Context* m_ctxt; 
    28332863    size_t          m_size; 
    28342864    void*           m_pmem; 
     
    28882918        *oldp = getStackTop(); 
    28892919        volatile tobj.m_lock = true; 
    2890         tobj.pushContext( &m_ctxt ); 
     2920        tobj.pushContext( m_ctxt ); 
    28912921 
    28922922        fiber_switchContext( oldp, newp ); 
  • trunk/lib/compiler/dmd/genobj.d

    r1968 r1975  
    193193+/ 
    194194 
     195/+ 
    195196    /** 
    196197     * Create instance of class specified by classname. 
     
    209210        return null; 
    210211    } 
     212+/ 
    211213} 
    212214 
     
    235237    } 
    236238} 
    237  
    238239 
    239240/** 
     
    243244struct Interface 
    244245{ 
    245     ClassInfo classinfo;        /// .classinfo for this interface (not for containing class) 
     246    ClassInfo classinfo;    /// .classinfo for this interface (not for containing class) 
    246247    void *[] vtbl; 
    247248    ptrdiff_t offset;       /// offset to Interface 'this' from Object 'this' 
     
    308309} 
    309310 
    310  
    311311/** 
    312312 * Array of pairs giving the offset and type information for each 
     
    318318    TypeInfo ti;        /// TypeInfo for this member 
    319319} 
    320  
    321320 
    322321/** 
  • trunk/object.di

    r1968 r1975  
    2020    //final void notifyRegister(void delegate(Object) dg); 
    2121    //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 
    2237 
    2338  version( DigitalMars ) 
     
    2540    static Object factory(char[] classname); 
    2641  } 
     42+/ 
    2743} 
    2844 
     
    3147    ClassInfo   classinfo; 
    3248    void*[]     vtbl; 
    33     ptrdiff_t offset;           // offset to Interface 'this' from Object 'this' 
     49    ptrdiff_t offset;   // offset to Interface 'this' from Object 'this' 
    3450} 
    3551 
    3652class ClassInfo : Object 
    3753{ 
    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 
    4157    Interface[] interfaces; 
    4258    ClassInfo   base; 
     
    4460    void(*classInvariant)(Object); 
    4561    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 
    5066    void*       deallocator; 
    5167    OffsetTypeInfo[] offTi; 
    5268  version( DigitalMars ) 
    5369  { 
    54     void* defaultConstructor;   // default Constructor 
     70    void*       defaultConstructor; 
    5571 
    5672    static ClassInfo find(char[] classname); 
     
    7591    void[]   init(); 
    7692    uint     flags(); 
    77     // 1:                   // has possible pointers into GC memory 
     93    // 1:    // has possible pointers into GC memory 
    7894    OffsetTypeInfo[] offTi(); 
    7995}