aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog7
-rw-r--r--e-util/e-msgport.c111
2 files changed, 56 insertions, 62 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index 3c4ee3133e..ada47cadf3 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -1,3 +1,10 @@
+2001-09-21 <NotZed@Ximian.com>
+
+ * e-msgport.c (e_thread_destroy): Instead of using
+ pthread_cancel() which seems to have numerous implementation
+ issues, send a special quit message to the subordinate thread.
+ (thread_dispatch): When it gets a quit message, well, quit!
+
2001-09-18 Ettore Perazzoli <ettore@ximian.com>
* e-gtk-utils.c (widget_realize_callback_for_backing_store): Use
diff --git a/e-util/e-msgport.c b/e-util/e-msgport.c
index d034f0deaf..aad3648615 100644
--- a/e-util/e-msgport.c
+++ b/e-util/e-msgport.c
@@ -264,6 +264,7 @@ struct _EThread {
};
#define E_THREAD_NONE ((pthread_t)~0)
+#define E_THREAD_QUIT_REPLYPORT ((struct _EMsgPort *)~0)
static void thread_destroy_msg(EThread *e, EMsg *m);
@@ -317,10 +318,10 @@ EThread *e_thread_new(e_thread_t type)
/* close down the threads & resources etc */
void e_thread_destroy(EThread *e)
{
- int tries = 0;
int busy = FALSE;
EMsg *msg;
struct _thread_info *info;
+ GList *l;
/* make sure we soak up all the messages first */
while ( (msg = e_msgport_get(e->server_port)) ) {
@@ -333,52 +334,48 @@ void e_thread_destroy(EThread *e)
case E_THREAD_QUEUE:
case E_THREAD_DROP:
/* if we have a thread, 'kill' it */
- while (e->id != E_THREAD_NONE && tries < 500) {
- if (e->waiting > 0) {
- pthread_t id = e->id;
- e->id = E_THREAD_NONE;
- pthread_mutex_unlock(&e->mutex);
- if (pthread_cancel(id) == 0)
- pthread_join(id, 0);
- pthread_mutex_lock(&e->mutex);
- } else {
- (printf("thread still active, waiting for it to finish\n"));
- pthread_mutex_unlock(&e->mutex);
- sleep(1);
- pthread_mutex_lock(&e->mutex);
- }
- tries++;
+ if (e->id != E_THREAD_NONE) {
+ pthread_t id = e->id;
+
+ t(printf("Sending thread '%d' quit message\n", id));
+
+ e->id = E_THREAD_NONE;
+
+ msg = g_malloc0(sizeof(*msg));
+ msg->reply_port = E_THREAD_QUIT_REPLYPORT;
+ e_msgport_put(e->server_port, msg);
+
+ pthread_mutex_unlock(&e->mutex);
+ t(printf("Joining thread '%d'\n", id));
+ pthread_join(id, 0);
+ t(printf("Joined thread '%d'!\n", id));
+ pthread_mutex_lock(&e->mutex);
}
busy = e->id != E_THREAD_NONE;
break;
case E_THREAD_NEW:
- while (e->id_list && tries < 500) {
- info = e->id_list->data;
- if (!info->busy) {
- e->id_list = g_list_remove(e->id_list, info);
- printf("cleaning up pool thread %ld\n", info->id);
- pthread_mutex_unlock(&e->mutex);
- if (pthread_cancel(info->id) == 0)
- pthread_join(info->id, 0);
- pthread_mutex_lock(&e->mutex);
- printf("cleaned up ok\n");
- g_free(info);
- } else {
- (printf("thread(s) still active, waiting for it to finish\n"));
- tries++;
- pthread_mutex_unlock(&e->mutex);
- sleep(1);
- pthread_mutex_lock(&e->mutex);
- }
+ /* first, send everyone a quit message */
+ l = e->id_list;
+ while (l) {
+ info = l->data;
+ t(printf("Sending thread '%d' quit message\n", info->id));
+ msg = g_malloc0(sizeof(*msg));
+ msg->reply_port = E_THREAD_QUIT_REPLYPORT;
+ e_msgport_put(e->server_port, msg);
+ l = l->next;
}
-#if 0
- while (g_list_length(e->id_list) && tries < 5) {
- (printf("thread(s) still active, waiting for them to finish\n"));
+
+ /* then, wait for everyone to quit */
+ while (e->id_list) {
+ info = e->id_list->data;
+ e->id_list = g_list_remove(e->id_list, info);
pthread_mutex_unlock(&e->mutex);
- sleep(1);
+ t(printf("Joining thread '%d'\n", info->id));
+ pthread_join(info->id, 0);
+ t(printf("Joined thread '%d'!\n", info->id));
pthread_mutex_lock(&e->mutex);
+ g_free(info);
}
-#endif
busy = g_list_length(e->id_list) != 0;
break;
}
@@ -492,6 +489,7 @@ thread_dispatch(void *din)
EThread *e = din;
EMsg *m;
struct _thread_info *info;
+ pthread_t self = pthread_self();
t(printf("dispatch thread started: %ld\n", pthread_self()));
@@ -506,7 +504,7 @@ thread_dispatch(void *din)
case E_THREAD_NEW:
case E_THREAD_QUEUE:
case E_THREAD_DROP:
- info = thread_find(e, pthread_self());
+ info = thread_find(e, self);
if (info)
info->busy = FALSE;
e->waiting++;
@@ -525,8 +523,17 @@ thread_dispatch(void *din)
}
continue;
+ } else if (m->reply_port == E_THREAD_QUIT_REPLYPORT) {
+ t(printf("Thread %d got quit message\n", self));
+ /* Handle a quit message, say we're quitting, free the message, and break out of the loop */
+ info = thread_find(e, self);
+ if (info)
+ info->busy = 2;
+ pthread_mutex_unlock(&e->mutex);
+ g_free(m);
+ break;
} else {
- info = thread_find(e, pthread_self());
+ info = thread_find(e, self);
if (info)
info->busy = TRUE;
}
@@ -545,27 +552,7 @@ thread_dispatch(void *din)
}
}
- /* if we run out of things to process we could conceivably 'hang around' for a bit,
- but to do this we need to use the fd interface of the msgport, and its utility
- is probably debatable anyway */
-
-#if 0
- /* signify we are no longer running */
- /* This code isn't used yet, but would be if we ever had a 'quit now' message implemented */
- pthread_mutex_lock(&e->mutex);
- switch (e->type) {
- case E_THREAD_QUEUE:
- case E_THREAD_DROP:
- e->id = E_THREAD_NONE;
- break;
- case E_THREAD_NEW:
- e->id_list = g_list_remove(e->id_list, (void *)pthread_self());
- break;
- }
- pthread_mutex_unlock(&e->mutex);
-#endif
-
- return 0;
+ return NULL;
}
/* send a message to the thread, start thread if necessary */