Changes between Version 2 and Version 3 of FDORfc47


Ignore:
Timestamp:
Jan 13, 2010, 10:11:13 AM (14 years ago)
Author:
gregboone
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • FDORfc47

    v2 v3  
    1919||-0|| ||
    2020||-1|| ||
     21
    2122 
    22 == Motivation ==
    23 
    24 
    2523== Overview ==
    2624
     25The !AddRef / Release / !GetRefCount methods on FdoIDisposable are not currently thread-safe.  As a consequence the m_refCount data member can get corrupted if two separate threads simultaneously call any of these methods on the same object.  This is known to happen during garbage collection of Managed FDO objects.  Because the managed objects implement a finalizer, they are processed by a separate GC finalizer thread.  So while the GC finalizer thread is releasing ref counts on unmanaged objects, the main thread can be simultaneously modifying ref-counts on those same objects.
    2726
    2827== Proposed Solution ==
    2928
     29In !MapGuide this issue is addressed by having all the unmanaged API classes extend from !MgGuardDisposable, which uses a mutex to limit access to the ref-count member to one thread at a time. 
     30
     31A similar solution will be implemented for the FDO API, with a slight variation. The FDO API will use !InterlockedIncrement and !InterlockedDecrement as opposed to a mutex. Also, the use of these thread safe functions will be limited to FDO objects that are wrapped by a Managed object wrapper.
     32
     33Here are the detailed steps that will need to be taken to implement the solution:
     34
     35    * Add a flag to FdoIDisposable (Boolean member variable) to indicate if Interlocked support should be enabled for FDO disposable objects
     36    * Add a pure virtual method on FdoIDispoable that will indicate if Interlocked access should be enabled. E.g. bool !EnableInterlocked()
     37    * Add Interlocked calls to !AddRef and Release (!GetRefCount) that will only be if the boolean flag set by !EnableInterlocked() is True.
     38    * Change the Managed FDO API's MgFdoIDisposable class to call !EnableInterlocked whenever creating an FDO managed wrapper object around an FDO unmanaged object.
     39
     40This solution should provide thread safe access for clients using the FDO Managed API while allowing those who use the unmanaged FDO API directly to avoid the added overhead of Interlocked support.
     41
     42Managed API callers will experience some performance impact as outlined below. All clients will incur a larger memory allocation/overhead due to the addition of the Boolean variable.
     43
     44NOTE: Timing tests were made to test the impact of implementing an Interlocked strategy vs using a Mutex. The testing involved repeatedly calling !AddRef and Release on a single unmanaged FDO object. 100 million repetitions ( 100 million !AddRef and 100 million Release calls) were done using a release build. 3 different cases were tried:
     45
     46    * Unguarded !AddRef and Release (as is now)
     47    * !AddRef and Release guarded by Mutex
     48    * !AddRef and Release implemented by !InterlockedIncrement and !InterlockedDecrement.
     49
     50The times in seconds were:
     51
     52    * Unguarded:   0.876 sec
     53    * With Mutex:  4.034 sec
     54    * Interlocked: 2.314 sec
     55
    3056
    3157== Test Plan ==
    32 
     58Unit Testing and System testing using OSGeo !MapGuide
    3359
    3460== Funding/Resources ==