diff --git a/src/Http.hx b/src/Http.hx index 9079a0f2..44295956 100644 --- a/src/Http.hx +++ b/src/Http.hx @@ -7,6 +7,8 @@ typedef HttpRequest = { var url:String; var callback:haxe.io.Bytes->Void; var errCallback:String->Void; + var cancelled:Bool; + var fulfilled:Bool; }; class Http { @@ -14,6 +16,7 @@ class Http { static var threadPool:sys.thread.FixedThreadPool; static var requests:sys.thread.Deque = new sys.thread.Deque(); static var responses:sys.thread.Deque<() -> Void> = new sys.thread.Deque<() -> Void>(); + static var cancellationMutex:sys.thread.Mutex = new sys.thread.Mutex(); #end public static function init() { @@ -30,12 +33,20 @@ class Http { static function threadLoop() { while (true) { var req = requests.pop(true); + cancellationMutex.acquire(); + if (req.cancelled) { + cancellationMutex.release(); + continue; + } + cancellationMutex.release(); var http = new sys.Http(req.url); http.onError = (e) -> { responses.add(() -> req.errCallback(e)); + req.fulfilled = true; }; http.onBytes = (b) -> { responses.add(() -> req.callback(b)); + req.fulfilled = true; }; hl.Gc.blocking(true); // Wtf is this shit http.request(false); @@ -44,14 +55,17 @@ class Http { } #end - public static function get(url:String, callback:haxe.io.Bytes->Void, errCallback:String->Void):Void { + public static function get(url:String, callback:haxe.io.Bytes->Void, errCallback:String->Void) { var req = { url: url, callback: callback, - errCallback: errCallback + errCallback: errCallback, + cancelled: false, + fulfilled: false }; #if sys requests.add(req); + return req; #else js.Browser.window.fetch(url).then(r -> r.arrayBuffer().then(b -> callback(haxe.io.Bytes.ofData(b))), e -> errCallback(e.toString())); #end @@ -65,4 +79,12 @@ class Http { } #end } + + public static function cancel(req:HttpRequest) { + #if sys + cancellationMutex.acquire(); + req.cancelled = true; + cancellationMutex.release(); + #end + } } diff --git a/src/Marbleland.hx b/src/Marbleland.hx index a9465a38..0a15e59b 100644 --- a/src/Marbleland.hx +++ b/src/Marbleland.hx @@ -88,7 +88,7 @@ class Marbleland { } public static function getMissionImage(id:Int, cb:Image->Void) { - Http.get('https://marbleland.vani.ga/api/level/${id}/image?width=258&height=194', (imageBytes) -> { + return Http.get('https://marbleland.vani.ga/api/level/${id}/image?width=258&height=194', (imageBytes) -> { var res = new Image(new hxd.fs.BytesFileSystem.BytesFileEntry('${id}.png', imageBytes)); cb(res); }, (e) -> { diff --git a/src/Mission.hx b/src/Mission.hx index dd2c2a4f..1c59eec8 100644 --- a/src/Mission.hx +++ b/src/Mission.hx @@ -1,5 +1,6 @@ package src; +import src.Http.HttpRequest; import gui.Canvas; import gui.MessageBoxOkDlg; import haxe.Json; @@ -19,6 +20,7 @@ import src.Util; import src.Console; import src.Marbleland; import src.MarbleGame; +import src.Http; class Mission { public var root:MissionElementSimGroup; @@ -44,7 +46,7 @@ class Mission { var imgFileEntry:hxd.fs.FileEntry; - static var doingLoadPreviewTimeout = false; + static var _previewRequest:HttpRequest; public function new() {} @@ -162,7 +164,10 @@ class Mission { onLoaded(Tile.fromBitmap(img)); return null; } else { - Marbleland.getMissionImage(this.id, (im) -> { + if (_previewRequest != null && !_previewRequest.fulfilled) { + Http.cancel(_previewRequest); // Cancel the previous request to save dequeing + } + _previewRequest = Marbleland.getMissionImage(this.id, (im) -> { if (im != null) { onLoaded(im.toTile()); } else {