コード例 #1
0
 private void RemoveParent(THandle obj,
                           UnmanagedObjectContext <THandleClass, THandle> trackedObjectContext,
                           Tuple <THandleClass, THandle> dep)
 {
     if (trackedObjectContext.parentCollection == null ||
         !trackedObjectContext.parentCollection.Remove(dep.Item1, dep.Item2))
     {
         throw new EParentNotFound <THandleClass, THandle>(dep.Item1, dep.Item2);
     }
     Unregister(dep.Item1, dep.Item2);
 }
コード例 #2
0
        private void AddParent(UnmanagedObjectContext <THandleClass, THandle> trackedObjectContext,
                               Tuple <THandleClass, THandle> dep)
        {
            UnmanagedObjectContext <THandleClass, THandle> depContext;

            if (!_trackedObjects.TryGetValue(dep, out depContext))
            {
                throw new EObjectNotFound <THandleClass, THandle>(dep.Item1, dep.Item2);
            }
            if (trackedObjectContext.parentCollection == null)
            {
                trackedObjectContext.InitParentCollection();
            }
            if (trackedObjectContext.parentCollection.Add(dep.Item1, dep.Item2))
            {
                depContext.AddRefCount();
            }
        }
コード例 #3
0
        public void Register(THandleClass handleClass, THandle obj,
                             UnmanagedObjectContext <THandleClass, THandle> .DestroyHandleDelegate destroyHandle = null,
                             HandleCollection <THandleClass, THandle> parentCollection = null)
        {
            UnmanagedObjectContext <THandleClass, THandle> existingContextObj;
            var handleContainer = new HandleContainer(handleClass, obj);
            var trackedObject   = new UnmanagedObjectContext <THandleClass, THandle>
            {
                DestroyHandle    = destroyHandle,
                parentCollection = parentCollection
            };

            do
            {
                if ((existingContextObj = _trackedObjects.GetOrAdd(handleContainer, trackedObject)) == trackedObject)
                {
                    if (parentCollection == null)
                    {
                        return;
                    }
                    foreach (var dep in trackedObject.parentCollection)
                    {
                        UnmanagedObjectContext <THandleClass, THandle> depContext;
                        if (!_trackedObjects.TryGetValue(dep, out depContext))
                        {
                            throw new EObjectNotFound <THandleClass, THandle>(dep.Item1, dep.Item2);
                        }
                        depContext.AddRefCount();
                    }
                    return;
                }

                /* If object already existed, under normal conditions AddRefCount() must return a value > 1.
                 * If it returns <= 1 it means it just got decremented in another thread, reached zero and
                 * it's about to be destroyed. So we will have to wait for that to happen and try again our
                 * entire operation */
                var newRefCount = existingContextObj.AddRefCount();
                if (newRefCount <= 0)
                {
                    throw new EInvalidRefCount <THandleClass, THandle>(handleClass, obj, newRefCount);
                }
                if (newRefCount > 1)
                {
                    break;
                }

                /* Object is getting removed in another thread. Let's spin while we wait for it to be gone
                 * from our _trackedObjects container */
                while (_trackedObjects.TryGetValue(handleContainer, out existingContextObj))
                {
                    Thread.Yield();
                }
            } while (true);

            /* Object already exists, could be an stale object not yet garbage collected,
             * so we will set the new cleanup methods in place of the current ones */
            existingContextObj.DestroyHandle = destroyHandle;
            if (parentCollection == null)
            {
                return;
            }
            foreach (var dep in parentCollection)
            {
                AddParent(existingContextObj, dep);
            }
        }