Beispiel #1
0
        static internal void UnsubscribeFromEvent(AObject receiver, RefCounted sender, uint eventType)
        {
            List <EventSubscription> eventReceivers;

            if (!eventReceiverLookup.TryGetValue(eventType, out eventReceivers))
            {
                return;
            }

            AObject obj;

            foreach (EventSubscription er in eventReceivers)
            {
                if (!er.Receiver.TryGetTarget(out obj))
                {
                    continue; // GC'd
                }
                if (obj == receiver &&
                    (sender == null || er.Sender == sender.nativeInstance))
                {
                    eventReceivers.Remove(er);
                    return;
                }
            }
        }
        public void Add(RefCounted refCounted, RefType refType = RefType.REF_DEFAULT)
        {
            lock (knownObjects)
            {
                ReferenceHolder <RefCounted> knownObject;
                if (knownObjects.TryGetValue(refCounted.nativeInstance, out knownObject))
                {
                    var existingObj = knownObject?.Reference;

                    // this is another check verifying correct RefCounted by using type, which isn't a good test
                    if (existingObj != null && !IsInHierarchy(existingObj.GetType(), refCounted.GetType()))
                    {
                        throw new InvalidOperationException($"NativeInstance '{refCounted.nativeInstance}' is in use by '{existingObj.GetType().Name}' (IsDeleted={existingObj.nativeInstance == IntPtr.Zero}). {refCounted.GetType()}");
                    }
                }

                // first check if explicit strong reference
                bool strongRef = refType == RefType.REF_STRONG;

                if (!strongRef)
                {
                    strongRef = StrongRefByDefault(refCounted);
                }

                knownObjects[refCounted.nativeInstance] = new ReferenceHolder <RefCounted>(refCounted, !strongRef);
            }
        }
Beispiel #3
0
        // register a newly created native
        public static IntPtr RegisterNative(IntPtr native, RefCounted r, InstantiationType instantiationType = InstantiationType.INSTANTIATION_NET)
        {
            if (native == IntPtr.Zero || r == null)
            {
                throw new InvalidOperationException("NativeCore.RegisterNative - native == IntPtr.Zero || RefCounted instance == null");
            }

            if (instantiationType == InstantiationType.INSTANTIATION_NET)
            {
                if (r.nativeInstance != IntPtr.Zero)
                {
                    throw new InvalidOperationException("NativeCore.RegisterNative - NET Instantiated RefCounted with initialized nativeInstance");
                }

                r.nativeInstance = native;
            }

            r.InstantiationType = instantiationType;
            r.InternalInit();

            refCountedCache.Add(r);

            r.PostNativeUpdate();

            return(native);
        }
Beispiel #4
0
        // wraps an existing native instance, with downcast support
        public static T WrapNative <T>(IntPtr native) where T : RefCounted
        {
            if (native == IntPtr.Zero)
            {
                return(null);
            }

            RefCounted r;
            WeakReference <RefCounted> w;

            // first see if we're already available
            if (nativeLookup.TryGetValue(native, out w))
            {
                if (w.TryGetTarget(out r))
                {
                    // we're alive!
                    return((T)r);
                }
                else
                {
                    // we were seen before, but have since been GC'd, remove!
                    nativeLookup.Remove(native);

                    if (csi_Atomic_RefCounted_Refs(native) == 1)
                    {
                        // only managed ref remains, so release and return null
                        csi_AtomicEngine_ReleaseRef(native);
                        return(null);
                    }

                    csi_AtomicEngine_ReleaseRef(native);
                }
            }

            IntPtr classID = RefCounted.csi_Atomic_RefCounted_GetClassID(native);

            // and store, with downcast support for instance Component -> StaticModel
            // we never want to hit this path for script inherited natives

            NativeType nativeType;

            if (!nativeClassIDToNativeType.TryGetValue(classID, out nativeType))
            {
                throw new InvalidOperationException("NativeCore.WrapNative - Attempting to wrap unknown native class id");
            }

            r = nativeType.managedConstructor(native);

            w = new WeakReference <RefCounted>(r);
            NativeCore.nativeLookup[native] = w;

            // store a ref, so native side will not be released while we still have a reference in managed code
            r.AddRef();

            return((T)r);
        }
        public static IntPtr RegisterNative(IntPtr native, RefCounted r)
        {
            r.nativeInstance = native;

            var w = new WeakReference(r);

            NativeCore.nativeLookup [r.RefID] = w;
            r.AddRef();

            return(native);
        }
Beispiel #6
0
        // register a newly created native
        public static IntPtr RegisterNative(IntPtr native, RefCounted r)
        {
            r.nativeInstance = native;

            var w = new WeakReference(r);

            NativeCore.nativeLookup [native] = w;
            // keep native side alive
            r.AddRef();

            return(native);
        }
Beispiel #7
0
        /// <summary>
        ///  Runs a GC collection, waits for any finalizers, and then expires any natives collected
        /// </summary>
        public static void RunGC()
        {
            // run a GC collection
            GC.Collect();
            // finalizers can run on any thread, we're explicitly running a GC here
            // so wait for all the finalizers to finish
            GC.WaitForPendingFinalizers();
            // Anything finalized on another thread will now be available to release
            // in main thread
            RefCounted.ReleaseFinalized();

            ExpireNatives();
        }
Beispiel #8
0
        // wraps an existing native instance, with downcast support
        public static T WrapNative <T>(IntPtr native) where T : RefCounted
        {
            if (native == IntPtr.Zero)
            {
                throw new InvalidOperationException("NativeCore.WrapNative - Attempting to wrap native instance IntPtr.Zero");
            }

            var reference = refCountedCache.Get(native)?.Reference;

            // This isn't really a good test to verify right object, better to test if not a T and error?
            if (reference is T)
            {
                return((T)reference);
            }

            IntPtr classID = RefCounted.csi_Atomic_RefCounted_GetClassID(native);

            // Check whether this is a valid native class to wrap
            NativeType nativeType;

            if (!nativeClassIDToNativeType.TryGetValue(classID, out nativeType))
            {
                if (logWrapUnknownNative)
                {
                    Log.Info("WrapNative returning null for unknown class: " + GetNativeTypeName(native));
                }

                return(null);
            }

            // TODO: make CSComponent abstract and have general abstract logic here?
            if (nativeType.Type == typeof(CSComponent))
            {
                return(null);
            }

            // Construct managed instance wrapper for native instance
            // this has downcast support for instance Component -> StaticModel
            // note, we never want to hit this path for script inherited natives

            var r = nativeType.managedConstructor(native);

            // IMPORTANT: if a RefCounted instance is created in managed code, has reference count increased in native code
            // and managed side is GC'd, the original NET created instance will be gone and we can get it back here reported
            // as instantiated in native code.  May want a transative boolean to be able to tell when an object has passed this "barrier"
            // which is somewhat common
            RegisterNative(native, r, InstantiationType.INSTANTIATION_NATIVE);

            return((T)r);
        }
Beispiel #9
0
        // register a newly created native
        public static IntPtr RegisterNative(IntPtr native, RefCounted r)
        {
            if (nativeLookup.ContainsKey(native))
            {
                throw new InvalidOperationException("NativeCore.RegisterNative - Duplicate IntPtr key");
            }

            r.nativeInstance = native;
            // keep native side alive
            r.AddRef();

            nativeLookup[native] = new WeakReference <RefCounted>(r);

            return(native);
        }
        // wraps an existing native instance, with downcast support
        public static T WrapNative <T> (IntPtr native) where T : RefCounted
        {
            if (native == IntPtr.Zero)
            {
                return(null);
            }

            // instance id
            uint id = csb_Atomic_RefCounted_GetRefID(native);

            WeakReference w;

            // first see if we're already available
            if (nativeLookup.TryGetValue(id, out w))
            {
                if (w.IsAlive)
                {
                    // we're alive!
                    return((T)w.Target);
                }
                else
                {
                    // we were seen before, but have since been GC'd, remove!
                    nativeLookup.Remove(id);
                }
            }

            IntPtr classID = RefCounted.csb_Atomic_RefCounted_GetClassID(native);

            // and store, with downcast support for instance Component -> StaticModel
            // we never want to hit this path for script inherited natives

            RefCounted r = nativeClassIDToManagedConstructor[classID](native);

            w = new WeakReference(r);
            NativeCore.nativeLookup [id] = w;

            // store a ref, so native side will not be released while we still have a reference in managed code
            r.AddRef();

            return((T)r);
        }
 /// <summary>
 /// Some types are stored with a StrongRef by default, to help avoid Object churn and support explicit Disposing
 /// </summary>
 bool StrongRefByDefault(RefCounted refCounted)
 {
     if (refCounted is Scene)
     {
         return(true);
     }
     if (refCounted is Node)
     {
         return(true);
     }
     if (refCounted is Context)
     {
         return(true);
     }
     if (refCounted is Component)
     {
         return(true);
     }
     return(false);
 }
        public static void ReleaseExpiredNativeReferences()
        {
            List <uint> released = new List <uint> ();

            foreach (KeyValuePair <uint, WeakReference> entry in nativeLookup)
            {
                if (entry.Value.Target == null || !entry.Value.IsAlive)
                {
                    released.Add(entry.Key);
                }
                else
                {
                }
            }

            foreach (uint id in released)
            {
                // use safe release
                RefCounted.SafeReleaseRef(id);
                nativeLookup.Remove(id);
            }
        }
        // wraps an existing native instance, with downcast support
        public static T WrapNative <T>(IntPtr native) where T : RefCounted
        {
            if (native == IntPtr.Zero)
            {
                return(null);
            }

            RefCounted r;
            WeakReference <RefCounted> w;

            // first see if we're already available
            if (nativeLookup.TryGetValue(native, out w))
            {
                if (w.TryGetTarget(out r))
                {
                    // we're alive!
                    return((T)r);
                }
                else
                {
                    // we were seen before, but have since been GC'd, remove!
                    nativeLookup.Remove(native);

                    if (csi_Atomic_RefCounted_Refs(native) == 1)
                    {
                        // only managed ref remains, so release and return null
                        csi_AtomicEngine_ReleaseRef(native);
                        return(null);
                    }

                    csi_AtomicEngine_ReleaseRef(native);
                }
            }

            IntPtr classID = RefCounted.csi_Atomic_RefCounted_GetClassID(native);

            // and store, with downcast support for instance Component -> StaticModel
            // we never want to hit this path for script inherited natives

            NativeType nativeType;

            if (!nativeClassIDToNativeType.TryGetValue(classID, out nativeType))
            {
                throw new InvalidOperationException("NativeCore.WrapNative - Attempting to wrap unknown native class id");
            }

            // TODO: make CSComponent abstract and have general abstract logic here?
            if (nativeType.Type == typeof(CSComponent))
            {
                return(null);
            }

            r = nativeType.managedConstructor(native);

            w = new WeakReference <RefCounted>(r);
            NativeCore.nativeLookup[native] = w;

            // store a ref, so native side will not be released while we still have a reference in managed code
            r.AddRef();

            // Note: r.InstantiationType may be INSTANTIATION_NET here is we were GC'd, native still had a reference, and we came back
            if (r.InstantiationType == InstantiationType.INSTANTIATION_NET)
            {
                //Log.Warn($"Wrapped {r.GetType().Name} was originally instantiated in NET, changing to native, this is likely an error");
                //r.InstantiationType = InstantiationType.INSTANTIATION_NATIVE;
            }

            r.PostNativeUpdate();

            return((T)r);
        }
 static private void registerSubsystem(RefCounted subsystem)
 {
     subSystems[subsystem.GetType()] = subsystem;
 }
Beispiel #15
0
 public Skeleton(RefCounted owner, IntPtr nativeSkeleton)
 {
     this.owner          = owner;
     this.nativeSkeleton = nativeSkeleton;
 }
Beispiel #16
0
 public Skeleton(RefCounted owner, IntPtr nativeSkeleton)
 {
     this.owner = owner;
     this.nativeSkeleton = nativeSkeleton;
 }
Beispiel #17
0
 public static void UpdateDispatch(float timeStep)
 {
     RefCounted.ReleaseFinalized();
 }