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

Reply via email to