[gnome-sudoku/multithread_printing] Start multiple threads in the async method for puzzle generation



commit 0b7653bfa405760a04c37f97fe4c1c9447378ae8
Author: Parin Porecha <parinporecha gmail com>
Date:   Fri Aug 15 11:49:00 2014 +0200

    Start multiple threads in the async method for puzzle generation
    
    Also remove spinner from new game screen

 data/gnome-sudoku.ui      |    5 ---
 data/print-games.ui       |   15 ++++++----
 lib/sudoku-generator.vala |   71 ++++++++++++++++++++++++++++++++++++--------
 src/gnome-sudoku.vala     |    7 ----
 src/sudoku-printer.vala   |    6 ++--
 5 files changed, 70 insertions(+), 34 deletions(-)
---
diff --git a/data/gnome-sudoku.ui b/data/gnome-sudoku.ui
index 1893988..d85f406 100644
--- a/data/gnome-sudoku.ui
+++ b/data/gnome-sudoku.ui
@@ -154,11 +154,6 @@
                                 <property name="position">3</property>
                             </packing>
                         </child>
-                        <child>
-                            <object class="GtkSpinner" id="start_spinner">
-                                <property name="visible">True</property>
-                            </object>
-                        </child>
                     </object> <!-- End of start_box -->
                     <packing>
                         <property name="name">start_box</property>
diff --git a/data/print-games.ui b/data/print-games.ui
index 44f9533..41815ed 100644
--- a/data/print-games.ui
+++ b/data/print-games.ui
@@ -24,12 +24,6 @@
         <property name="can_focus">False</property>
         <property name="show-close-button">False</property>
         <child>
-            <object class="GtkSpinner" id="spinner">
-                <property name="halign">center</property>
-                <property name="visible">False</property>
-            </object>
-        </child>
-        <child>
           <object class="GtkButton" id="okbutton1">
             <property name="label" translatable="yes">_Print</property>
             <property name="visible">True</property>
@@ -60,6 +54,15 @@
             <property name="pack_type">start</property>
           </packing>
         </child>
+        <child>
+            <object class="GtkSpinner" id="spinner">
+                <property name="valign">center</property>
+                <property name="visible">True</property>
+            </object>
+            <packing>
+                <property name="pack_type">end</property>
+            </packing>
+        </child>
       </object>
     </child>
     <child internal-child="vbox">
diff --git a/lib/sudoku-generator.vala b/lib/sudoku-generator.vala
index c67f4e5..cb34444 100644
--- a/lib/sudoku-generator.vala
+++ b/lib/sudoku-generator.vala
@@ -1,5 +1,7 @@
 /* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
+using Gee;
+
 public class SudokuGenerator : Object
 {
     private SudokuGenerator () {
@@ -24,23 +26,38 @@ public class SudokuGenerator : Object
 
     public async static SudokuBoard[] generate_boards_async (int nboards, DifficultyCategory category) 
throws ThreadError
     {
-        SourceFunc callback = generate_boards_async.callback;
+        var boards_list = new ArrayList<SudokuBoard> ();
         var boards = new SudokuBoard[nboards];
 
-        // Hold reference to closure to keep it from being freed whilst
-        // thread is active.
-        ThreadFunc<void*> generate = () => {
-            for (var i = 0; i < nboards; i++)
-                boards[i] = generate_board (category);
+//        var sysinfo = GLibtop.glibtop_sysinfo.get_sysinfo ();
+//        stdout.printf ("ncpus = %d\n", sysinfo.ncpu);
+        var ncpu = 4;
+        var nthreads = int.min (ncpu, nboards);
+        var base_nsudokus_each = nboards / nthreads;
+        var remainder = nboards % nthreads;
+        var nsudokus_per_thread = base_nsudokus_each;
+
+        stdout.printf ("no. of threads = %d\n", nthreads);
+
+        for (var i = 0; i < nthreads; i++)
+        {
+            if (i > (nthreads - remainder - 1))
+                nsudokus_per_thread = base_nsudokus_each + 1;
+            var gen_thread = new GeneratorThread (nsudokus_per_thread, category, ref boards_list, 
generate_boards_async.callback, i);
+            Thread<int> thread = new Thread<int> ("Generator thread", gen_thread.run);
+
+            // Relinquish the CPU, so that the generated thread can run
+            yield;
 
-            // Schedule callback
-            Idle.add((owned) callback);
-            return null;
-        };
-        new Thread<void*>("Generator thread", generate);
+            stdout.printf ("waiting for #%d to join\n", i);
+            var result = thread.join ();
+            stdout.printf ("Thread #%d exited\n", result);
+        }
+
+        stdout.printf ("boards list size = %d\n", boards_list.size);
+        for (var i = 0; i < boards_list.size; i++)
+            boards[i] = boards_list[i];
 
-        // Wait for background thread to schedule our callback
-        yield;
         return boards;
     }
 
@@ -61,3 +78,31 @@ public class SudokuGenerator : Object
         return QQwing.get_version ();
     }
 }
+
+public class GeneratorThread : Object
+{
+    private int nsudokus;
+    private DifficultyCategory level;
+    private int id;
+    private ArrayList<SudokuBoard> boards_list;
+    private SourceFunc callback;
+
+    public GeneratorThread (int nsudokus, DifficultyCategory level, ref ArrayList<SudokuBoard> boards_list, 
SourceFunc callback, int id)
+    {
+        this.nsudokus = nsudokus;
+        this.level = level;
+        this.id = id;
+        this.boards_list = boards_list;
+        this.callback = callback;
+    }
+
+    public int run ()
+    {
+        stdout.printf ("generating %d puzzles\n", nsudokus);
+        for (var i = 0; i < nsudokus; i++)
+            boards_list.add (SudokuGenerator.generate_board (level));
+
+        Idle.add((owned) callback);
+        return id;
+    }
+}
diff --git a/src/gnome-sudoku.vala b/src/gnome-sudoku.vala
index 189a2c3..fb60af5 100644
--- a/src/gnome-sudoku.vala
+++ b/src/gnome-sudoku.vala
@@ -297,14 +297,7 @@ public class Sudoku : Gtk.Application
 
         SudokuGenerator.generate_boards_async.begin (1, selected_difficulty, (obj, res) => {
             try {
-                var spinner = builder.get_object ("start_spinner") as Spinner;
-                spinner.active = true;
-                spinner.show ();
-                spinner.start ();
-
                 var gen_boards = SudokuGenerator.generate_boards_async.end (res);
-
-                spinner.stop ();
                 start_game (gen_boards[0]);
             } catch (ThreadError e) {
                 error ("Thread error: %s", e.message);
diff --git a/src/sudoku-printer.vala b/src/sudoku-printer.vala
index c77dacb..89b6fab 100644
--- a/src/sudoku-printer.vala
+++ b/src/sudoku-printer.vala
@@ -327,6 +327,9 @@ public class GamePrinter: GLib.Object
             try {
                 var boards = SudokuGenerator.generate_boards_async.end(res);
 
+                spinner.stop ();
+                spinner.hide ();
+
                 SudokuPrinter printer = new SudokuPrinter (boards, ref window);
                 PrintOperationResult result = printer.print_sudoku ();
                 if (result == PrintOperationResult.APPLY)
@@ -335,10 +338,7 @@ public class GamePrinter: GLib.Object
                     foreach (SudokuBoard board in boards)
                         saver.add_game_to_finished (new SudokuGame (board));
                 }
-
                 boards_list = null;
-                spinner.stop ();
-                spinner.hide ();
             } catch (ThreadError e) {
                 error ("Thread error: %s\n", e.message);
             }


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