g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
g_propagte_error to hand over local errors to the calling
function.
+ * glib.h: Include gerror.h before it is used for some g_thread_*
+ functions.
+
+ * gthread.c, gthreadpool.c, glib.h: Enable error reporting for
+ thread creation, namly for g_thread_create, g_thread_pool_new,
+ g_thread_pool_push and g_thread_pool_set_max_threads.
+
+ * tests/thread-test.c, tests/threadpool-test.c: Adapted
+ accordingly.
+
2000-08-31 Tor Lillqvist <tml@iki.fi>
* glib.h
guint len;
};
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include <gerror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
/* IEEE Standard 754 Single Precision Storage Format (gfloat):
*
/* GLib Thread support
*/
+extern GQuark g_thread_error_quark();
+#define G_THREAD_ERROR g_thread_error_quark()
+
+typedef enum
+{
+ G_THREAD_ERROR_AGAIN /* Resource temporarily unavailable */
+} GThreadError;
+
typedef void (*GThreadFunc) (gpointer value);
typedef enum
gboolean joinable,
gboolean bound,
GThreadPriority priority,
- gpointer thread);
+ gpointer thread,
+ GError **error);
void (*thread_yield) (void);
void (*thread_join) (gpointer thread);
void (*thread_exit) (void);
gulong stack_size,
gboolean joinable,
gboolean bound,
- GThreadPriority priority);
+ GThreadPriority priority,
+ GError **error);
GThread* g_thread_self ();
-void g_thread_join (GThread* thread);
-void g_thread_set_priority (GThread* thread,
- GThreadPriority priority);
+void g_thread_join (GThread *thread);
+void g_thread_set_priority (GThread *thread,
+ GThreadPriority priority);
/* GStaticMutexes can be statically initialized with the value
* G_STATIC_MUTEX_INIT, and then they can directly be used, that is
gboolean bound,
GThreadPriority priority,
gboolean exclusive,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
/* 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 **error);
/* 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 **error);
gint g_thread_pool_get_max_threads (GThreadPool *pool);
/* Get the number of threads assigned to that pool. This number doesn't
#endif /* __cplusplus */
#include <gunicode.h>
-#include <gerror.h>
#endif /* __G_LIB_H__ */
guint len;
};
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include <gerror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
/* IEEE Standard 754 Single Precision Storage Format (gfloat):
*
/* GLib Thread support
*/
+extern GQuark g_thread_error_quark();
+#define G_THREAD_ERROR g_thread_error_quark()
+
+typedef enum
+{
+ G_THREAD_ERROR_AGAIN /* Resource temporarily unavailable */
+} GThreadError;
+
typedef void (*GThreadFunc) (gpointer value);
typedef enum
gboolean joinable,
gboolean bound,
GThreadPriority priority,
- gpointer thread);
+ gpointer thread,
+ GError **error);
void (*thread_yield) (void);
void (*thread_join) (gpointer thread);
void (*thread_exit) (void);
gulong stack_size,
gboolean joinable,
gboolean bound,
- GThreadPriority priority);
+ GThreadPriority priority,
+ GError **error);
GThread* g_thread_self ();
-void g_thread_join (GThread* thread);
-void g_thread_set_priority (GThread* thread,
- GThreadPriority priority);
+void g_thread_join (GThread *thread);
+void g_thread_set_priority (GThread *thread,
+ GThreadPriority priority);
/* GStaticMutexes can be statically initialized with the value
* G_STATIC_MUTEX_INIT, and then they can directly be used, that is
gboolean bound,
GThreadPriority priority,
gboolean exclusive,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
/* 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 **error);
/* 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 **error);
gint g_thread_pool_get_max_threads (GThreadPool *pool);
/* Get the number of threads assigned to that pool. This number doesn't
#endif /* __cplusplus */
#include <gunicode.h>
-#include <gerror.h>
#endif /* __G_LIB_H__ */
(memcpy (&dest, &src, GLIB_SIZEOF_SYSTEM_THREAD))
#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
+GQuark
+g_thread_error_quark()
+{
+ static GQuark quark;
+ G_LOCK_DEFINE_STATIC(lock);
+ if (!quark)
+ {
+ G_LOCK (lock);
+ if (!quark)
+ quark = g_quark_from_static_string ("g-thread-error");
+ G_UNLOCK (lock);
+ }
+ return quark;
+}
+
typedef struct _GRealThread GRealThread;
struct _GRealThread
{
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 */
gulong stack_size,
gboolean joinable,
gboolean bound,
- GThreadPriority priority)
+ GThreadPriority priority,
+ GError **error)
{
GRealThread* result = g_new (GRealThread, 1);
-
+ GError *local_error = NULL;
g_return_val_if_fail (thread_func, NULL);
result->thread.joinable = joinable;
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, &local_error));
G_UNLOCK (g_thread_create);
+
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ g_free (result);
+ return NULL;
+ }
+
return (GThread*) result;
}
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 **error);
static void g_thread_pool_wakeup_and_stop_all (GRealThreadPool* pool);
#define g_thread_should_run(pool, len) \
}
static void
-g_thread_pool_start_thread (GRealThreadPool* pool)
+g_thread_pool_start_thread (GRealThreadPool *pool,
+ GError **error)
{
gboolean success = FALSE;
GThreadPriority priority = pool->pool.priority;
}
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);
+ {
+ GError *local_error = NULL;
+ /* 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, &local_error);
+
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ return;
+ }
+ }
/* See comment in g_thread_pool_thread_proxy as to why this is done
* here and not there */
gboolean bound,
GThreadPriority priority,
gboolean exclusive,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
GRealThreadPool *retval;
if (retval->pool.exclusive)
{
g_async_queue_lock (retval->queue);
-
+
while (retval->num_threads < retval->max_threads)
- g_thread_pool_start_thread (retval);
+ {
+ GError *local_error = NULL;
+ g_thread_pool_start_thread (retval, &local_error);
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ break;
+ }
+ }
g_async_queue_unlock (retval->queue);
}
void
g_thread_pool_push (GThreadPool *pool,
- gpointer data)
+ gpointer data,
+ GError **error)
{
GRealThreadPool *real = (GRealThreadPool*) pool;
}
if (!pool->exclusive && g_async_queue_length_unlocked (real->queue) >= 0)
- {
- /* No thread is waiting in the queue */
- g_thread_pool_start_thread (real);
- }
+ /* No thread is waiting in the queue */
+ g_thread_pool_start_thread (real, error);
+
g_async_queue_push_unlocked (real->queue, data);
g_async_queue_unlock (real->queue);
}
void
g_thread_pool_set_max_threads (GThreadPool *pool,
- gint max_threads)
+ gint max_threads,
+ GError **error)
{
GRealThreadPool *real = (GRealThreadPool*) pool;
gint to_start;
to_start = g_async_queue_length_unlocked (real->queue);
for ( ; to_start > 0; to_start--)
- g_thread_pool_start_thread (real);
-
+ {
+ GError *local_error = NULL;
+ g_thread_pool_start_thread (real, &local_error);
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ break;
+ }
+ }
+
g_async_queue_unlock (real->queue);
}
(memcpy (&dest, &src, GLIB_SIZEOF_SYSTEM_THREAD))
#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
+GQuark
+g_thread_error_quark()
+{
+ static GQuark quark;
+ G_LOCK_DEFINE_STATIC(lock);
+ if (!quark)
+ {
+ G_LOCK (lock);
+ if (!quark)
+ quark = g_quark_from_static_string ("g-thread-error");
+ G_UNLOCK (lock);
+ }
+ return quark;
+}
+
typedef struct _GRealThread GRealThread;
struct _GRealThread
{
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 */
gulong stack_size,
gboolean joinable,
gboolean bound,
- GThreadPriority priority)
+ GThreadPriority priority,
+ GError **error)
{
GRealThread* result = g_new (GRealThread, 1);
-
+ GError *local_error = NULL;
g_return_val_if_fail (thread_func, NULL);
result->thread.joinable = joinable;
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, &local_error));
G_UNLOCK (g_thread_create);
+
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ g_free (result);
+ return NULL;
+ }
+
return (GThread*) result;
}
+2000-09-01 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gthread-posix.c (g_thread_create_posix_impl): Use GError to
+ report errors.
+
2000-05-13 Tor Lillqvist <tml@iki.fi>
* makefile.mingw.in: New file, with gthread stuff moved from
gboolean joinable,
gboolean bound,
GThreadPriority priority,
- gpointer thread)
+ gpointer thread,
+ GError **error)
{
pthread_attr_t attr;
+ gint ret;
g_return_if_fail (thread_func);
# 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 (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN,
+ "Error creating thread: %s", g_strerror (ret));
+ return;
+ }
+
#ifdef G_THREADS_IMPL_DCE
if (!joinable)
posix_check_for_error (pthread_detach (thread));
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 **error);
static void g_thread_pool_wakeup_and_stop_all (GRealThreadPool* pool);
#define g_thread_should_run(pool, len) \
}
static void
-g_thread_pool_start_thread (GRealThreadPool* pool)
+g_thread_pool_start_thread (GRealThreadPool *pool,
+ GError **error)
{
gboolean success = FALSE;
GThreadPriority priority = pool->pool.priority;
}
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);
+ {
+ GError *local_error = NULL;
+ /* 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, &local_error);
+
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ return;
+ }
+ }
/* See comment in g_thread_pool_thread_proxy as to why this is done
* here and not there */
gboolean bound,
GThreadPriority priority,
gboolean exclusive,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
GRealThreadPool *retval;
if (retval->pool.exclusive)
{
g_async_queue_lock (retval->queue);
-
+
while (retval->num_threads < retval->max_threads)
- g_thread_pool_start_thread (retval);
+ {
+ GError *local_error = NULL;
+ g_thread_pool_start_thread (retval, &local_error);
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ break;
+ }
+ }
g_async_queue_unlock (retval->queue);
}
void
g_thread_pool_push (GThreadPool *pool,
- gpointer data)
+ gpointer data,
+ GError **error)
{
GRealThreadPool *real = (GRealThreadPool*) pool;
}
if (!pool->exclusive && g_async_queue_length_unlocked (real->queue) >= 0)
- {
- /* No thread is waiting in the queue */
- g_thread_pool_start_thread (real);
- }
+ /* No thread is waiting in the queue */
+ g_thread_pool_start_thread (real, error);
+
g_async_queue_push_unlocked (real->queue, data);
g_async_queue_unlock (real->queue);
}
void
g_thread_pool_set_max_threads (GThreadPool *pool,
- gint max_threads)
+ gint max_threads,
+ GError **error)
{
GRealThreadPool *real = (GRealThreadPool*) pool;
gint to_start;
to_start = g_async_queue_length_unlocked (real->queue);
for ( ; to_start > 0; to_start--)
- g_thread_pool_start_thread (real);
-
+ {
+ GError *local_error = NULL;
+ g_thread_pool_start_thread (real, &local_error);
+ if (local_error)
+ {
+ g_propagate_error (error, local_error);
+ break;
+ }
+ }
+
g_async_queue_unlock (real->queue);
}
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);
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);
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++)
{
{
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;
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);