/// <summary> /// Removes the registered instance from the dictionary. /// </summary> internal static void DeregisterHandle(IntPtr handle, SKObject instance) { if (handle == IntPtr.Zero) { return; } if (instance is ISKSkipObjectRegistration) { return; } instancesLock.EnterWriteLock(); try { var existed = instances.TryGetValue(handle, out var weak); if (existed && (!weak.IsAlive || weak.Target == instance)) { instances.Remove(handle); } else { #if THROW_OBJECT_EXCEPTIONS InvalidOperationException ex = null; if (!existed) { // the object may have been replaced if (!instance.IsDisposed) { // recoverable error // there was no object there, but we are still alive ex = new InvalidOperationException( $"A managed object did not exist for the specified native object. " + $"H: {handle.ToString ("x")} Type: {instance.GetType ()}"); } } else if (weak.Target is SKObject o && o != instance) { // there was an object in the dictionary, but it was NOT this object if (!instance.IsDisposed) { // recoverable error // there was a new living object there, but we are still alive ex = new InvalidOperationException( $"Trying to remove a different object with the same native handle. " + $"H: {handle.ToString ("x")} Type: ({o.GetType ()}, {instance.GetType ()})"); } } if (ex != null) { if (instance.fromFinalizer) { exceptions.Add(ex); } else { throw ex; } } #endif } } finally { instancesLock.ExitWriteLock(); } }
/// <summary> /// Registers the specified instance with the dictionary. /// </summary> internal static void RegisterHandle(IntPtr handle, SKObject instance) { if (handle == IntPtr.Zero || instance == null) { return; } if (instance is ISKSkipObjectRegistration) { return; } SKObject objectToDispose = null; instancesLock.EnterWriteLock(); try { if (instances.TryGetValue(handle, out var oldValue) && oldValue.Target is SKObject obj && !obj.IsDisposed) { #if THROW_OBJECT_EXCEPTIONS if (obj.OwnsHandle) { // a mostly recoverable error // if there is a managed object, then maybe something happened and the native object is dead throw new InvalidOperationException( $"A managed object already exists for the specified native object. " + $"H: {handle.ToString ("x")} Type: ({obj.GetType ()}, {instance.GetType ()})"); } #endif // this means the ownership was handed off to a native object, so clean up the managed side objectToDispose = obj; } instances[handle] = new WeakReference(instance); } finally { instancesLock.ExitWriteLock(); } // dispose the object we just replaced objectToDispose?.DisposeInternal(); }