|
|
|
@ -24,8 +24,10 @@ struct detach_thread { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
mutex_t threads_to_join_lock = MUTEX_STATIC_INIT; |
|
|
|
static GSList *threads_to_join; |
|
|
|
static mutex_t threads_lists_lock = MUTEX_STATIC_INIT; |
|
|
|
static GList *threads_to_join; |
|
|
|
static GList *threads_running; |
|
|
|
static cond_t threads_cond = COND_STATIC_INIT; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -119,31 +121,58 @@ void g_queue_clear(GQueue *q) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void thread_join_me() { |
|
|
|
static void thread_join_me() { |
|
|
|
pthread_t *me; |
|
|
|
|
|
|
|
me = g_slice_alloc(sizeof(*me)); |
|
|
|
*me = pthread_self(); |
|
|
|
mutex_lock(&threads_to_join_lock); |
|
|
|
threads_to_join = g_slist_prepend(threads_to_join, me); |
|
|
|
mutex_unlock(&threads_to_join_lock); |
|
|
|
mutex_lock(&threads_lists_lock); |
|
|
|
threads_to_join = g_list_prepend(threads_to_join, me); |
|
|
|
cond_broadcast(&threads_cond); |
|
|
|
mutex_unlock(&threads_lists_lock); |
|
|
|
} |
|
|
|
|
|
|
|
void threads_join_all() { |
|
|
|
static gint thread_equal(gconstpointer a, gconstpointer b) { |
|
|
|
const pthread_t *x = a, *y = b; |
|
|
|
return !pthread_equal(*x, *y); |
|
|
|
} |
|
|
|
|
|
|
|
void threads_join_all(int wait) { |
|
|
|
pthread_t *t; |
|
|
|
GList *l; |
|
|
|
|
|
|
|
mutex_lock(&threads_lists_lock); |
|
|
|
while (1) { |
|
|
|
while (threads_to_join) { |
|
|
|
t = threads_to_join->data; |
|
|
|
pthread_join(*t, NULL); |
|
|
|
threads_to_join = g_list_delete_link(threads_to_join, threads_to_join); |
|
|
|
l = g_list_find_custom(threads_running, t, thread_equal); |
|
|
|
if (l) |
|
|
|
threads_running = g_list_delete_link(threads_running, l); |
|
|
|
else |
|
|
|
abort(); |
|
|
|
g_slice_free1(sizeof(*t), t); |
|
|
|
} |
|
|
|
|
|
|
|
mutex_lock(&threads_to_join_lock); |
|
|
|
while (threads_to_join) { |
|
|
|
t = threads_to_join->data; |
|
|
|
pthread_join(*t, NULL); |
|
|
|
threads_to_join = g_slist_delete_link(threads_to_join, threads_to_join); |
|
|
|
g_slice_free1(sizeof(*t), t); |
|
|
|
if (!wait) |
|
|
|
break; |
|
|
|
if (!threads_running) |
|
|
|
break; |
|
|
|
cond_wait(&threads_cond, &threads_lists_lock); |
|
|
|
} |
|
|
|
mutex_unlock(&threads_to_join_lock); |
|
|
|
mutex_unlock(&threads_lists_lock); |
|
|
|
} |
|
|
|
|
|
|
|
static gpointer thread_detach_func(gpointer d) { |
|
|
|
static void *thread_detach_func(void *d) { |
|
|
|
struct detach_thread *dt = d; |
|
|
|
pthread_t *t; |
|
|
|
|
|
|
|
t = g_slice_alloc(sizeof(*t)); |
|
|
|
*t = pthread_self(); |
|
|
|
mutex_lock(&threads_lists_lock); |
|
|
|
threads_running = g_list_prepend(threads_running, t); |
|
|
|
mutex_unlock(&threads_lists_lock); |
|
|
|
|
|
|
|
dt->func(dt->data); |
|
|
|
g_slice_free1(sizeof(*dt), dt); |
|
|
|
@ -151,7 +180,7 @@ static gpointer thread_detach_func(gpointer d) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
int thread_create(void *(*func)(void *), void *arg, int joinable, pthread_t *handle) { |
|
|
|
static int thread_create(void *(*func)(void *), void *arg, int joinable, pthread_t *handle) { |
|
|
|
pthread_attr_t att; |
|
|
|
pthread_t thr; |
|
|
|
int ret; |
|
|
|
@ -162,9 +191,12 @@ int thread_create(void *(*func)(void *), void *arg, int joinable, pthread_t *han |
|
|
|
abort(); |
|
|
|
ret = pthread_create(&thr, &att, func, arg); |
|
|
|
pthread_attr_destroy(&att); |
|
|
|
if (!ret && handle) |
|
|
|
if (ret) |
|
|
|
return ret; |
|
|
|
if (handle) |
|
|
|
*handle = thr; |
|
|
|
return ret; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void thread_create_detach(void (*f)(void *), void *d) { |
|
|
|
|