Changeset: 5dd2fb712612 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/5dd2fb712612 Modified Files: clients/Tests/exports.stable.out gdk/gdk_system.c gdk/gdk_system.h Branch: geos-reentrant Log Message:
New function MT_thread_init_add_callback to register callbacks. The callbacks are called at thread creation and destruction by the thread itself. diffs (148 lines): diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -385,6 +385,7 @@ const char *MT_thread_getalgorithm(void) void *MT_thread_getdata(void); const char *MT_thread_getname(void); bool MT_thread_init(void); +gdk_return MT_thread_init_add_callback(void (*init)(void *), void (*destroy)(void *), void *data); bool MT_thread_register(void); void MT_thread_set_qry_ctx(QryCtx *ctx); void MT_thread_setalgorithm(const char *algo); diff --git a/gdk/gdk_system.c b/gdk/gdk_system.c --- a/gdk/gdk_system.c +++ b/gdk/gdk_system.c @@ -184,10 +184,18 @@ GDKlockstatistics(int what) #endif /* LOCK_STATS */ +struct thread_funcs { + void (*init)(void *); + void (*destroy)(void *); + void *data; +}; + static struct mtthread { struct mtthread *next; void (*func) (void *); /* function to be called */ void *data; /* and its data */ + struct thread_funcs *thread_funcs; /* callback funcs */ + int nthread_funcs; MT_Lock *lockwait; /* lock we're waiting for */ MT_Sema *semawait; /* semaphore we're waiting for */ MT_Cond *condwait; /* condition variable we're waiting for */ @@ -686,6 +694,36 @@ MT_thread_override_limits(void) return self && self->limit_override; } +static struct thread_init_cb { + struct thread_init_cb *next; + void (*init)(void *); + void (*destroy)(void *); + void *data; +} *init_cb; +static MT_Lock thread_init_lock = MT_LOCK_INITIALIZER(thread_init_lock); + +gdk_return +MT_thread_init_add_callback(void (*init)(void *), void (*destroy)(void *), void *data) +{ + struct thread_init_cb *p = GDKmalloc(sizeof(struct thread_init_cb)); + + if (p == NULL) + return GDK_FAIL; + *p = (struct thread_init_cb) { + .init = init, + .destroy = destroy, + .next = NULL, + .data = data, + }; + MT_lock_set(&thread_init_lock); + struct thread_init_cb **pp = &init_cb; + while (*pp) + pp = &(*pp)->next; + *pp = p; + MT_lock_unset(&thread_init_lock); + return GDK_SUCCEED; +} + #ifdef HAVE_PTHREAD_H static void * #else @@ -719,7 +757,16 @@ thread_starter(void *arg) self->data = NULL; self->sp = THRsp(); thread_setself(self); + for (int i = 0; i < self->nthread_funcs; i++) { + if (self->thread_funcs[i].init) + (*self->thread_funcs[i].init)(self->thread_funcs[i].data); + } (*self->func)(data); + for (int i = 0; i < self->nthread_funcs; i++) { + if (self->thread_funcs[i].destroy) + (*self->thread_funcs[i].destroy)(self->thread_funcs[i].data); + } + free(self->thread_funcs); ATOMIC_SET(&self->exited, 1); TRC_DEBUG(THRD, "Exit thread \"%s\"\n", self->threadname); return 0; /* NULL for pthreads, 0 for Windows */ @@ -843,6 +890,33 @@ MT_create_thread(MT_Id *t, void (*f) (vo .refs = 1, .tid = mtid, }; + MT_lock_set(&thread_init_lock); + /* remember the list of callback functions we need to call for + * this thread (i.e. anything registered so far) */ + for (struct thread_init_cb *p = init_cb; p; p = p->next) + self->nthread_funcs++; + if (self->nthread_funcs > 0) { + self->thread_funcs = malloc(self->nthread_funcs * sizeof(*self->thread_funcs)); + if (self->thread_funcs == NULL) { + GDKsyserror("Cannot allocate memory\n"); + MT_lock_unset(&thread_init_lock); + free(self); +#ifdef HAVE_PTHREAD_H + pthread_attr_destroy(&attr); +#endif + return -1; + } + int n = 0; + for (struct thread_init_cb *p = init_cb; p; p = p->next) { + self->thread_funcs[n++] = (struct thread_funcs) { + .init = p->init, + .destroy = p->destroy, + .data = p->data, + }; + } + } + MT_lock_unset(&thread_init_lock); + ATOMIC_INIT(&self->exited, 0); strcpy_len(self->threadname, threadname, sizeof(self->threadname)); char *p; @@ -869,6 +943,7 @@ MT_create_thread(MT_Id *t, void (*f) (vo #endif if (ret != 0) { GDKsyserr(ret, "Cannot start thread"); + free(self->thread_funcs); free(self); return -1; } @@ -877,6 +952,7 @@ MT_create_thread(MT_Id *t, void (*f) (vo 0, &self->wtid); if (self->hdl == NULL) { GDKwinerror("Failed to create thread"); + free(self->thread_funcs); free(self); return -1; } diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h --- a/gdk/gdk_system.h +++ b/gdk/gdk_system.h @@ -198,6 +198,7 @@ gdk_export bool MT_thread_init(void); gdk_export int MT_create_thread(MT_Id *t, void (*function) (void *), void *arg, enum MT_thr_detach d, const char *threadname); +gdk_export gdk_return MT_thread_init_add_callback(void (*init)(void *), void (*destroy)(void *), void *data); gdk_export bool MT_thread_register(void); gdk_export void MT_thread_deregister(void); gdk_export const char *MT_thread_getname(void); _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org