[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
A thread object -- GtkThread
- From: Gustavo Joćo Alves Marques Carneiro <ee96090 fe up pt>
- To: gtk-app-devel-list redhat com
- Subject: A thread object -- GtkThread
- Date: Wed, 16 Feb 2000 18:04:00 +0000 (WET)
I've been working on a wraper to threads as a GTK object, using the
wonderful gob. The file is in attachment. If anyone would like to use it,
go ahead.
How it works:
- a GtkThread object is created -- it manages a single thread;
- signal handlers for termination and cancelation of the thread
can be connected;
- gtk_thread_launch (function, arg) creates the thread and
returns;
- a timeout function is registered, which monitors the thread for
completion;
- when the thread terminates, it is joined, the object emits a
signal and the function removes itself;
The question is: is there a better way to do this? Specifically, I
don't know of any function from the pthread library to check if a thread
has terminated -- I'm using a flag and the timeout function. I don't like
this very much, but it's the best I could do.
Any ideas, sugestions, bugs, etc.?
PS: If anyone is interested in a wraper to GSList, I have one.
--
Gustavo J.A.M. Carneiro [reinolinux.fe.up.pt/~ee96090]
/* -*- Mode: C; c-file-style: "bsd"; coding: latin-1-unix -*- */
%h{
#include <pthread.h>
typedef void * (*GtkThreadRoutine)(void *);
extern int gtk_thread_disable_threads;
%}
%{
typedef void * (*ThreadFunction)(void *);
typedef void (*ThreadCleanUpFunc)(void *);
int gtk_thread_disable_threads=0;
%}
class Gtk:Thread from Gtk:Object
{
protected pthread_t thread;
protected gboolean running;
protected gboolean busy;
protected guint timeout_handler_id;
public void *return_value;
public gint check_interval;
protected GtkThreadRoutine routine;
protected void * arg;
init(self) {
self->running = FALSE;
self->busy = FALSE;
self->check_interval = 10;
}
public GtkObject * new(void) {
return GTK_OBJECT(GET_NEW);
}
signal private NONE (POINTER) void finished(self, void *ret_val);
signal private NONE (NONE) void canceled(self);
public gboolean launch(self, GtkThreadRoutine routine, void * ARG) {
gint err;
if(self->busy)
return FALSE;
self->busy = TRUE;
self->routine = routine;
self->arg = ARG;
self->running = TRUE;
if(gtk_thread_disable_threads)
{
void *ret;
ret = routine(ARG);
self->running = FALSE;
finished(self, ret);
self->busy = FALSE;
return TRUE;
}
err = pthread_create(&self->thread, NULL, (ThreadFunction)marshaller, self);
if(err) g_warning("pthread_create failed!");
self->timeout_handler_id = gtk_timeout_add(self->check_interval,
(GtkFunction)check_thread_termination,
self);
return TRUE;
}
/* This function runs periodically in gtk's main loop with a
timeout. It monitors the completion of a thread. When
completed, it pthread_join's the thread and emits a gtk
signal. The function then returns FALSE to stop itself from
being called anymore. */
private gint check_thread_termination (void *foo) {
GtkThread *self;
gdk_threads_enter();
self = GTK_THREAD(foo);
if (self->running) {
gdk_threads_leave();
return TRUE;
}
if(pthread_join(self->thread, &self->return_value))
g_warning("pthread_join failed!");
self->busy = FALSE;
finished(self, self->return_value);
gdk_threads_leave();
return FALSE;
}
/* This function calls the user routine, but first it installs a
cleanup handler which changes the flag self->running to
FALSE. The function 'check_thread_termination', that runs in the
main thread as a timeout function, monitors that flag. */
private void * marshaller (void *foo) {
GtkThread *self;
void *ret_val;
self = (GtkThread*)foo;
printf(__FUNCTION__"\n");
if(!self) return NULL;
pthread_cleanup_push((ThreadCleanUpFunc)thread_cleanup, self);
ret_val = self->routine(self->arg);
pthread_cleanup_pop(TRUE);
return ret_val;
}
private void thread_cleanup (void *arg) {
GtkThread *self;
g_return_if_fail(arg);
self = (GtkThread *)arg;
self->running = FALSE;
}
/* Before destroying the object, cancel it. */
override (Gtk:Object) void destroy(Gtk:Object *object) {
GtkThread *self;
self = GTK_THREAD(object);
cancel (self);
PARENT_HANDLER(object);
}
/* Send a cancelation request to the thread, then join it, in case
it is running. */
public void cancel (self) {
if(self->busy) {
pthread_cancel(self->thread);
pthread_join(self->thread, NULL);
gtk_timeout_remove (self->timeout_handler_id);
self->busy = FALSE;
canceled(self);
}
}
}
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]