gerror.c revisited



Hi everyone, (especially Havoc)

I just sat down using the new GError for some of the new thread functions, all
related to thread creation, where such error reporting really is sensible.
Here are my comments after doing that. The according patch is attached.
Please, Havoc, have a look at it.

* I ended up defining 

  #define glib_error_domain() g_quark_from_static_string ("glib-error-domain")

  in gerror.h. As far as I can tell it is quite hard to get such a
  glib_error_domain statically defined. So in essence the question is, whether 
  an approach similiar to GLogDomain (i.e. take just a string) might be better
  suited for the API. The domain is only accessed inside g_error_matches,
  which in turn is only called after an error has occured, so the overhead of
  doing strcmp there shouldn't be too bad. We might as well just take
  GLogDomain for added consistency!
* I would very much like to see a function
  g_print_error (GError **err, gboolean fatal), that prints out the error in
  some canonical form and does abort, if fatal is true. Or two functions, one
  for error, one for warning (without abort).
* g_set_error should call g_print_error (the_error, TRUE), when err is NULL.
  Because if I supply NULL as an err argument, I actually don't want to know,
  in the calling code whether it fails, but I'm not calling out for silent
  failure, when the error condition is occuring. Or let g_set_error take a
  fatal argument as above.

Maybe I got everything wrong. Then please look at the code, that lead me to
the above statements. In thread-test you will find a very crude test-code for
that. Just run it. For now you better ignore the code in gthreadpool.c.
Additionally it is so far only ported for POSIX threads.

Bye,
Sebastian
-- 
Sebastian Wilhelmi                   |            här ovanför alla molnen
mailto:wilhelmi@ira.uka.de           |     är himmlen så förunderligt blå
http://goethe.ira.uka.de/~wilhelmi   |
Index: gerror.h
===================================================================
RCS file: /cvs/gnome/glib/gerror.h,v
retrieving revision 1.2
diff -u -b -B -r1.2 gerror.h
--- gerror.h	2000/07/26 11:01:59	1.2
+++ gerror.h	2000/08/29 13:52:44
@@ -35,6 +35,9 @@
   gchar       *message;
 };
 
+#define glib_error_domain() g_quark_from_static_string ("glib-error-domain")
+#define GLIB_ERROR_AGAIN   1   /* Resource temporarily unavailable */
+
 GError*  g_error_new           (GQuark         domain,
                                 gint           code,
                                 const gchar   *format,
Index: glib.h
===================================================================
RCS file: /cvs/gnome/glib/glib.h,v
retrieving revision 1.190
diff -u -b -B -r1.190 glib.h
--- glib.h	2000/08/27 15:33:15	1.190
+++ glib.h	2000/08/29 13:52:45
@@ -941,6 +941,15 @@
   guint len;
 };
 
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include <gerror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
 
 /* IEEE Standard 754 Single Precision Storage Format (gfloat):
  *
@@ -3087,7 +3096,8 @@
 			           gboolean 		 joinable,
 			           gboolean 		 bound,
 			           GThreadPriority 	 priority,
-				   gpointer              thread);
+				   gpointer              thread,
+				   GError              **err);
   void      (*thread_yield)       (void);
   void      (*thread_join)        (gpointer		 thread);
   void      (*thread_exit)        (void);
@@ -3149,10 +3159,11 @@
 			  gulong 		 stack_size,
 			  gboolean 		 joinable,
 			  gboolean 		 bound,
-			  GThreadPriority 	 priority);
+			  GThreadPriority 	 priority,
+			  GError               **err);
 GThread* g_thread_self ();
-void g_thread_join (GThread* thread);
-void g_thread_set_priority (GThread* thread, 
+void g_thread_join (GThread *thread);
+void g_thread_set_priority (GThread         *thread, 
 			    GThreadPriority priority);
 
 /* GStaticMutexes can be statically initialized with the value
@@ -3353,20 +3364,23 @@
 					       gboolean         bound,
 					       GThreadPriority  priority,
 					       gboolean         exclusive,
-					       gpointer         user_data);
+					       gpointer         user_data,
+					       GError         **err);
 
 /* Push new data into the thread pool. This task is assigned to a thread later
  * (when the maximal number of threads is reached for that pool) or now
  * (otherwise). If necessary a new thread will be started. The function
  * returns immediatly */
 void            g_thread_pool_push            (GThreadPool     *pool,
-					       gpointer         data);
+					       gpointer         data,
+					       GError         **err);
 
 /* Set the number of threads, which can run concurrently for that pool, -1
  * means no limit. 0 means has the effect, that the pool won't process
  * requests until the limit is set higher again */
 void            g_thread_pool_set_max_threads (GThreadPool     *pool,
-					       gint             max_threads);
+					       gint             max_threads,
+					       GError         **err);
 gint            g_thread_pool_get_max_threads (GThreadPool     *pool);
 
 /* Get the number of threads assigned to that pool. This number doesn't
@@ -3398,6 +3412,5 @@
 #endif /* __cplusplus */
 
 #include <gunicode.h>
-#include <gerror.h>
 
 #endif /* __G_LIB_H__ */
Index: gthread.c
===================================================================
RCS file: /cvs/gnome/glib/gthread.c,v
retrieving revision 1.6
diff -u -b -B -r1.6 gthread.c
--- gthread.c	2000/07/26 11:01:59	1.6
+++ gthread.c	2000/08/29 13:52:45
@@ -97,7 +97,7 @@
   NULL,                                        /* private_set */
   (void(*)(GThreadFunc, gpointer, gulong, 
 	   gboolean, gboolean, GThreadPriority, 
-	   gpointer))g_thread_fail,            /* thread_create */
+	   gpointer, GError**))g_thread_fail,  /* thread_create */
   NULL,                                        /* thread_yield */
   NULL,                                        /* thread_join */
   NULL,                                        /* thread_exit */
@@ -381,10 +381,10 @@
 		 gulong 		 stack_size,
 		 gboolean 		 joinable,
 		 gboolean 		 bound,
-		 GThreadPriority 	 priority)
+		 GThreadPriority 	 priority,
+		 GError                **err)
 {
   GRealThread* result = g_new (GRealThread, 1);
-
   g_return_val_if_fail (thread_func, NULL);
   
   result->thread.joinable = joinable;
@@ -394,10 +394,15 @@
   result->arg = arg;
   result->private_data = NULL; 
   G_LOCK (g_thread_create);
-  G_THREAD_UF (thread_create, (g_thread_create_proxy, result, stack_size, 
-			       joinable, bound, priority,
-			       &result->system_thread));
+  G_THREAD_UF (thread_create, (g_thread_create_proxy, result, 
+			       stack_size, joinable, bound, priority,
+			       &result->system_thread, err));
   G_UNLOCK (g_thread_create);
+  if (err && *err)
+    {
+      g_free (result);
+      return NULL;
+    }
   return (GThread*) result;
 }
 
Index: gthreadpool.c
===================================================================
RCS file: /cvs/gnome/glib/gthreadpool.c,v
retrieving revision 1.2
diff -u -b -B -r1.2 gthreadpool.c
--- gthreadpool.c	2000/07/26 11:01:59	1.2
+++ gthreadpool.c	2000/08/29 13:52:45
@@ -55,7 +55,7 @@
 
 static void g_thread_pool_free_internal (GRealThreadPool* pool);
 static void g_thread_pool_thread_proxy (gpointer data);
-static void g_thread_pool_start_thread (GRealThreadPool* pool);
+static void g_thread_pool_start_thread (GRealThreadPool* pool, GError **err);
 static void g_thread_pool_wakeup_and_stop_all (GRealThreadPool* pool);
 
 #define g_thread_should_run(pool, len) \
@@ -162,7 +162,8 @@
 }
 
 static void
-g_thread_pool_start_thread (GRealThreadPool* pool)
+g_thread_pool_start_thread (GRealThreadPool  *pool, 
+			    GError          **err)
 {
   gboolean success = FALSE;
   GThreadPriority priority = pool->pool.priority;
@@ -208,7 +209,7 @@
   if (!success)
     /* No thread was found, we have to start one new */
     g_thread_create (g_thread_pool_thread_proxy, pool, pool->pool.stack_size, 
-		     FALSE, pool->pool.bound, priority);
+		     FALSE, pool->pool.bound, priority, err);
 
   /* See comment in g_thread_pool_thread_proxy as to why this is done
    * here and not there */
@@ -222,7 +223,8 @@
 		   gboolean         bound,
 		   GThreadPriority  priority,
 		   gboolean         exclusive,
-		   gpointer         user_data)
+		   gpointer         user_data,
+		   GError         **err)
 {
   GRealThreadPool *retval;
 
@@ -259,7 +261,15 @@
       g_async_queue_lock (retval->queue);
 
       while (retval->num_threads < retval->max_threads)
-	g_thread_pool_start_thread (retval);
+	{
+	  g_thread_pool_start_thread (retval, err);
+	  if (err && *err)
+	    {
+	      g_free (retval);
+	      /* FIXME: free all other threads */
+	      return NULL;
+	    }
+	}
 
       g_async_queue_unlock (retval->queue);
     }
@@ -269,7 +279,8 @@
 
 void 
 g_thread_pool_push (GThreadPool     *pool,
-		    gpointer         data)
+		    gpointer         data,
+		    GError         **err)
 {
   GRealThreadPool *real = (GRealThreadPool*) pool;
 
@@ -286,7 +297,12 @@
   if (!pool->exclusive && g_async_queue_length_unlocked (real->queue) >= 0)
     {
       /* No thread is waiting in the queue */
-      g_thread_pool_start_thread (real);
+      g_thread_pool_start_thread (real, err);
+      if (err && *err)
+	{
+	  g_async_queue_unlock (real->queue);
+	  return;
+	}
     }
   g_async_queue_push_unlocked (real->queue, data);
   g_async_queue_unlock (real->queue);
@@ -294,7 +310,8 @@
 
 void
 g_thread_pool_set_max_threads (GThreadPool     *pool,
-			       gint             max_threads)
+			       gint             max_threads,
+			       GError         **err)
 {
   GRealThreadPool *real = (GRealThreadPool*) pool;
   gint to_start;
@@ -314,7 +331,11 @@
     to_start = g_async_queue_length_unlocked (real->queue);
   
   for ( ; to_start > 0; to_start--)
-    g_thread_pool_start_thread (real);
+    {
+      g_thread_pool_start_thread (real, err);
+      if (err && *err)
+	break;
+    }
     
   g_async_queue_unlock (real->queue);
 }
Index: gthread/gthread-posix.c
===================================================================
RCS file: /cvs/gnome/glib/gthread/gthread-posix.c,v
retrieving revision 1.17
diff -u -b -B -r1.17 gthread-posix.c
--- gthread/gthread-posix.c	2000/07/26 11:02:01	1.17
+++ gthread/gthread-posix.c	2000/08/29 13:52:45
@@ -232,9 +232,11 @@
 			    gboolean joinable,
 			    gboolean bound,
 			    GThreadPriority priority,
-			    gpointer thread)
+			    gpointer thread,
+			    GError **err)
 {
   pthread_attr_t attr;
+  gint ret;
 
   g_return_if_fail (thread_func);
 
@@ -274,11 +276,23 @@
 # endif /* G_THREADS_IMPL_DCE */
 #endif /* HAVE_PRIORITIES */
 
-  posix_check_for_error (pthread_create (thread, &attr, 
-                                         (void* (*)(void*))thread_func,
-                                         arg));
+  ret = pthread_create (thread, &attr, (void* (*)(void*))thread_func, arg);
   
+#ifdef G_THREADS_IMPL_DCE
+  if (ret == -1) 
+    ret = errno;
+  else
+    ret = 0;
+#endif /* G_THREADS_IMPL_DCE */
+
   posix_check_for_error (pthread_attr_destroy (&attr));
+
+  if (ret)
+    {
+      g_set_error (err, glib_error_domain (), GLIB_ERROR_AGAIN, 
+		   "Error creating thread: %s", g_strerror (ret));
+      return;
+    }
 
 #ifdef G_THREADS_IMPL_DCE
   if (!joinable)
Index: tests/thread-test.c
===================================================================
RCS file: /cvs/gnome/glib/tests/thread-test.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 thread-test.c
--- tests/thread-test.c	2000/04/19 09:29:19	1.3
+++ tests/thread-test.c	2000/08/29 13:52:45
@@ -27,7 +27,7 @@
   g_assert (G_TRYLOCK (test_g_mutex));
   thread = g_thread_create (test_g_mutex_thread, 
 			    GINT_TO_POINTER (42),
-			    0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL);
+			    0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL);
   g_usleep (G_MICROSEC);
   test_g_mutex_int = 42;
   G_UNLOCK (test_g_mutex);
@@ -62,7 +62,7 @@
   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
   thread = g_thread_create (test_g_static_rec_mutex_thread, 
 			    GINT_TO_POINTER (42),
-			    0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL);
+			    0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL);
   g_usleep (G_MICROSEC);
   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
   g_usleep (G_MICROSEC);
@@ -136,7 +136,7 @@
       threads[i] = g_thread_create (test_g_static_private_thread, 
 				    GINT_TO_POINTER (i),
 				    0, TRUE, TRUE, 
-				    G_THREAD_PRIORITY_NORMAL);      
+				    G_THREAD_PRIORITY_NORMAL, NULL);      
     }
   for (i = 0; i < THREADS; i++)
     {
@@ -213,7 +213,7 @@
     {
       threads[i] = g_thread_create (test_g_static_rw_lock_thread, 
 				    0, 0, TRUE, TRUE, 
-				    G_THREAD_PRIORITY_NORMAL);      
+				    G_THREAD_PRIORITY_NORMAL, NULL);      
     }
   g_usleep (G_MICROSEC);
   test_g_static_rw_lock_run = FALSE;
@@ -238,10 +238,21 @@
 main (int   argc,
       char *argv[])
 {
+  int i;
+  GError *err = NULL;
+  g_thread_init (NULL);
   /* Only run the test, if threads are enabled and a default thread
      implementation is available */
+  for (i = 0; i < 10000; i++)
+    {
+      g_thread_create (test_g_static_rw_lock_thread, 
+		       0, 0, TRUE, TRUE, 
+		       G_THREAD_PRIORITY_NORMAL, &err);      
+      g_print ("%d\n",i);
+      if (err)
+	g_error ("%d, %d, %s.\n", err->domain, err->code, err->message);
+    }
 #if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
-  g_thread_init (NULL);
   run_all_tests ();
 
   /* Now we rerun all tests, but this time we fool the system into
Index: tests/threadpool-test.c
===================================================================
RCS file: /cvs/gnome/glib/tests/threadpool-test.c,v
retrieving revision 1.1
diff -u -b -B -r1.1 threadpool-test.c
--- tests/threadpool-test.c	2000/04/28 12:24:53	1.1
+++ tests/threadpool-test.c	2000/08/29 13:52:45
@@ -33,17 +33,17 @@
   g_thread_init (NULL);
   
   pool1 = g_thread_pool_new (thread_pool_func, 3, 0, FALSE, 
-                            G_THREAD_PRIORITY_NORMAL, FALSE, NULL);
+                            G_THREAD_PRIORITY_NORMAL, FALSE, NULL, NULL);
   pool2 = g_thread_pool_new (thread_pool_func, 5, 0, FALSE, 
-			     G_THREAD_PRIORITY_LOW, FALSE, NULL);
+			     G_THREAD_PRIORITY_LOW, FALSE, NULL, NULL);
   pool3 = g_thread_pool_new (thread_pool_func, 7, 0, FALSE, 
-                             G_THREAD_PRIORITY_LOW, TRUE, NULL);
+                             G_THREAD_PRIORITY_LOW, TRUE, NULL, NULL);
 
   for (i = 0; i < RUNS; i++)
     {
-      g_thread_pool_push (pool1, GUINT_TO_POINTER (1));
-      g_thread_pool_push (pool2, GUINT_TO_POINTER (1));
-      g_thread_pool_push (pool3, GUINT_TO_POINTER (1));
+      g_thread_pool_push (pool1, GUINT_TO_POINTER (1), NULL);
+      g_thread_pool_push (pool2, GUINT_TO_POINTER (1), NULL);
+      g_thread_pool_push (pool3, GUINT_TO_POINTER (1), NULL);
     } 
   
   g_thread_pool_free (pool1, FALSE, TRUE);


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