Renamed g_thread_create to g_thread_create_full and added macro

2001-05-18  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>

	* gthread.c, gthread.h: Renamed g_thread_create to
	g_thread_create_full and added macro g_thread_create, which omits
	'stack_size', 'bound' and 'priority' parameters. Also removed
	'bound' from GThread struct.

	* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
	changes. GThreadPool lost the 'priority' and 'bound'
	members. g_thread_pool_new the 'stack_size', 'bound' and
	'priority' parameters.

	* tests/mainloop-test.c, tests/thread-test.c,
	tests/threadpool-test.c: Adapted to the above changes.
This commit is contained in:
Sebastian Wilhelmi
2001-05-18 08:44:57 +00:00
committed by Sebastian Wilhelmi
parent a70206f177
commit 227d18bc46
19 changed files with 187 additions and 222 deletions

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -1,5 +1,18 @@
2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-18 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.c, gthread.h: Renamed g_thread_create to
g_thread_create_full and added macro g_thread_create, which omits
'stack_size', 'bound' and 'priority' parameters. Also removed
'bound' from GThread struct.
* gthreadpool.h, gthreadpool.c: Adapted GThreadPool to the above
changes. GThreadPool lost the 'priority' and 'bound'
members. g_thread_pool_new the 'stack_size', 'bound' and
'priority' parameters.
* tests/mainloop-test.c, tests/thread-test.c,
tests/threadpool-test.c: Adapted to the above changes.
* gmem.c (g_mem_profile): Fixed mutex deadlock. * gmem.c (g_mem_profile): Fixed mutex deadlock.
2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de> 2001-05-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>

View File

@@ -541,13 +541,13 @@ g_thread_create_proxy (gpointer data)
} }
GThread* GThread*
g_thread_create (GThreadFunc func, g_thread_create_full (GThreadFunc func,
gpointer data, gpointer data,
gulong stack_size, gulong stack_size,
gboolean joinable, gboolean joinable,
gboolean bound, gboolean bound,
GThreadPriority priority, GThreadPriority priority,
GError **error) GError **error)
{ {
GRealThread* result = g_new (GRealThread, 1); GRealThread* result = g_new (GRealThread, 1);
GError *local_error = NULL; GError *local_error = NULL;
@@ -556,7 +556,6 @@ g_thread_create (GThreadFunc func,
g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL); g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL);
result->thread.joinable = joinable; result->thread.joinable = joinable;
result->thread.bound = bound;
result->thread.priority = priority; result->thread.priority = priority;
result->thread.func = func; result->thread.func = func;
result->thread.data = data; result->thread.data = data;
@@ -653,7 +652,6 @@ g_thread_self (void)
created by GLib. */ created by GLib. */
thread = g_new (GRealThread, 1); thread = g_new (GRealThread, 1);
thread->thread.joinable = FALSE; /* This is a save guess */ thread->thread.joinable = FALSE; /* This is a save guess */
thread->thread.bound = TRUE; /* This isn't important at all */
thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
just a guess */ just a guess */
thread->thread.func = NULL; thread->thread.func = NULL;

View File

@@ -59,7 +59,6 @@ struct _GThread
GThreadFunc func; GThreadFunc func;
gpointer data; gpointer data;
gboolean joinable; gboolean joinable;
gboolean bound;
GThreadPriority priority; GThreadPriority priority;
}; };
@@ -194,7 +193,11 @@ GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex);
(private_key, value)) (private_key, value))
#define g_thread_yield() G_THREAD_CF (thread_yield, (void)0, ()) #define g_thread_yield() G_THREAD_CF (thread_yield, (void)0, ())
GThread* g_thread_create (GThreadFunc func, #define g_thread_create(func, data, joinable, error) \
(g_thread_create_full (func, data, 0, joinable, FALSE, \
G_THREAD_PRIORITY_NORMAL, error))
GThread* g_thread_create_full (GThreadFunc func,
gpointer data, gpointer data,
gulong stack_size, gulong stack_size,
gboolean joinable, gboolean joinable,

View File

@@ -31,7 +31,6 @@ typedef struct _GRealThreadPool GRealThreadPool;
struct _GRealThreadPool struct _GRealThreadPool
{ {
GThreadPool pool; GThreadPool pool;
gulong stack_size;
GAsyncQueue* queue; GAsyncQueue* queue;
gint max_threads; gint max_threads;
gint num_threads; gint num_threads;
@@ -45,8 +44,8 @@ struct _GRealThreadPool
* GThreadPool address) */ * GThreadPool address) */
static const gpointer stop_this_thread_marker = (gpointer) &g_thread_pool_new; static const gpointer stop_this_thread_marker = (gpointer) &g_thread_pool_new;
/* Here all unused threads are waiting, depending on their priority */ /* Here all unused threads are waiting */
static GAsyncQueue *unused_thread_queue[G_THREAD_PRIORITY_URGENT + 1][2]; static GAsyncQueue *unused_thread_queue;
static gint unused_threads = 0; static gint unused_threads = 0;
static gint max_unused_threads = 0; static gint max_unused_threads = 0;
G_LOCK_DEFINE_STATIC (unused_threads); G_LOCK_DEFINE_STATIC (unused_threads);
@@ -73,8 +72,7 @@ g_thread_pool_thread_proxy (gpointer data)
while (TRUE) while (TRUE)
{ {
gpointer task; gpointer task;
gboolean goto_global_pool = gboolean goto_global_pool = !pool->pool.exclusive;
!pool->pool.exclusive && pool->stack_size == 0;
gint len = g_async_queue_length_unlocked (pool->queue); gint len = g_async_queue_length_unlocked (pool->queue);
if (g_thread_should_run (pool, len)) if (g_thread_should_run (pool, len))
@@ -147,8 +145,6 @@ g_thread_pool_thread_proxy (gpointer data)
if (goto_global_pool) if (goto_global_pool)
{ {
GAsyncQueue *unused_queue =
unused_thread_queue[pool->pool.priority][pool->pool.bound ? 1 : 0];
pool->num_threads--; pool->num_threads--;
if (!pool->running && !pool->waiting) if (!pool->running && !pool->waiting)
@@ -167,27 +163,27 @@ g_thread_pool_thread_proxy (gpointer data)
else else
g_async_queue_unlock (pool->queue); g_async_queue_unlock (pool->queue);
g_async_queue_lock (unused_queue); g_async_queue_lock (unused_thread_queue);
G_LOCK (unused_threads); G_LOCK (unused_threads);
if ((unused_threads >= max_unused_threads && if ((unused_threads >= max_unused_threads &&
max_unused_threads != -1) || pool->stack_size != 0) max_unused_threads != -1))
{ {
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);
g_async_queue_unlock (unused_queue); g_async_queue_unlock (unused_thread_queue);
/* Stop this thread */ /* Stop this thread */
return NULL; return NULL;
} }
unused_threads++; unused_threads++;
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);
pool = g_async_queue_pop_unlocked (unused_queue); pool = g_async_queue_pop_unlocked (unused_thread_queue);
G_LOCK (unused_threads); G_LOCK (unused_threads);
unused_threads--; unused_threads--;
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);
g_async_queue_unlock (unused_queue); g_async_queue_unlock (unused_thread_queue);
if (pool == stop_this_thread_marker) if (pool == stop_this_thread_marker)
/* Stop this thread */ /* Stop this thread */
@@ -208,35 +204,26 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
GError **error) GError **error)
{ {
gboolean success = FALSE; gboolean success = FALSE;
GThreadPriority priority = pool->pool.priority;
guint bound = pool->pool.bound ? 1 : 0;
GAsyncQueue *queue = unused_thread_queue[priority][bound];
if (pool->num_threads >= pool->max_threads && pool->max_threads != -1) if (pool->num_threads >= pool->max_threads && pool->max_threads != -1)
/* Enough threads are already running */ /* Enough threads are already running */
return; return;
g_async_queue_lock (queue); g_async_queue_lock (unused_thread_queue);
if (g_async_queue_length_unlocked (queue) < 0) if (g_async_queue_length_unlocked (unused_thread_queue) < 0)
{ {
/* First we try a thread with the right priority */ g_async_queue_push_unlocked (unused_thread_queue, pool);
g_async_queue_push_unlocked (queue, pool);
success = TRUE; success = TRUE;
} }
g_async_queue_unlock (queue); g_async_queue_unlock (unused_thread_queue);
/* We will not search for threads with other priorities, because changing
* priority is quite unportable */
if (!success) if (!success)
{ {
GError *local_error = NULL; GError *local_error = NULL;
/* No thread was found, we have to start a new one */ /* No thread was found, we have to start a new one */
g_thread_create (g_thread_pool_thread_proxy, pool, g_thread_create (g_thread_pool_thread_proxy, pool, FALSE, &local_error);
pool->stack_size, FALSE,
bound, priority, &local_error);
if (local_error) if (local_error)
{ {
@@ -257,17 +244,10 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
* is called * is called
* @max_threads: the maximal number of threads to execute concurrently in * @max_threads: the maximal number of threads to execute concurrently in
* the new thread pool, -1 means no limit * the new thread pool, -1 means no limit
* @stack_size: the stack size for the threads of the new thread pool,
* 0 means using the standard
* @bound: should the threads of the new thread pool be bound?
* @priority: a priority for the threads of the new thread pool
* @exclusive: should this thread pool be exclusive? * @exclusive: should this thread pool be exclusive?
* @error: return location for error * @error: return location for error
* *
* This function creates a new thread pool. All threads created within * This function creates a new thread pool.
* this thread pool will have the priority @priority and the stack
* size @stack_size and will be bound if and only if @bound is
* true.
* *
* Whenever you call g_thread_pool_push(), either a new thread is * Whenever you call g_thread_pool_push(), either a new thread is
* created or an unused one is reused. At most @max_threads threads * created or an unused one is reused. At most @max_threads threads
@@ -286,12 +266,6 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
* non-exclusive thread pools. This implies that @max_threads may not * non-exclusive thread pools. This implies that @max_threads may not
* be -1 for exclusive thread pools. * be -1 for exclusive thread pools.
* *
* Note, that only threads from a thread pool with a @stack_size of 0
* (which means using the standard stack size) will be globally
* reused. Threads from a thread pool with a non-zero stack size will
* stay only in this thread pool until it is freed and can thus not be
* controlled by the g_thread_pool_set_unused_threads() function.
*
* @error can be NULL to ignore errors, or non-NULL to report * @error can be NULL to ignore errors, or non-NULL to report
* errors. An error can only occur, when @exclusive is set to @TRUE and * errors. An error can only occur, when @exclusive is set to @TRUE and
* not all @max_threads threads could be created. * not all @max_threads threads could be created.
@@ -302,9 +276,6 @@ GThreadPool*
g_thread_pool_new (GFunc func, g_thread_pool_new (GFunc func,
gpointer user_data, gpointer user_data,
gint max_threads, gint max_threads,
gulong stack_size,
gboolean bound,
GThreadPriority priority,
gboolean exclusive, gboolean exclusive,
GError **error) GError **error)
{ {
@@ -320,10 +291,7 @@ g_thread_pool_new (GFunc func,
retval->pool.func = func; retval->pool.func = func;
retval->pool.user_data = user_data; retval->pool.user_data = user_data;
retval->pool.bound = bound;
retval->pool.priority = priority;
retval->pool.exclusive = exclusive; retval->pool.exclusive = exclusive;
retval->stack_size = stack_size;
retval->queue = g_async_queue_new (); retval->queue = g_async_queue_new ();
retval->max_threads = max_threads; retval->max_threads = max_threads;
retval->num_threads = 0; retval->num_threads = 0;
@@ -335,12 +303,7 @@ g_thread_pool_new (GFunc func,
{ {
inform_mutex = g_mutex_new (); inform_mutex = g_mutex_new ();
inform_cond = g_cond_new (); inform_cond = g_cond_new ();
for (priority = G_THREAD_PRIORITY_LOW; unused_thread_queue = g_async_queue_new ();
priority < G_THREAD_PRIORITY_URGENT + 1; priority++)
{
unused_thread_queue[priority][0] = g_async_queue_new ();
unused_thread_queue[priority][1] = g_async_queue_new ();
}
} }
G_UNLOCK (init); G_UNLOCK (init);
@@ -659,37 +622,13 @@ g_thread_pool_set_max_unused_threads (gint max_threads)
if (max_unused_threads < unused_threads && max_unused_threads != -1) if (max_unused_threads < unused_threads && max_unused_threads != -1)
{ {
guint close_down_num = unused_threads - max_unused_threads; guint i;
while (close_down_num > 0) g_async_queue_lock (unused_thread_queue);
{ for (i = unused_threads - max_unused_threads; i > 0; i--)
GThreadPriority priority; g_async_queue_push_unlocked (unused_thread_queue,
guint bound; stop_this_thread_marker);
g_async_queue_unlock (unused_thread_queue);
guint old_close_down_num = close_down_num;
for (priority = G_THREAD_PRIORITY_LOW;
priority < G_THREAD_PRIORITY_URGENT + 1 && close_down_num > 0;
priority++)
{
for (bound = 0; bound < 2; bound++)
{
GAsyncQueue *queue = unused_thread_queue[priority][bound];
g_async_queue_lock (queue);
if (g_async_queue_length_unlocked (queue) < 0)
{
g_async_queue_push_unlocked (queue,
stop_this_thread_marker);
close_down_num--;
}
g_async_queue_unlock (queue);
}
}
/* Just to make sure, there are no counting problems */
g_assert (old_close_down_num != close_down_num);
}
} }
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);

View File

@@ -42,22 +42,17 @@ struct _GThreadPool
{ {
GFunc func; GFunc func;
gpointer user_data; gpointer user_data;
gboolean bound;
GThreadPriority priority;
gboolean exclusive; gboolean exclusive;
}; };
/* Get a thread pool with the function func, at most max_threads may /* Get a thread pool with the function func, at most max_threads may
* run at a time (max_threads == -1 means no limit), stack_size, bound, * run at a time (max_threads == -1 means no limit), exclusive == TRUE
* priority like in g_thread_create, exclusive == TRUE means, that the threads * means, that the threads shouldn't be shared and that they will be
* shouldn't be shared and that they will be prestarted (otherwise they are * prestarted (otherwise they are started as needed) user_data is the
* started as needed) user_data is the 2nd argument to the func */ * 2nd argument to the func */
GThreadPool* g_thread_pool_new (GFunc func, GThreadPool* g_thread_pool_new (GFunc func,
gpointer user_data, gpointer user_data,
gint max_threads, gint max_threads,
gulong stack_size,
gboolean bound,
GThreadPriority priority,
gboolean exclusive, gboolean exclusive,
GError **error); GError **error);

View File

@@ -541,13 +541,13 @@ g_thread_create_proxy (gpointer data)
} }
GThread* GThread*
g_thread_create (GThreadFunc func, g_thread_create_full (GThreadFunc func,
gpointer data, gpointer data,
gulong stack_size, gulong stack_size,
gboolean joinable, gboolean joinable,
gboolean bound, gboolean bound,
GThreadPriority priority, GThreadPriority priority,
GError **error) GError **error)
{ {
GRealThread* result = g_new (GRealThread, 1); GRealThread* result = g_new (GRealThread, 1);
GError *local_error = NULL; GError *local_error = NULL;
@@ -556,7 +556,6 @@ g_thread_create (GThreadFunc func,
g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL); g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL);
result->thread.joinable = joinable; result->thread.joinable = joinable;
result->thread.bound = bound;
result->thread.priority = priority; result->thread.priority = priority;
result->thread.func = func; result->thread.func = func;
result->thread.data = data; result->thread.data = data;
@@ -653,7 +652,6 @@ g_thread_self (void)
created by GLib. */ created by GLib. */
thread = g_new (GRealThread, 1); thread = g_new (GRealThread, 1);
thread->thread.joinable = FALSE; /* This is a save guess */ thread->thread.joinable = FALSE; /* This is a save guess */
thread->thread.bound = TRUE; /* This isn't important at all */
thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
just a guess */ just a guess */
thread->thread.func = NULL; thread->thread.func = NULL;

View File

@@ -59,7 +59,6 @@ struct _GThread
GThreadFunc func; GThreadFunc func;
gpointer data; gpointer data;
gboolean joinable; gboolean joinable;
gboolean bound;
GThreadPriority priority; GThreadPriority priority;
}; };
@@ -194,7 +193,11 @@ GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex);
(private_key, value)) (private_key, value))
#define g_thread_yield() G_THREAD_CF (thread_yield, (void)0, ()) #define g_thread_yield() G_THREAD_CF (thread_yield, (void)0, ())
GThread* g_thread_create (GThreadFunc func, #define g_thread_create(func, data, joinable, error) \
(g_thread_create_full (func, data, 0, joinable, FALSE, \
G_THREAD_PRIORITY_NORMAL, error))
GThread* g_thread_create_full (GThreadFunc func,
gpointer data, gpointer data,
gulong stack_size, gulong stack_size,
gboolean joinable, gboolean joinable,

View File

@@ -31,7 +31,6 @@ typedef struct _GRealThreadPool GRealThreadPool;
struct _GRealThreadPool struct _GRealThreadPool
{ {
GThreadPool pool; GThreadPool pool;
gulong stack_size;
GAsyncQueue* queue; GAsyncQueue* queue;
gint max_threads; gint max_threads;
gint num_threads; gint num_threads;
@@ -45,8 +44,8 @@ struct _GRealThreadPool
* GThreadPool address) */ * GThreadPool address) */
static const gpointer stop_this_thread_marker = (gpointer) &g_thread_pool_new; static const gpointer stop_this_thread_marker = (gpointer) &g_thread_pool_new;
/* Here all unused threads are waiting, depending on their priority */ /* Here all unused threads are waiting */
static GAsyncQueue *unused_thread_queue[G_THREAD_PRIORITY_URGENT + 1][2]; static GAsyncQueue *unused_thread_queue;
static gint unused_threads = 0; static gint unused_threads = 0;
static gint max_unused_threads = 0; static gint max_unused_threads = 0;
G_LOCK_DEFINE_STATIC (unused_threads); G_LOCK_DEFINE_STATIC (unused_threads);
@@ -73,8 +72,7 @@ g_thread_pool_thread_proxy (gpointer data)
while (TRUE) while (TRUE)
{ {
gpointer task; gpointer task;
gboolean goto_global_pool = gboolean goto_global_pool = !pool->pool.exclusive;
!pool->pool.exclusive && pool->stack_size == 0;
gint len = g_async_queue_length_unlocked (pool->queue); gint len = g_async_queue_length_unlocked (pool->queue);
if (g_thread_should_run (pool, len)) if (g_thread_should_run (pool, len))
@@ -147,8 +145,6 @@ g_thread_pool_thread_proxy (gpointer data)
if (goto_global_pool) if (goto_global_pool)
{ {
GAsyncQueue *unused_queue =
unused_thread_queue[pool->pool.priority][pool->pool.bound ? 1 : 0];
pool->num_threads--; pool->num_threads--;
if (!pool->running && !pool->waiting) if (!pool->running && !pool->waiting)
@@ -167,27 +163,27 @@ g_thread_pool_thread_proxy (gpointer data)
else else
g_async_queue_unlock (pool->queue); g_async_queue_unlock (pool->queue);
g_async_queue_lock (unused_queue); g_async_queue_lock (unused_thread_queue);
G_LOCK (unused_threads); G_LOCK (unused_threads);
if ((unused_threads >= max_unused_threads && if ((unused_threads >= max_unused_threads &&
max_unused_threads != -1) || pool->stack_size != 0) max_unused_threads != -1))
{ {
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);
g_async_queue_unlock (unused_queue); g_async_queue_unlock (unused_thread_queue);
/* Stop this thread */ /* Stop this thread */
return NULL; return NULL;
} }
unused_threads++; unused_threads++;
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);
pool = g_async_queue_pop_unlocked (unused_queue); pool = g_async_queue_pop_unlocked (unused_thread_queue);
G_LOCK (unused_threads); G_LOCK (unused_threads);
unused_threads--; unused_threads--;
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);
g_async_queue_unlock (unused_queue); g_async_queue_unlock (unused_thread_queue);
if (pool == stop_this_thread_marker) if (pool == stop_this_thread_marker)
/* Stop this thread */ /* Stop this thread */
@@ -208,35 +204,26 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
GError **error) GError **error)
{ {
gboolean success = FALSE; gboolean success = FALSE;
GThreadPriority priority = pool->pool.priority;
guint bound = pool->pool.bound ? 1 : 0;
GAsyncQueue *queue = unused_thread_queue[priority][bound];
if (pool->num_threads >= pool->max_threads && pool->max_threads != -1) if (pool->num_threads >= pool->max_threads && pool->max_threads != -1)
/* Enough threads are already running */ /* Enough threads are already running */
return; return;
g_async_queue_lock (queue); g_async_queue_lock (unused_thread_queue);
if (g_async_queue_length_unlocked (queue) < 0) if (g_async_queue_length_unlocked (unused_thread_queue) < 0)
{ {
/* First we try a thread with the right priority */ g_async_queue_push_unlocked (unused_thread_queue, pool);
g_async_queue_push_unlocked (queue, pool);
success = TRUE; success = TRUE;
} }
g_async_queue_unlock (queue); g_async_queue_unlock (unused_thread_queue);
/* We will not search for threads with other priorities, because changing
* priority is quite unportable */
if (!success) if (!success)
{ {
GError *local_error = NULL; GError *local_error = NULL;
/* No thread was found, we have to start a new one */ /* No thread was found, we have to start a new one */
g_thread_create (g_thread_pool_thread_proxy, pool, g_thread_create (g_thread_pool_thread_proxy, pool, FALSE, &local_error);
pool->stack_size, FALSE,
bound, priority, &local_error);
if (local_error) if (local_error)
{ {
@@ -257,17 +244,10 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
* is called * is called
* @max_threads: the maximal number of threads to execute concurrently in * @max_threads: the maximal number of threads to execute concurrently in
* the new thread pool, -1 means no limit * the new thread pool, -1 means no limit
* @stack_size: the stack size for the threads of the new thread pool,
* 0 means using the standard
* @bound: should the threads of the new thread pool be bound?
* @priority: a priority for the threads of the new thread pool
* @exclusive: should this thread pool be exclusive? * @exclusive: should this thread pool be exclusive?
* @error: return location for error * @error: return location for error
* *
* This function creates a new thread pool. All threads created within * This function creates a new thread pool.
* this thread pool will have the priority @priority and the stack
* size @stack_size and will be bound if and only if @bound is
* true.
* *
* Whenever you call g_thread_pool_push(), either a new thread is * Whenever you call g_thread_pool_push(), either a new thread is
* created or an unused one is reused. At most @max_threads threads * created or an unused one is reused. At most @max_threads threads
@@ -286,12 +266,6 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
* non-exclusive thread pools. This implies that @max_threads may not * non-exclusive thread pools. This implies that @max_threads may not
* be -1 for exclusive thread pools. * be -1 for exclusive thread pools.
* *
* Note, that only threads from a thread pool with a @stack_size of 0
* (which means using the standard stack size) will be globally
* reused. Threads from a thread pool with a non-zero stack size will
* stay only in this thread pool until it is freed and can thus not be
* controlled by the g_thread_pool_set_unused_threads() function.
*
* @error can be NULL to ignore errors, or non-NULL to report * @error can be NULL to ignore errors, or non-NULL to report
* errors. An error can only occur, when @exclusive is set to @TRUE and * errors. An error can only occur, when @exclusive is set to @TRUE and
* not all @max_threads threads could be created. * not all @max_threads threads could be created.
@@ -302,9 +276,6 @@ GThreadPool*
g_thread_pool_new (GFunc func, g_thread_pool_new (GFunc func,
gpointer user_data, gpointer user_data,
gint max_threads, gint max_threads,
gulong stack_size,
gboolean bound,
GThreadPriority priority,
gboolean exclusive, gboolean exclusive,
GError **error) GError **error)
{ {
@@ -320,10 +291,7 @@ g_thread_pool_new (GFunc func,
retval->pool.func = func; retval->pool.func = func;
retval->pool.user_data = user_data; retval->pool.user_data = user_data;
retval->pool.bound = bound;
retval->pool.priority = priority;
retval->pool.exclusive = exclusive; retval->pool.exclusive = exclusive;
retval->stack_size = stack_size;
retval->queue = g_async_queue_new (); retval->queue = g_async_queue_new ();
retval->max_threads = max_threads; retval->max_threads = max_threads;
retval->num_threads = 0; retval->num_threads = 0;
@@ -335,12 +303,7 @@ g_thread_pool_new (GFunc func,
{ {
inform_mutex = g_mutex_new (); inform_mutex = g_mutex_new ();
inform_cond = g_cond_new (); inform_cond = g_cond_new ();
for (priority = G_THREAD_PRIORITY_LOW; unused_thread_queue = g_async_queue_new ();
priority < G_THREAD_PRIORITY_URGENT + 1; priority++)
{
unused_thread_queue[priority][0] = g_async_queue_new ();
unused_thread_queue[priority][1] = g_async_queue_new ();
}
} }
G_UNLOCK (init); G_UNLOCK (init);
@@ -659,37 +622,13 @@ g_thread_pool_set_max_unused_threads (gint max_threads)
if (max_unused_threads < unused_threads && max_unused_threads != -1) if (max_unused_threads < unused_threads && max_unused_threads != -1)
{ {
guint close_down_num = unused_threads - max_unused_threads; guint i;
while (close_down_num > 0) g_async_queue_lock (unused_thread_queue);
{ for (i = unused_threads - max_unused_threads; i > 0; i--)
GThreadPriority priority; g_async_queue_push_unlocked (unused_thread_queue,
guint bound; stop_this_thread_marker);
g_async_queue_unlock (unused_thread_queue);
guint old_close_down_num = close_down_num;
for (priority = G_THREAD_PRIORITY_LOW;
priority < G_THREAD_PRIORITY_URGENT + 1 && close_down_num > 0;
priority++)
{
for (bound = 0; bound < 2; bound++)
{
GAsyncQueue *queue = unused_thread_queue[priority][bound];
g_async_queue_lock (queue);
if (g_async_queue_length_unlocked (queue) < 0)
{
g_async_queue_push_unlocked (queue,
stop_this_thread_marker);
close_down_num--;
}
g_async_queue_unlock (queue);
}
}
/* Just to make sure, there are no counting problems */
g_assert (old_close_down_num != close_down_num);
}
} }
G_UNLOCK (unused_threads); G_UNLOCK (unused_threads);

View File

@@ -42,22 +42,17 @@ struct _GThreadPool
{ {
GFunc func; GFunc func;
gpointer user_data; gpointer user_data;
gboolean bound;
GThreadPriority priority;
gboolean exclusive; gboolean exclusive;
}; };
/* Get a thread pool with the function func, at most max_threads may /* Get a thread pool with the function func, at most max_threads may
* run at a time (max_threads == -1 means no limit), stack_size, bound, * run at a time (max_threads == -1 means no limit), exclusive == TRUE
* priority like in g_thread_create, exclusive == TRUE means, that the threads * means, that the threads shouldn't be shared and that they will be
* shouldn't be shared and that they will be prestarted (otherwise they are * prestarted (otherwise they are started as needed) user_data is the
* started as needed) user_data is the 2nd argument to the func */ * 2nd argument to the func */
GThreadPool* g_thread_pool_new (GFunc func, GThreadPool* g_thread_pool_new (GFunc func,
gpointer user_data, gpointer user_data,
gint max_threads, gint max_threads,
gulong stack_size,
gboolean bound,
GThreadPriority priority,
gboolean exclusive, gboolean exclusive,
GError **error); GError **error);

View File

@@ -267,8 +267,7 @@ create_adder_thread (void)
sub_channels[0] = in_channels[0]; sub_channels[0] = in_channels[0];
sub_channels[1] = out_channels[1]; sub_channels[1] = out_channels[1];
g_thread_create (adder_thread, sub_channels, 0, g_thread_create (adder_thread, sub_channels, FALSE, &err);
FALSE, TRUE, G_THREAD_PRIORITY_NORMAL, &err);
if (err) if (err)
{ {

View File

@@ -27,9 +27,8 @@ test_g_mutex (void)
g_assert (g_mutex_trylock (test_g_mutex_mutex)); g_assert (g_mutex_trylock (test_g_mutex_mutex));
g_assert (G_TRYLOCK (test_g_mutex)); g_assert (G_TRYLOCK (test_g_mutex));
thread = g_thread_create (test_g_mutex_thread, thread = g_thread_create (test_g_mutex_thread, GINT_TO_POINTER (42),
GINT_TO_POINTER (42), TRUE, NULL);
0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL);
g_usleep (G_USEC_PER_SEC); g_usleep (G_USEC_PER_SEC);
test_g_mutex_int = 42; test_g_mutex_int = 42;
G_UNLOCK (test_g_mutex); G_UNLOCK (test_g_mutex);
@@ -68,8 +67,7 @@ test_g_static_rec_mutex (void)
g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)); g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
thread = g_thread_create (test_g_static_rec_mutex_thread, thread = g_thread_create (test_g_static_rec_mutex_thread,
GINT_TO_POINTER (42), GINT_TO_POINTER (42), TRUE, NULL);
0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL);
g_usleep (G_USEC_PER_SEC); g_usleep (G_USEC_PER_SEC);
g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)); g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
g_usleep (G_USEC_PER_SEC); g_usleep (G_USEC_PER_SEC);
@@ -180,9 +178,7 @@ test_g_static_private (void)
for (i = 0; i < THREADS; i++) for (i = 0; i < THREADS; i++)
{ {
threads[i] = g_thread_create (test_g_static_private_thread, threads[i] = g_thread_create (test_g_static_private_thread,
GINT_TO_POINTER (i), GINT_TO_POINTER (i), TRUE, NULL);
0, TRUE, TRUE,
G_THREAD_PRIORITY_NORMAL, NULL);
} }
/* Busy wait is not nice but that's just a test */ /* Busy wait is not nice but that's just a test */
@@ -269,8 +265,7 @@ test_g_static_rw_lock ()
for (i = 0; i < THREADS; i++) for (i = 0; i < THREADS; i++)
{ {
threads[i] = g_thread_create (test_g_static_rw_lock_thread, threads[i] = g_thread_create (test_g_static_rw_lock_thread,
0, 0, TRUE, TRUE, NULL, TRUE, NULL);
G_THREAD_PRIORITY_NORMAL, NULL);
} }
g_usleep (G_USEC_PER_SEC); g_usleep (G_USEC_PER_SEC);
test_g_static_rw_lock_run = FALSE; test_g_static_rw_lock_run = FALSE;

View File

@@ -32,12 +32,9 @@ main (int argc,
guint i; guint i;
g_thread_init (NULL); g_thread_init (NULL);
pool1 = g_thread_pool_new (thread_pool_func, 3, 0, FALSE, pool1 = g_thread_pool_new (thread_pool_func, NULL, 3, FALSE, NULL);
G_THREAD_PRIORITY_NORMAL, FALSE, NULL, NULL); pool2 = g_thread_pool_new (thread_pool_func, NULL, 5, TRUE, NULL);
pool2 = g_thread_pool_new (thread_pool_func, 5, 0, FALSE, pool3 = g_thread_pool_new (thread_pool_func, NULL, 7, TRUE, 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, NULL);
for (i = 0; i < RUNS; i++) for (i = 0; i < RUNS; i++)
{ {