4 using System.Collections.Generic;
7 using System.Threading.Tasks;
9 namespace SiliconStudio.Core.Serialization.Assets
11 partial class AssetManager
15 private Stack<AssetReference> stack =
new Stack<AssetReference>();
16 private uint nextCollectIndex;
23 internal void IncrementReference(AssetReference assetReference,
bool publicReference)
27 assetReference.PublicReferenceCount++;
31 assetReference.PrivateReferenceCount++;
40 internal void DecrementReference(AssetReference assetReference,
bool publicReference)
45 referenceCount = --assetReference.PublicReferenceCount;
46 if (referenceCount < 0)
47 throw new InvalidOperationException(
"Cannot release an object that doesn't have active public references. Load/Unload pairs must match.");
49 referenceCount += assetReference.PrivateReferenceCount;
53 referenceCount = --assetReference.PrivateReferenceCount;
54 if (referenceCount < 0)
55 throw new InvalidOperationException(
"Cannot release an object that doesn't have active private references. This is either due to non-matching Load/Unload pairs or an engine internal error.");
57 referenceCount += assetReference.PublicReferenceCount;
60 if (referenceCount == 0)
63 ReleaseAsset(assetReference);
66 foreach (var reference
in assetReference.References)
68 DecrementReference(reference,
false);
71 else if (publicReference && assetReference.PublicReferenceCount == 0)
74 CollectUnreferencedCycles();
82 private void ReleaseAsset(AssetReference assetReference)
84 var referencable = assetReference.Object as IReferencable;
85 if (referencable != null)
87 referencable.Release();
91 var disposable = assetReference.Object as IDisposable;
92 if (disposable != null)
99 var oldPrev = assetReference.Prev;
100 var oldNext = assetReference.Next;
102 oldPrev.Next = oldNext;
104 oldNext.Prev = oldPrev;
109 loadedAssetsByUrl.Remove(assetReference.ObjectId);
111 loadedAssetsByUrl[assetReference.ObjectId] = oldNext;
113 loadedAssetsUrl.Remove(assetReference.Object);
115 assetReference.Object = null;
118 internal void CollectUnreferencedCycles()
121 var currentCollectIndex = nextCollectIndex++;
122 foreach (var asset
in loadedAssetsByUrl)
124 var currentAsset = asset.Value;
127 if (asset.Value.PublicReferenceCount > 0)
128 stack.Push(asset.Value);
129 currentAsset = currentAsset.Next;
131 while (currentAsset != null);
135 while (stack.Count > 0)
140 var collectIndex = v.CollectIndex;
141 if (collectIndex != currentCollectIndex)
143 v.CollectIndex = currentCollectIndex;
144 foreach (var reference
in v.References)
146 if (reference.CollectIndex != currentCollectIndex)
147 stack.Push(reference);
155 foreach (var asset
in loadedAssetsByUrl)
157 var currentAsset = asset.Value;
160 if (asset.Value.CollectIndex != currentCollectIndex)
162 stack.Push(asset.Value);
164 currentAsset = currentAsset.Next;
166 while (currentAsset != null);
172 foreach (var assetReference
in stack)
174 ReleaseAsset(assetReference);