GIOSchedulerJobs vs the main loop



While porting the trashapplet to gio, I noticed that GIOScheduler runs
the job function as an atomic unit. While that may be ok when threads
are available and it runs in its own thread, copying an entire
directory tree (as an example) in an idle function can possibly block
the mainloop for undue amounts of time.

Here is a simple patch that allows a GIOSchedulerJobFunc to do its job
in chunks, by returning a boolean. The scheduler will keep the idle
alive until the job is done and the function returns FALSE. Job
functions can maintain state between the invocations by storing it in
user_data. In the threaded case, the job function gets simply called
in a loop until it is done.

Does this look ok to commit ?


Matthias
Index: gioscheduler.h
===================================================================
--- gioscheduler.h	(revision 6366)
+++ gioscheduler.h	(working copy)
@@ -53,10 +53,13 @@
  *
  * Long-running jobs should periodically check the @cancellable
  * to see if they have been cancelled.
+ *
+ * Returns: %TRUE if this function should be called again to
+ *    complete the job, %FALSE if the job is complete (or cancelled)
  **/
-typedef void (*GIOSchedulerJobFunc) (GIOSchedulerJob *job,
-				     GCancellable    *cancellable,
-				     gpointer         user_data);
+typedef gboolean (*GIOSchedulerJobFunc) (GIOSchedulerJob *job,
+		   		         GCancellable    *cancellable,
+				         gpointer         user_data);
 
 void     g_io_scheduler_push_job                   (GIOSchedulerJobFunc  job_func,
 						    gpointer             user_data,
Index: gioscheduler.c
===================================================================
--- gioscheduler.c	(revision 6365)
+++ gioscheduler.c	(working copy)
@@ -152,45 +152,54 @@
 }
 
 static void
+job_destroy (gpointer data)
+{
+  GIOSchedulerJob *job = data;
+
+  if (job->destroy_notify)
+    job->destroy_notify (job->data);
+
+  remove_active_job (job);
+  g_io_job_free (job);
+}
+
+static void
 io_job_thread (gpointer data,
 	       gpointer user_data)
 {
   GIOSchedulerJob *job = data;
+  gboolean result;
 
   if (job->cancellable)
     g_cancellable_push_current (job->cancellable);
-  job->job_func (job, job->cancellable, job->data);
+
+  do 
+    {
+      result = job->job_func (job, job->cancellable, job->data);
+    }
+  while (result);
+
   if (job->cancellable)
     g_cancellable_pop_current (job->cancellable);
 
-  if (job->destroy_notify)
-    job->destroy_notify (job->data);
-
-  remove_active_job (job);
-  g_io_job_free (job);
-
+  job_destroy (job);
 }
 
 static gboolean
 run_job_at_idle (gpointer data)
 {
   GIOSchedulerJob *job = data;
+  gboolean result;
 
   if (job->cancellable)
     g_cancellable_push_current (job->cancellable);
   
-  job->job_func (job, job->cancellable, job->data);
+  result = job->job_func (job, job->cancellable, job->data);
   
   if (job->cancellable)
     g_cancellable_pop_current (job->cancellable);
 
-  if (job->destroy_notify)
-    job->destroy_notify (job->data);
-
-  remove_active_job (job);
-  g_io_job_free (job);
-
-  return FALSE;
+  return result;
 }
 
 /**
@@ -249,7 +258,7 @@
        */
       job->idle_tag = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1 + io_priority / 10,
 				       run_job_at_idle,
-				       job, NULL);
+				       job, job_destroy);
     }
 }
 
Index: gsimpleasyncresult.c
===================================================================
--- gsimpleasyncresult.c	(revision 6365)
+++ gsimpleasyncresult.c	(working copy)
@@ -595,10 +595,10 @@
   GSimpleAsyncThreadFunc func;
 } RunInThreadData;
 
-static void
-run_in_thread (GIOSchedulerJob       *job,
-               GCancellable *c,
-               gpointer      _data)
+static gboolean
+run_in_thread (GIOSchedulerJob *job,
+               GCancellable    *c,
+               gpointer         _data)
 {
   RunInThreadData *data = _data;
   GSimpleAsyncResult *simple = data->simple;
@@ -617,6 +617,8 @@
   g_simple_async_result_complete_in_idle (data->simple);
   g_object_unref (data->simple);
   g_free (data);
+
+  return FALSE;
 }
 
 /**


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