Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added decorators for AssetLoader functions
AssetLoader functions will now notify passed Promise of exceptions
Changed DcParams#combineFrames from boolean to int [-1 (auto), 0 (don't combine), 1 (combine)]
  • Loading branch information
collinsmith committed Dec 6, 2021
1 parent 8dec043 commit 9dfe541
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 60 deletions.
85 changes: 80 additions & 5 deletions core/src/main/java/com/riiablo/asset/AssetLoader.java
Expand Up @@ -2,18 +2,93 @@

import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;

import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;

public abstract class AssetLoader<T> {
protected Array<AssetDesc> dependencies(AssetDesc<T> asset) {
public final Array<AssetDesc> dependencies(
Promise<T> promise,
AssetDesc<T> asset
) {
try {
return dependencies0(asset);
} catch (Throwable t) {
promise.setFailure(t);
throw t;
}
}

public final void validate(
Promise<T> promise,
AssetDesc<T> asset
) {
try {
validate0(asset);
} catch (Throwable t) {
promise.setFailure(t);
throw t;
}
}

public final <F extends FileHandle> Future<?> ioAsync(
Promise<T> promise,
EventExecutor executor,
AssetManager assets,
AssetDesc<T> asset,
F handle,
Adapter<F> adapter
) {
try {
return ioAsync0(executor, assets, asset, handle, adapter);
} catch (Throwable t) {
promise.setFailure(t);
throw t;
}
}

public final <F extends FileHandle> T loadAsync(
Promise<T> promise,
AssetManager assets,
AssetDesc<T> asset,
F handle,
Object data
) {
try {
return loadAsync0(assets, asset, handle, data);
} catch (Throwable t) {
promise.setFailure(t);
throw t;
}
}

public final T loadSync(
Promise<T> promise,
AssetManager assets,
AssetDesc<T> asset,
T object
) {
try {
return loadSync0(assets, asset, object);
} catch (Throwable t) {
promise.setFailure(t);
throw t;
}
}

protected Array<AssetDesc> dependencies0(
AssetDesc<T> asset
) {
return EmptyArray.empty();
}

protected void validate(AssetDesc<T> asset) {}
protected void validate0(
AssetDesc<T> asset
) {
}

protected <F extends FileHandle> Future<?> ioAsync(
protected <F extends FileHandle> Future<?> ioAsync0(
EventExecutor executor,
AssetManager assets,
AssetDesc<T> asset,
Expand All @@ -23,7 +98,7 @@ protected <F extends FileHandle> Future<?> ioAsync(
return executor.newSucceededFuture(null);
}

protected <F extends FileHandle> T loadAsync(
protected <F extends FileHandle> T loadAsync0(
AssetManager assets,
AssetDesc<T> asset,
F handle,
Expand All @@ -32,7 +107,7 @@ protected <F extends FileHandle> T loadAsync(
return null;
}

protected T loadSync(
protected T loadSync0(
AssetManager assets,
AssetDesc<T> asset,
T object
Expand Down
24 changes: 17 additions & 7 deletions core/src/main/java/com/riiablo/asset/AssetManager.java
Expand Up @@ -142,7 +142,7 @@ public <T> T getDepNow(final AssetDesc<T> asset) {
<T> AssetContainer[] loadDependencies(Promise<T> promise, AssetDesc<T> asset) {
final AssetLoader loader = findLoader(asset.type);
@SuppressWarnings("unchecked") // guaranteed by loader contract
Array<AssetDesc> dependencies = loader.dependencies(asset);
Array<AssetDesc> dependencies = loader.dependencies(promise, asset);
final int numDependencies = dependencies.size;
final AssetContainer[] containers = numDependencies > 0
? new AssetContainer[dependencies.size]
Expand All @@ -169,10 +169,10 @@ <T> void ioAsync(final EventExecutor executor, final AssetContainer container) {
final FileHandle handle = resolve(asset); // TODO: refactor AssetLoader#resolver?
final Adapter adapter = findAdapter(handle);
loader
.ioAsync(executor, AssetManager.this, asset, handle, adapter)
.ioAsync(promise, executor, AssetManager.this, asset, handle, adapter)
.addListener((FutureListener) future -> {
@SuppressWarnings("unchecked") // guaranteed by loader contract
T object = (T) loader.loadAsync(AssetManager.this, asset, handle, future.getNow());
T object = (T) loader.loadAsync(promise, AssetManager.this, asset, handle, future.getNow());
boolean inserted = syncQueue.offer(SyncMessage.wrap(container, promise, loader, object));
if (!inserted) log.error("Failed to enqueue {}", asset);
});
Expand All @@ -185,15 +185,22 @@ <T> AssetContainer load0(final AssetDesc<T> asset) {
if (container0 != null) return container0.retain();

final Promise<T> promise = sync.newPromise();
promise.setUncancellable();
promise.addListener(future -> {
final Throwable cause = future.cause();
if (cause != null) {
log.warn("Failed to load asset {}", asset, cause);
}
});
// FIXME: loadDependencies may throw an exception to propagate to caller
final AssetContainer[] dependencies = loadDependencies(promise, asset);
final AssetContainer container = AssetContainer.wrap(asset, promise, dependencies);
loadedAssets.put(asset, container);
if (promise.isDone()) return container; // one or more dependencies was invalid

try {
findLoader(asset.type).validate(asset);
} catch (Throwable cause) {
promise.setFailure(cause);
findLoader(asset.type).validate(promise, asset);
} catch (Throwable t) {
return container;
}

Expand Down Expand Up @@ -241,7 +248,10 @@ public void sync(final long timeoutMillis) {
start = end;
msg = syncQueue.poll(timeoutRemaining, TimeUnit.MILLISECONDS);
if (msg == null) break;
msg.loadSync(this);
try {
msg.loadSync(this);
} catch (Throwable ignored) {
}
end = System.currentTimeMillis();
timeoutRemaining -= (end - start);
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/com/riiablo/asset/SyncMessage.java
Expand Up @@ -33,8 +33,8 @@ static <T> SyncMessage<T> wrap(

@SuppressWarnings("unchecked") // guaranteed by loader contract
Future<?> loadSync(AssetManager assets) {
loader.loadSync(assets, container.asset, object);
promise.setSuccess(object);
loader.loadSync(promise, assets, container.asset, object);
promise.trySuccess(object);
return promise;
}

Expand Down
14 changes: 7 additions & 7 deletions core/src/main/java/com/riiablo/asset/loader/Dc6Loader.java
Expand Up @@ -35,7 +35,7 @@ protected Dc6Decoder newInstance() {
};

@Override
public Array<AssetDesc> dependencies(AssetDesc<Dc6> asset) {
public Array<AssetDesc> dependencies0(AssetDesc<Dc6> asset) {
DcParams params = asset.params(DcParams.class);
if (params.direction < 0) return EmptyArray.empty();
AssetDesc<Dc6> header = AssetDesc.of(asset, PARENT_DC);
Expand All @@ -45,14 +45,14 @@ public Array<AssetDesc> dependencies(AssetDesc<Dc6> asset) {
}

@Override
protected <F extends FileHandle> Future<?> ioAsync(
protected <F extends FileHandle> Future<?> ioAsync0(
EventExecutor executor,
AssetManager assets,
AssetDesc<Dc6> asset,
F handle,
Adapter<F> adapter
) {
log.traceEntry("ioAsync(executor: {}, asset: {}, handle: {}, adapter: {})", executor, asset, handle, adapter);
log.traceEntry("ioAsync0(executor: {}, asset: {}, handle: {}, adapter: {})", executor, asset, handle, adapter);
DcParams params = asset.params(DcParams.class);
if (params.direction >= 0) {
Dc6 dc6 = assets.getDepNow(AssetDesc.of(asset, PARENT_DC));
Expand All @@ -65,13 +65,13 @@ protected <F extends FileHandle> Future<?> ioAsync(
}

@Override
protected <F extends FileHandle> Dc6 loadAsync(
protected <F extends FileHandle> Dc6 loadAsync0(
AssetManager assets,
AssetDesc<Dc6> asset,
F handle,
Object data
) {
log.traceEntry("loadAsync(assets: {}, asset: {}, handle: {}, data: {})", assets, asset, handle, data);
log.traceEntry("loadAsync0(assets: {}, asset: {}, handle: {}, data: {})", assets, asset, handle, data);
DcParams params = asset.params(DcParams.class);
if (params.direction >= 0) {
boolean released = ReferenceCountUtil.release(handle); // dcc already owns a reference
Expand Down Expand Up @@ -100,8 +100,8 @@ protected <F extends FileHandle> Dc6 loadAsync(
}

@Override
protected Dc6 loadSync(AssetManager assets, AssetDesc<Dc6> asset, Dc6 dc6) {
log.traceEntry("loadSync(assets: {}, asset: {}, dcc: {})", assets, asset, dc6);
protected Dc6 loadSync0(AssetManager assets, AssetDesc<Dc6> asset, Dc6 dc6) {
log.traceEntry("loadSync0(assets: {}, asset: {}, dcc: {})", assets, asset, dc6);
DcParams params = asset.params(DcParams.class);
if (params.direction < 0) return dc6;
dc6.uploadTextures(params.direction, params.combineFrames);
Expand Down
20 changes: 10 additions & 10 deletions core/src/main/java/com/riiablo/asset/loader/DccLoader.java
Expand Up @@ -36,7 +36,7 @@ protected DccDecoder newInstance() {
};

@Override
protected Array<AssetDesc> dependencies(AssetDesc<Dcc> asset) {
protected Array<AssetDesc> dependencies0(AssetDesc<Dcc> asset) {
DcParams params = asset.params(DcParams.class);
if (params.direction < 0) return EmptyArray.empty();
AssetDesc<Dcc> header = AssetDesc.of(asset, PARENT_DC);
Expand All @@ -46,21 +46,21 @@ protected Array<AssetDesc> dependencies(AssetDesc<Dcc> asset) {
}

@Override
protected void validate(AssetDesc<Dcc> asset) {
protected void validate0(AssetDesc<Dcc> asset) {
DcParams params = asset.params(DcParams.class);
if (params.combineFrames) throw new InvalidParams(asset,
"Dcc does not support DcParams#combineFrames=true");
if (params.combineFrames == 1) throw new InvalidParams(asset,
"Dcc does not support DcParams#combineFrames=1");
}

@Override
protected <F extends FileHandle> Future<?> ioAsync(
protected <F extends FileHandle> Future<?> ioAsync0(
EventExecutor executor,
AssetManager assets,
AssetDesc<Dcc> asset,
F handle,
Adapter<F> adapter
) {
log.traceEntry("ioAsync(executor: {}, asset: {}, handle: {}, adapter: {})", executor, asset, handle, adapter);
log.traceEntry("ioAsync0(executor: {}, asset: {}, handle: {}, adapter: {})", executor, asset, handle, adapter);
DcParams params = asset.params(DcParams.class);
if (params.direction >= 0) {
Dcc dcc = assets.getDepNow(AssetDesc.of(asset, PARENT_DC));
Expand All @@ -73,13 +73,13 @@ protected <F extends FileHandle> Future<?> ioAsync(
}

@Override
protected <F extends FileHandle> Dcc loadAsync(
protected <F extends FileHandle> Dcc loadAsync0(
AssetManager assets,
AssetDesc<Dcc> asset,
F handle,
Object data
) {
log.traceEntry("loadAsync(assets: {}, asset: {}, handle: {}, data: {})", assets, asset, handle, data);
log.traceEntry("loadAsync0(assets: {}, asset: {}, handle: {}, data: {})", assets, asset, handle, data);
DcParams params = asset.params(DcParams.class);
if (params.direction >= 0) {
boolean released = ReferenceCountUtil.release(handle); // dcc already owns a reference
Expand Down Expand Up @@ -108,8 +108,8 @@ protected <F extends FileHandle> Dcc loadAsync(
}

@Override
protected Dcc loadSync(AssetManager assets, AssetDesc<Dcc> asset, Dcc dcc) {
log.traceEntry("loadSync(assets: {}, asset: {}, dcc: {})", assets, asset, dcc);
protected Dcc loadSync0(AssetManager assets, AssetDesc<Dcc> asset, Dcc dcc) {
log.traceEntry("loadSync0(assets: {}, asset: {}, dcc: {})", assets, asset, dcc);
DcParams params = asset.params(DcParams.class);
if (params.direction < 0) return dcc;
dcc.uploadTextures(params.direction, params.combineFrames);
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/com/riiablo/asset/loader/MusicLoader.java
Expand Up @@ -14,7 +14,7 @@

public class MusicLoader extends AssetLoader<Music> {
@Override
protected <F extends FileHandle> Future<?> ioAsync(
protected <F extends FileHandle> Future<?> ioAsync0(
EventExecutor executor,
AssetManager assets,
AssetDesc<Music> asset,
Expand All @@ -25,7 +25,7 @@ protected <F extends FileHandle> Future<?> ioAsync(
}

@Override
protected <F extends FileHandle> Music loadAsync(
protected <F extends FileHandle> Music loadAsync0(
AssetManager assets,
AssetDesc<Music> asset,
F handle,
Expand All @@ -35,7 +35,7 @@ protected <F extends FileHandle> Music loadAsync(
}

@Override
protected Music loadSync(
protected Music loadSync0(
AssetManager assets,
AssetDesc<Music> asset,
Music music
Expand Down
18 changes: 6 additions & 12 deletions core/src/main/java/com/riiablo/asset/loader/PaletteLoader.java
Expand Up @@ -6,7 +6,6 @@
import io.netty.util.concurrent.Future;

import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;

import com.riiablo.asset.Adapter;
import com.riiablo.asset.AssetDesc;
Expand All @@ -20,25 +19,20 @@ public class PaletteLoader extends AssetLoader<Palette> {
private static final Logger log = LogManager.getLogger(PaletteLoader.class);

@Override
public Array<AssetDesc> dependencies(AssetDesc<Palette> asset) {
return super.dependencies(asset);
}

@Override
protected <F extends FileHandle> Future<?> ioAsync(
protected <F extends FileHandle> Future<?> ioAsync0(
EventExecutor executor,
AssetManager assets,
AssetDesc<Palette> asset,
F handle,
Adapter<F> adapter
) {
log.traceEntry("ioAsync(executor: {}, assets: {}, asset: {}, handle: {}, adapter: {})", executor, assets, asset, handle, adapter);
log.traceEntry("ioAsync0(executor: {}, assets: {}, asset: {}, handle: {}, adapter: {})", executor, assets, asset, handle, adapter);
return adapter.buffer(executor, handle, 0, (int) handle.length());
}

@Override
protected <F extends FileHandle> Palette loadAsync(AssetManager assets, AssetDesc<Palette> asset, F handle, Object data) {
log.traceEntry("loadAsync(assets: {}, asset: {}, handle: {}, data: {})", assets, asset, handle, data);
protected <F extends FileHandle> Palette loadAsync0(AssetManager assets, AssetDesc<Palette> asset, F handle, Object data) {
log.traceEntry("loadAsync0(assets: {}, asset: {}, handle: {}, data: {})", assets, asset, handle, data);
assert data instanceof ByteBuf;
ByteBuf buffer = (ByteBuf) data; // borrowed, don't release
try {
Expand All @@ -49,8 +43,8 @@ protected <F extends FileHandle> Palette loadAsync(AssetManager assets, AssetDes
}

@Override
protected Palette loadSync(AssetManager assets, AssetDesc<Palette> asset, Palette palette) {
log.traceEntry("loadSync(assets: {}, asset: {}, object: {})", assets, asset, palette);
protected Palette loadSync0(AssetManager assets, AssetDesc<Palette> asset, Palette palette) {
log.traceEntry("loadSync0(assets: {}, asset: {}, object: {})", assets, asset, palette);
return palette;
}
}

0 comments on commit 9dfe541

Please sign in to comment.