Non-Locking Reference Counting

I am working on a system requiring extensive C API interaction. Part of the interaction requires initialization and shutdown of the system in question before and after any operations. Failure to do so will lead to instability in the system. I accomplished this by simply doing the reference count in the base class of the one-time environment as follows:

public FooEnvironment()
{
  lock(EnvironmentLock)
  {
    if(_initCount == 0)
    {
      Init();  // global startup
    }
    _initCount++;
  }
}

private void Dispose(bool disposing)
{
  if(_disposed)
    return;

  if(disposing)
  {
    lock(EnvironmentLock)
    {
      _initCount--;
      if(_initCount == 0)
      {
        Term(); // global termination
      }
    }
  }
}

It works great and achieves the goal. However, since any interop operation must be nested in the FooEnvironment block, we lock all the time, and profiling shows that this lock is about 50% of the work performed at runtime. It seems to me that this is a fairly fundamental concept that something in .NET or the CLR should solve the problem. Is there a better way to do link counting?

+5
7

, . , Interlocked.Increment . , , - CAS (Compare-And-Swap).

, - , - - , heisenbugs.

, . , " ". , .

, , . , , . , , , . , , .

+5

harold's Interlocked:

public FooEnvironment() {
  if (Interlocked.Increment(ref _initCount) == 1) {
    Init();  // global startup
  }
}

private void Dispose(bool disposing) {
  if(_disposed)
    return;

  if (disposing) {
    if (0 == Interlocked.Decrement(ref _initCount)) {
      Term(); // global termination
    }
  }
}

Increment Decrement ( ), , .

: , - concurrency. Interlocked , ( Interlocked ). Init() , .

+2

, . - - .

0

, Interlocked.Increment/Decrement.

. , , Init() . Dispose , , init - reset, . , , SpinLock, InterlockedIncrement, .

static ManualResetEvent _inited = new ManualResetEvent(false);
public FooEnvironment()
{
    if(Interlocked.Increment(ref _initCount) == 1)
    {
        Init();  // global startup
        _inited.Set();
    }

    _inited.WaitOne();
}

private void Dispose(bool disposing)
{
    if(_disposed)
        return;

    if(disposing)
    {
        if(Interlocked.Decrement(ref _initCount) == 0)
        {
            _inited.Reset();
            Term(); // global termination
        }
    }
}

Edit:
, , Init Term, Init Term, , , 50% , , Init, .

0

, . , , .

Dispose / ( ). Dispose - disposing. , .

, .

public class FooEnvironment
{
    private static int _initCount;
    private static bool _initialized;
    private static object _environmentLock = new object();

    private bool _disposed;

    public FooEnvironment()
    {
        Interlocked.Increment(ref _initCount);

        if (_initCount > 0 && !_initialized)
        {
            lock (_environmentLock)
            {
                if (_initCount > 0 && !_initialized)
                {
                    Init(); // global startup
                    _initialized = true;
                }
            }
        }
    }

    private void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            // Dispose managed resources here
        }

        Interlocked.Decrement(ref _initCount);

        if (_initCount <= 0 && _initialized)
        {
            lock (_environmentLock)
            {
                if (_initCount <= 0 && _initialized)
                {
                    Term(); // global termination
                    _initialized = false;
                }
            }
        }

        _disposed = true;
    }

    ~FooEnvironment()
    {
        Dispose(false);
    }
}
0

Threading.Interlocked.Increment , , , . . Interlocked.Increment , , . , , , , , , - , - , waylaid.

, .net , Concurrent , . , , , - ConcurrentBag. , , , . , , , . , . , "". , -, "" . , , , , - , , , (, , ). , , , , . , , , .

, Threading.Interlocked.Increment, , , , ConcurrentBag . 1 Interlocked.Increment - , 2 , 2 1 , , 1 , , , , , , . , , 1 , . . ConcurrentBag, , , . , , , , , .

, , ConcurrentBag, , , , .

0

, , , .

Term(), / ?

Init() , API, Term(). :

static FooEnvironment() { 
    Init();  // global startup 
}

CLR , , - .

( ) , Term() . . . http://www.codeproject.com/Articles/16164/Managed-Application-Shutdown

0

All Articles