in

ASP.NET Weblogs

Eddie Garmon's Weblog

some architecture, some c#

Sync Enumerator update.

After a few more unit tests, I have fixed an issue with the GetSyncEnumerator method.

The origional had 2 issues.

  1. was that the lock was being released too soon.
  2. was that a write in the middle of a long enumeration would cause a race and/or a deadlock.

The fix was to 'write' lock for enumeration, and not to 'use' the lock, but to let the design of IDisposable on the enumerator itself work as intended.

/// <summary>
/// Gets a synchronized enumerator.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="getEnumeratorFunction">The get enumerator function.</param>
/// <returns></returns>
public IEnumerator<TValue> GetSynchronizedEnumerator<TValue>(Func<T, IEnumerator<TValue>> getEnumeratorFunction) {
    Guard.ArgumentNotNull(getEnumeratorFunction, "getEnumeratorFunction");

    //cheat here and write block for enumeration.
    //otherwize a write during a long enumeration can cause a race.
    SynchronizedWriter synchronizedWriter = null;
    SynchronizedEnumerator<TValue> synchronizedEnumerator = null;
    try {
        synchronizedWriter = new SynchronizedWriter(_readerWriter);
        IEnumerator<TValue> enumerator = getEnumeratorFunction(_instance);
        synchronizedEnumerator = new SynchronizedEnumerator<TValue>(synchronizedWriter, enumerator);
        return synchronizedEnumerator;
        //When the enumerator disposes, the lock is released.
    } catch {
        if (synchronizedEnumerator != null) {
            synchronizedEnumerator.Dispose();
        } else if (synchronizedWriter != null) {
            synchronizedWriter.Dispose();
        }
        throw;
    }
}

The linked code has been updated.

Comments

No Comments

Leave a Comment

(required)  
(optional)
(required)  
Add