RefCounted.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //
  2. // TODO: optimization, remove the static initializer, so we do not need to add code
  3. // at JIT/AOT time to probe for static class initialization
  4. //
  5. using System;
  6. using System.Diagnostics;
  7. using System.Runtime.InteropServices;
  8. using Urho.IO;
  9. namespace Urho {
  10. public partial class RefCounted : IDisposable {
  11. internal IntPtr handle;
  12. public IntPtr Handle => handle;
  13. internal RefCounted (UrhoObjectFlag empty) { }
  14. protected RefCounted (IntPtr handle)
  15. {
  16. if (handle == IntPtr.Zero)
  17. throw new ArgumentException ($"Attempted to instantiate a {GetType()} with a null handle");
  18. this.handle = handle;
  19. Runtime.RegisterObject (this);
  20. }
  21. public void Dispose ()
  22. {
  23. DeleteNativeObject();
  24. Dispose (true);
  25. GC.SuppressFinalize (this);
  26. }
  27. /// <summary>
  28. /// Called by RefCounted::~RefCounted - we don't need to check Refs here - just mark it as deleted and remove from cache
  29. /// </summary>
  30. internal void HandleNativeDelete()
  31. {
  32. LogSharp.Trace($"{GetType().Name}: HandleNativeDelete");
  33. Dispose(true);
  34. GC.SuppressFinalize(this);
  35. }
  36. [DllImport(Consts.NativeImport, CallingConvention = CallingConvention.Cdecl)]
  37. static extern void TryDeleteRefCounted(IntPtr handle);
  38. /// <summary>
  39. /// Try to delete underlying native object if nobody uses it (Refs==0)
  40. /// </summary>
  41. void DeleteNativeObject()
  42. {
  43. if (!IsDeleted && AllowNativeDelete)
  44. {
  45. LogSharp.Trace($"{GetType().Name}: DeleteNativeObject");
  46. TryDeleteRefCounted(handle);
  47. }
  48. }
  49. protected virtual void Dispose (bool disposing)
  50. {
  51. if (IsDeleted)
  52. return;
  53. if (disposing)
  54. {
  55. IsDeleted = true;
  56. OnDeleted();
  57. }
  58. Runtime.UnregisterObject(handle);
  59. }
  60. protected void CheckEngine()
  61. {
  62. UrhoPlatformInitializer.DefaultInit();
  63. }
  64. /// <summary>
  65. /// True if underlying native object is deleted
  66. /// </summary>
  67. public bool IsDeleted { get; private set; }
  68. protected virtual void OnDeleted() { }
  69. protected virtual bool AllowNativeDelete => true;
  70. public override bool Equals (object other)
  71. {
  72. if (other == null)
  73. return false;
  74. if (other.GetType () != GetType ())
  75. return false;
  76. var or = other as RefCounted;
  77. if (or != null && or.handle == handle)
  78. return true;
  79. return false;
  80. }
  81. public static bool operator ==(RefCounted _a, RefCounted _b)
  82. {
  83. object a = _a;
  84. object b = _b;
  85. if (a == null){
  86. if (b == null)
  87. return true;
  88. return false;
  89. } else {
  90. if (b == null)
  91. return false;
  92. return _a.handle == _b.handle;
  93. }
  94. }
  95. public static bool operator !=(RefCounted _a, RefCounted _b)
  96. {
  97. object a = _a;
  98. object b = _b;
  99. if (a == null)
  100. return b != null;
  101. else {
  102. if (b == null)
  103. return true;
  104. return _a.handle != _b.handle;
  105. }
  106. }
  107. public override int GetHashCode ()
  108. {
  109. if (IntPtr.Size == 8) //means 64bit
  110. return unchecked ((int) (long) handle);
  111. return (int) handle;
  112. }
  113. ~RefCounted ()
  114. {
  115. DeleteNativeObject();
  116. Dispose (false);
  117. }
  118. }
  119. }