[gnome-games/wip/exalm/cache] game-collection: Load collection in background thread



commit 6da5138dc3804f6f1ae7bd6dd57eed6ad75bb30f
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Fri Nov 15 00:54:38 2019 +0500

    game-collection: Load collection in background thread
    
    Make loading functions in GameUriAdapter and UriGameFactory sync, then
    move the whole loading into a background thread. This massively improves
    loading speed and responsiveness.

 .../playstation/src/playstation-game-factory.vala  | 17 ++++---
 src/core/game-collection.vala                      | 55 +++++++++++++---------
 src/core/game-uri-adapter.vala                     |  2 +-
 src/core/uri-game-factory.vala                     |  9 ++--
 src/generic/generic-game-uri-adapter.vala          |  5 +-
 src/generic/generic-uri-game-factory.vala          | 39 +++++----------
 src/retro/retro-simple-game-uri-adapter.vala       |  5 +-
 src/ui/application.vala                            | 24 ++++------
 8 files changed, 72 insertions(+), 84 deletions(-)
---
diff --git a/plugins/playstation/src/playstation-game-factory.vala 
b/plugins/playstation/src/playstation-game-factory.vala
index 9460572f..f12a95bf 100644
--- a/plugins/playstation/src/playstation-game-factory.vala
+++ b/plugins/playstation/src/playstation-game-factory.vala
@@ -14,6 +14,7 @@ public class Games.PlayStationGameFactory : Object, UriGameFactory {
        private HashTable<string, Game> game_for_disc_set_id;
        private GenericSet<Game> games;
        private RetroPlatform platform;
+       private unowned GameCallback game_added_callback;
 
        public PlayStationGameFactory (RetroPlatform platform, PlaystationGameinfoCache gameinfo_cache) {
                media_for_disc_id = new HashTable<string, Media> (str_hash, str_equal);
@@ -28,17 +29,14 @@ public class Games.PlayStationGameFactory : Object, UriGameFactory {
                return { CUE_MIME_TYPE };
        }
 
-       public async Game? query_game_for_uri (Uri uri) {
-               Idle.add (this.query_game_for_uri.callback);
-               yield;
-
+       public Game? query_game_for_uri (Uri uri) {
                if (game_for_uri.contains (uri))
                        return game_for_uri[uri];
 
                return null;
        }
 
-       public async void add_uri (Uri uri) {
+       public void add_uri (Uri uri) {
                try {
                        add_uri_with_error (uri);
                }
@@ -126,13 +124,14 @@ public class Games.PlayStationGameFactory : Object, UriGameFactory {
                game_for_uri[uri] = game;
                game_for_disc_set_id[disc_set_id] = game;
                games.add (game);
-               game_added (game);
+               if (game_added_callback != null)
+                       game_added_callback (game);
 
                var input_capabilities = new GameinfoDiscIdInputCapabilities (gameinfo, disc_set_id);
                gameinfo_cache.store_info (uri, media_set, input_capabilities);
        }
 
-       public async void foreach_game (GameCallback game_callback) {
+       public void foreach_game (GameCallback game_callback) {
                games.foreach ((game) => game_callback (game));
        }
 
@@ -174,4 +173,8 @@ public class Games.PlayStationGameFactory : Object, UriGameFactory {
 
                return gameinfo;
        }
+
+       public void set_game_added_callback (GameCallback game_callback) {
+               game_added_callback = game_callback;
+       }
 }
diff --git a/src/core/game-collection.vala b/src/core/game-collection.vala
index 3fb8db3f..d7732849 100644
--- a/src/core/game-collection.vala
+++ b/src/core/game-collection.vala
@@ -40,7 +40,7 @@ private class Games.GameCollection : Object {
                        factories_for_scheme[scheme].append_val (factory);
                }
 
-               factory.game_added.connect ((game) => store_game (game));
+               factory.set_game_added_callback (store_game);
        }
 
        public void add_runner_factory (RunnerFactory factory) {
@@ -57,15 +57,15 @@ private class Games.GameCollection : Object {
                return factories_for_mime_type.get_keys_as_array ();
        }
 
-       public async void add_uri (Uri uri) {
-               foreach (var factory in yield get_factories_for_uri (uri))
-                       yield factory.add_uri (uri);
+       public void add_uri (Uri uri) {
+               foreach (var factory in get_factories_for_uri (uri))
+                       factory.add_uri (uri);
        }
 
-       public async Game? query_game_for_uri (Uri uri) {
+       public Game? query_game_for_uri (Uri uri) {
                Game[] games = {};
-               foreach (var factory in yield get_factories_for_uri (uri)) {
-                       var game = yield factory.query_game_for_uri (uri);
+               foreach (var factory in get_factories_for_uri (uri)) {
+                       var game = factory.query_game_for_uri (uri);
                        if (game != null)
                                games += game;
                }
@@ -76,16 +76,27 @@ private class Games.GameCollection : Object {
                return games[0];
        }
 
-       public async bool search_games () {
-               foreach (var source in sources)
-                       foreach (var uri in source) {
-                               if (paused)
-                                       return false;
+       public async void search_games () {
+               SourceFunc callback = search_games.callback;
 
-                               yield add_uri (uri);
-                       }
+               ThreadFunc<void*> run = () => {
+                       foreach (var source in sources)
+                               foreach (var uri in source) {
+                                       if (paused) {
+                                               Idle.add ((owned) callback);
+                                               return null;
+                                       }
+
+                                       add_uri (uri);
+                               }
+
+                       Idle.add ((owned) callback);
+                       return null;
+               };
 
-               return true;
+               new Thread<void*> (null, (owned) run);
+
+               yield;
        }
 
        public Runner? create_runner (Game game) {
@@ -112,10 +123,7 @@ private class Games.GameCollection : Object {
                return null;
        }
 
-       private async UriGameFactory[] get_factories_for_uri (Uri uri) {
-               Idle.add (get_factories_for_uri.callback);
-               yield;
-
+       private UriGameFactory[] get_factories_for_uri (Uri uri) {
                UriGameFactory[] factories = {};
 
                string scheme;
@@ -131,7 +139,7 @@ private class Games.GameCollection : Object {
                if (scheme == "file") {
                        try {
                                var file = uri.to_file ();
-                               foreach (var factory in yield get_factories_for_file (file))
+                               foreach (var factory in get_factories_for_file (file))
                                        factories += factory;
                        }
                        catch (Error e) {
@@ -146,7 +154,7 @@ private class Games.GameCollection : Object {
                return factories;
        }
 
-       private async UriGameFactory[] get_factories_for_file (File file) throws Error {
+       private UriGameFactory[] get_factories_for_file (File file) throws Error {
                if (!file.query_exists ())
                        return {};
 
@@ -163,6 +171,9 @@ private class Games.GameCollection : Object {
                        return;
 
                games.add (game);
-               game_added (game);
+               Idle.add (() => {
+                       game_added (game);
+                       return Source.REMOVE;
+               });
        }
 }
diff --git a/src/core/game-uri-adapter.vala b/src/core/game-uri-adapter.vala
index 8e970865..f9be6f63 100644
--- a/src/core/game-uri-adapter.vala
+++ b/src/core/game-uri-adapter.vala
@@ -1,5 +1,5 @@
 // This file is part of GNOME Games. License: GPL-3.0+.
 
 public interface Games.GameUriAdapter : Object {
-       public abstract async Game game_for_uri (Uri uri) throws Error;
+       public abstract Game game_for_uri (Uri uri) throws Error;
 }
diff --git a/src/core/uri-game-factory.vala b/src/core/uri-game-factory.vala
index 7e2e9a79..b9315a37 100644
--- a/src/core/uri-game-factory.vala
+++ b/src/core/uri-game-factory.vala
@@ -1,8 +1,6 @@
 // This file is part of GNOME Games. License: GPL-3.0+.
 
 public interface Games.UriGameFactory : Object {
-       public signal void game_added (Game game);
-
        public virtual string[] get_mime_types () {
                return {};
        }
@@ -11,7 +9,8 @@ public interface Games.UriGameFactory : Object {
                return {};
        }
 
-       public abstract async void add_uri (Uri uri);
-       public abstract async Game? query_game_for_uri (Uri uri);
-       public abstract async void foreach_game (Games.GameCallback game_callback);
+       public abstract void add_uri (Uri uri);
+       public abstract Game? query_game_for_uri (Uri uri);
+       public abstract void foreach_game (GameCallback game_callback);
+       public abstract void set_game_added_callback (GameCallback game_callback);
 }
diff --git a/src/generic/generic-game-uri-adapter.vala b/src/generic/generic-game-uri-adapter.vala
index e3b957bf..aaa1f028 100644
--- a/src/generic/generic-game-uri-adapter.vala
+++ b/src/generic/generic-game-uri-adapter.vala
@@ -9,10 +9,7 @@ public class Games.GenericGameUriAdapter : GameUriAdapter, Object {
                this.callback = (owned) callback;
        }
 
-       public async Game game_for_uri (Uri uri) throws Error {
-               Idle.add (this.game_for_uri.callback);
-               yield;
-
+       public Game game_for_uri (Uri uri) throws Error {
                return callback (uri);
        }
 }
diff --git a/src/generic/generic-uri-game-factory.vala b/src/generic/generic-uri-game-factory.vala
index 4a79169c..186f32c4 100644
--- a/src/generic/generic-uri-game-factory.vala
+++ b/src/generic/generic-uri-game-factory.vala
@@ -1,12 +1,11 @@
 // This file is part of GNOME Games. License: GPL-3.0+.
 
 public class Games.GenericUriGameFactory : Object, UriGameFactory {
-       private const uint GAMES_PER_CYCLE = 4;
-
        private GameUriAdapter game_uri_adapter;
        private HashTable<Uri, Game> game_for_uri;
        private string[] mime_types;
        private string[] schemes;
+       private unowned GameCallback game_added_callback;
 
        public GenericUriGameFactory (GameUriAdapter game_uri_adapter) {
                this.game_uri_adapter = game_uri_adapter;
@@ -31,50 +30,36 @@ public class Games.GenericUriGameFactory : Object, UriGameFactory {
                schemes += scheme;
        }
 
-       public async void add_uri (Uri uri) {
-               Idle.add (this.add_uri.callback);
-               yield;
-
+       public void add_uri (Uri uri) {
                if (game_for_uri.contains (uri))
                        return;
 
                try {
-                       var game = yield game_uri_adapter.game_for_uri (uri);
+                       var game = game_uri_adapter.game_for_uri (uri);
                        game_for_uri[uri] = game;
 
-                       game_added (game);
+                       if (game_added_callback != null)
+                               game_added_callback (game);
                }
                catch (Error e) {
                        debug (e.message);
                }
        }
 
-       public async Game? query_game_for_uri (Uri uri) {
-               Idle.add (this.query_game_for_uri.callback);
-               yield;
-
+       public Game? query_game_for_uri (Uri uri) {
                if (game_for_uri.contains (uri))
                        return game_for_uri[uri];
 
                return null;
        }
 
-       public async void foreach_game (GameCallback game_callback) {
-               uint handled_uris = 0;
+       public void foreach_game (GameCallback game_callback) {
                var games = game_for_uri.get_values ();
-               for (unowned List<weak Game> game = games; game != null; game = game.next) {
-                       game_callback (game.data);
-
-                       if (handled_uris++ < GAMES_PER_CYCLE)
-                               continue;
-
-                       // Free the execution only once every HANDLED_URIS_PER_CYCLE
-                       // games to speed up the execution by avoiding too many context
-                       // switching.
-                       handled_uris = 0;
+               foreach (var game in games)
+                       game_callback (game);
+       }
 
-                       Idle.add (this.foreach_game.callback);
-                       yield;
-               }
+       public void set_game_added_callback (GameCallback game_callback) {
+               game_added_callback = game_callback;
        }
 }
diff --git a/src/retro/retro-simple-game-uri-adapter.vala b/src/retro/retro-simple-game-uri-adapter.vala
index d9522292..5d553520 100644
--- a/src/retro/retro-simple-game-uri-adapter.vala
+++ b/src/retro/retro-simple-game-uri-adapter.vala
@@ -9,10 +9,7 @@ private class Games.RetroSimpleGameUriAdapter : GameUriAdapter, Object {
                this.platform = platform;
        }
 
-       public async Game game_for_uri (Uri uri) throws Error {
-               Idle.add (this.game_for_uri.callback);
-               yield;
-
+       public Game game_for_uri (Uri uri) throws Error {
                var uid = new FingerprintUid (uri, simple_type.prefix);
                var title = new FilenameTitle (uri);
                var media = new GriloMedia (title, simple_type.mime_type);
diff --git a/src/ui/application.vala b/src/ui/application.vala
index 4f35de04..bb8dcb34 100644
--- a/src/ui/application.vala
+++ b/src/ui/application.vala
@@ -145,10 +145,6 @@ public class Games.Application : Gtk.Application {
        }
 
        public void add_game_files () {
-               add_game_files_async.begin ();
-       }
-
-       public async void add_game_files_async () {
                var chooser = new Gtk.FileChooserDialog (
                        _("Select game files"), window, Gtk.FileChooserAction.OPEN,
                        _("_Cancel"), Gtk.ResponseType.CANCEL,
@@ -165,7 +161,7 @@ public class Games.Application : Gtk.Application {
                if (chooser.run () == Gtk.ResponseType.ACCEPT)
                        foreach (unowned string uri_string in chooser.get_uris ()) {
                                var uri = new Uri (uri_string);
-                               yield add_cached_uri (uri);
+                               add_cached_uri (uri);
                        }
 
                chooser.close ();
@@ -188,7 +184,7 @@ public class Games.Application : Gtk.Application {
 
                // FIXME: This is done because files[0] gets freed after yield
                var file = files[0];
-               var game = yield game_for_uris (uris);
+               var game = game_for_uris (uris);
 
                if (game == null) {
                        var filename = file.get_basename ();
@@ -328,16 +324,16 @@ public class Games.Application : Gtk.Application {
                Migrator.apply_migration_if_necessary ();
        }
 
-       private async Game? game_for_uris (Uri[] uris) {
+       private Game? game_for_uris (Uri[] uris) {
                init_game_sources ();
 
                foreach (var uri in uris)
-                       yield add_cached_uri (uri);
+                       add_cached_uri (uri);
 
-               return yield game_collection.query_game_for_uri (uris[0]);
+               return game_collection.query_game_for_uri (uris[0]);
        }
 
-       private async void add_cached_uri (Uri uri) {
+       private void add_cached_uri (Uri uri) {
                try {
                        if (database != null)
                                        database.add_uri (uri);
@@ -346,12 +342,11 @@ public class Games.Application : Gtk.Application {
                        debug (e.message);
                }
 
-               yield game_collection.add_uri (uri);
+               game_collection.add_uri (uri);
        }
 
        internal async void load_game_list () {
-               if (!yield game_collection.search_games ())
-                       return;
+               yield game_collection.search_games ();
 
                game_list_loaded = true;
                if (window != null)
@@ -361,7 +356,8 @@ public class Games.Application : Gtk.Application {
        public void set_pause_loading (bool paused) {
                game_collection.paused = paused;
 
-               load_game_list.begin ();
+               if (!paused)
+                       load_game_list.begin ();
        }
 
        private void preferences () {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]