gerror.c revisited
- From: Sebastian Wilhelmi <wilhelmi ira uka de>
- To: Gtk Development List <gtk-devel-list gnome org>
- Subject: gerror.c revisited
- Date: Tue, 29 Aug 2000 16:09:00 +0200
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]