NativeCore.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using System;
  2. using System.Collections.Generic;
  3. namespace AtomicEngine
  4. {
  5. static class NativeCore
  6. {
  7. // given an existing instance classID, construct the managed instance, with downcast support (ask for Component, get StaticModel for example)
  8. public static Dictionary<IntPtr, Func<IntPtr, RefCounted>> nativeClassIDToManagedConstructor = new Dictionary<IntPtr, Func<IntPtr, RefCounted>>();
  9. public static Dictionary<IntPtr, WeakReference> nativeLookup = new Dictionary<IntPtr, WeakReference> ();
  10. public static IntPtr RegisterNative (IntPtr native, RefCounted r)
  11. {
  12. var w = new WeakReference (r);
  13. NativeCore.nativeLookup [native] = w;
  14. RefCounted._AddRef (native);
  15. return native;
  16. }
  17. public static void ReleaseExpiredNativeReferences()
  18. {
  19. List<IntPtr> released = new List<IntPtr> ();
  20. foreach(KeyValuePair<IntPtr, WeakReference> entry in nativeLookup)
  21. {
  22. if (entry.Value.Target == null || !entry.Value.IsAlive) {
  23. released.Add (entry.Key);
  24. } else {
  25. }
  26. }
  27. foreach (IntPtr native in released) {
  28. RefCounted._ReleaseRef(native);
  29. nativeLookup.Remove (native);
  30. }
  31. }
  32. // wraps an existing native instance, with downcast support
  33. public static T WrapNative<T> (IntPtr native) where T:RefCounted
  34. {
  35. if (native == IntPtr.Zero)
  36. return null;
  37. WeakReference w;
  38. // first see if we're already available
  39. if (nativeLookup.TryGetValue (native, out w)) {
  40. if (w.IsAlive) {
  41. // we're alive!
  42. return (T)w.Target;
  43. } else {
  44. // we were seen before, but have since been GC'd, remove!
  45. nativeLookup.Remove (native);
  46. }
  47. }
  48. IntPtr classID = RefCounted.csb_RefCounted_GetClassID (native);
  49. // and store, with downcast support for instance Component -> StaticModel
  50. w = new WeakReference (nativeClassIDToManagedConstructor[classID](native));
  51. NativeCore.nativeLookup [native] = w;
  52. // store a ref, so native side will not be released while we still have a reference in managed code
  53. RefCounted._AddRef (native);
  54. return (T) w.Target;
  55. }
  56. }
  57. }