Skip to content

Commit

Permalink
Asset lookup registration rework (#15)
Browse files Browse the repository at this point in the history
* Experiments.

* AssetFileEntry, disconnected lookup registration from autoload.

* Various fixes.

(cherry picked from commit 4f5b280182a4e5f8bbf05caa18e96e9a13284c07)

* Removed unused junk.
  • Loading branch information
Mirsario committed Nov 13, 2021
1 parent ab2891c commit 04581a5
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 91 deletions.
19 changes: 11 additions & 8 deletions Src/IO/Asset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public abstract class Asset
/// <summary> The state of this asset. </summary>
public AssetState State { get; internal set; }

/// <summary> The source of this asset. Can be null. </summary>
public AssetSource Source { get; internal set; }
/// <summary> The file source of this asset. Can be null. </summary>
public AssetFileEntry? File { get; internal set; }

/// <summary> Whether or not this asset is currently being loaded. </summary>
public bool IsLoading => State == AssetState.Loading;
Expand Down Expand Up @@ -111,7 +111,7 @@ private async Task Load(AssetRequestMode mode)
var asyncContext = new ContinuationScheduler(this);

string extension = Path.GetExtension(AssetPath);
var readerByExtension = Assets.ReadersByDataType<T>.ReaderByExtension;
var readerByExtension = Assets.AssetTypeData<T>.ReaderByExtension;

if (readerByExtension.Count == 0) {
throw new InvalidOperationException($"No asset reader found with a return type of '{typeof(T).Name}'.");
Expand All @@ -125,23 +125,26 @@ private async Task Load(AssetRequestMode mode)
await Task.Yield(); // This transfers the method's execution to a worker thread.
}

using var stream = Source.OpenStream(AssetPath);

Value = await assetReader.ReadFromStream(stream, AssetPath, new MainThreadCreationContext(asyncContext));
Value = await assetReader.ReadAsset(File, new MainThreadCreationContext(asyncContext));

State = AssetState.Loaded;
}

private void SafelyWaitForLoad(Task loadTask, bool tracked)
{
if (State == AssetState.Loaded)
if (State == AssetState.Loaded) {
return;
}

if (!loadTask.IsCompleted && Assets.IsMainThread) {
while (Continuation == null) {
while (Continuation == null && State != AssetState.Loaded) {
Thread.Yield();
}

if (State == AssetState.Loaded) {
return;
}

if (tracked) {
lock (Assets.RequestLock) {
Continuation();
Expand Down
21 changes: 21 additions & 0 deletions Src/IO/AssetFileEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.IO;

namespace Dissonance.Engine.IO
{
public class AssetFileEntry
{
public readonly string Path;
public readonly AssetSource Source;

public AssetFileEntry(string path, AssetSource source)
{
Path = path;
Source = source;
}

public Stream OpenStream()
{
return Source.OpenStream(Path);
}
}
}
48 changes: 38 additions & 10 deletions Src/IO/AssetLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal static class AssetLookup

internal static class AssetLookup<T>
{
private static readonly ConcurrentDictionary<string, Asset<T>> lookup = new();
private static readonly ConcurrentDictionary<string, (string assetPath, Asset<T> asset)> lookup = new();

public static int Count => lookup.Count;

Expand All @@ -24,21 +24,49 @@ static AssetLookup()
};
}

public static void Register(string name, Asset<T> asset)
public static void Register(string name, string path, Asset<T> asset)
{
if (lookup.ContainsKey(name)) {
//throw new Exception($"Cannot register two {typeof(T).Name} with the same name: {name}.");
if (lookup.TryGetValue(name, out var existingTuple) && existingTuple.assetPath == path) {
lookup[name] = (null, null); // This marks the registry as ambiguous.
} else {
lookup[name] = (path, asset);
}
}

public static Asset<T> Get(string fullName, AssetRequestMode mode = AssetRequestMode.DoNotLoad)
{
var tuple = lookup[fullName];

asset = null; // This marks the registry as ambiguous.
if (tuple.assetPath == null && tuple.asset == null) {
throw new ArgumentException($"Key '{fullName}' is ambiguous.");
}

lookup[name] = asset;
if (tuple.asset == null) {
tuple.asset = Assets.Get<T>(tuple.assetPath, mode);
lookup[fullName] = tuple;
}

return tuple.asset;
}

public static Asset<T> Get(string fullName)
=> lookup[fullName] ?? throw new ArgumentException($"Key '{fullName}' is ambiguous.");
public static bool TryGet(string fullName, out Asset<T> result, AssetRequestMode mode = AssetRequestMode.DoNotLoad)
{
var tuple = lookup[fullName];

if (tuple.assetPath == null && tuple.asset == null) {
result = null;

return false;
}

public static bool TryGetValue(string fullName, out Asset<T> value)
=> lookup.TryGetValue(fullName, out value) && value != null;
if (tuple.asset == null) {
tuple.asset = Assets.Get<T>(tuple.assetPath, mode);
lookup[fullName] = tuple;
}

result = tuple.asset;

return true;
}
}
}
Loading

0 comments on commit 04581a5

Please sign in to comment.