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 -- [email protected]
To unsubscribe send an email to [email protected]