title: Handling shared ownership of unmanaged resources with object resurrection
body: <p>I am currently working on a project using OpenGL via the OpenTK library. OpenGL objects like buffers or shaders are all unmanaged resources that come as an integer id. The majority of objects in my program are reference an OpenGL resource. It is also very common that the same resource is used by <strong>multiple different</strong> objects.</p>
  <p>All OpenGL resources are derived from a <code>GLObject</code> class that implements <code>IDisposable</code>. When dealing with single ownership manually calling <code>Dispose()</code> works fine. However when having shared ownership you have the problem of not really knowing anymore when to actually call Dispose().</p>
  <p>I am trying to find a solution that doesn't require me to manually keep track on how many objects reference a GLObject to know when to call <code>Dispose()</code>. Deleting OpenGL resources also needs to happen from the thread where the context is current so it can't be done from the finalizer.</p>
  <p>What I ended up coming up with was just letting my objects getting garbage collected without disposing and then resurrect them to a garbage queue:</p>
  <pre><code>abstract class GLObject : IDisposable
  {
      public int ID { get; protected set; }
  
      ~GLObject()
      {           
          Renderer.garbage.Enqueue(this);
      }
  
      public void Dispose()
      {
          FreeGPURessource();
  
          GC.SuppressFinalize(this);
      }
  
      public abstract void FreeGPURessource();
  }
  </code></pre>
  <p>.</p>
  <pre><code>public static ConcurrentQueue&lt;GLObject&gt; garbage = new ConcurrentQueue&lt;GLObject&gt;();
  </code></pre>
  <p>At an appropriate time my application then calls the CollectGarbage() method from the correct thread:</p>
  <pre><code>public static void CollectGarbage()
  {
      while (garbage.TryDequeue(out GLObject ressource))
      {
          ressource.Dispose();
      }
  }
  </code></pre>
  <p><strong>Is this something I can/should rely on working without any side effects?</strong></p>
  <p>This smells like it might be a really bad practice.</p>