changeset 1887:09860ba329a4

Divided thread initialization and deinitialization into separate exported functions so they can be accessed from language bindings.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Mon, 09 Sep 2013 19:18:36 +0000
parents f7d408a47752
children 0df3fc47002e
files dw.h gtk/dw.c gtk3/dw.c mac/dw.m os2/dw.c os2/dw.def os2/dw.lnk win/dw-mingw.def win/dw.c win/dw.def
diffstat 10 files changed, 221 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/dw.h	Thu Sep 05 17:58:40 2013 +0000
+++ b/dw.h	Mon Sep 09 19:18:36 2013 +0000
@@ -1770,5 +1770,8 @@
 void API dw_print_cancel(HPRINT print);
 wchar_t * API dw_utf8_to_wchar(char *utf8string);
 char * API dw_wchar_to_utf8(wchar_t *wstring);
+/* Exported for language bindings */
+void API _dw_init_thread(void);
+void API _dw_deinit_thread(void);
 
 #endif
--- a/gtk/dw.c	Thu Sep 05 17:58:40 2013 +0000
+++ b/gtk/dw.c	Mon Sep 09 19:18:36 2013 +0000
@@ -1983,15 +1983,6 @@
 }
 #endif
 
-void _init_thread(void)
-{
-   GdkColor *foreground = malloc(sizeof(GdkColor));
-
-   foreground->pixel = foreground->red = foreground->green = foreground->blue = 0;
-   pthread_setspecific(_dw_fg_color_key, foreground);
-   pthread_setspecific(_dw_bg_color_key, NULL);
-}
-
 /* Try to load the mozilla embed shared libary */
 #ifdef USE_GTKMOZEMBED
 #include <ctype.h>
@@ -2177,7 +2168,7 @@
    pthread_key_create(&_dw_bg_color_key, NULL);
    pthread_key_create(&_dw_mutex_key, NULL);
 
-   _init_thread();
+   _dw_init_thread();
 
    gtk_rc_parse_string("style \"gtk-tooltips-style\" { bg[NORMAL] = \"#eeee00\" } widget \"gtk-tooltips\" style \"gtk-tooltips-style\"");
 
@@ -10106,6 +10097,37 @@
    return DW_ERROR_NONE;
 }
 
+/* 
+ * Generally an internal function called from a newly created
+ * thread to setup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they create threads that require access to Dynamic Windows.
+ */
+void API _dw_init_thread(void)
+{
+   GdkColor *foreground = malloc(sizeof(GdkColor));
+
+   foreground->pixel = foreground->red = foreground->green = foreground->blue = 0;
+   pthread_setspecific(_dw_fg_color_key, foreground);
+   pthread_setspecific(_dw_bg_color_key, NULL);
+}
+
+/* 
+ * Generally an internal function called from a terminating
+ * thread to cleanup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they exit threads that require access to Dynamic Windows.
+ */
+void API _dw_deinit_thread(void)
+{
+   GdkColor *foreground, *background;
+   
+   if((foreground = pthread_getspecific(_dw_fg_color_key)))
+      free(foreground);
+   if((background = pthread_getspecific(_dw_bg_color_key)))
+      free(background);
+}
+
 /*
  * Setup thread independent color sets.
  */
@@ -10113,21 +10135,17 @@
 {
    void (*threadfunc)(void *) = NULL;
    void **tmp = (void **)data;
-   GdkColor *foreground, *background;
 
    threadfunc = (void (*)(void *))tmp[0];
 
    /* Initialize colors */
-   _init_thread();
+   _dw_init_thread();
 
    threadfunc(tmp[1]);
    free(tmp);
 
    /* Free colors */
-   if((foreground = pthread_getspecific(_dw_fg_color_key)))
-      free(foreground);
-   if((background = pthread_getspecific(_dw_bg_color_key)))
-      free(background);
+   _dw_deinit_thread();
 }
 
 /*
--- a/gtk3/dw.c	Thu Sep 05 17:58:40 2013 +0000
+++ b/gtk3/dw.c	Mon Sep 09 19:18:36 2013 +0000
@@ -1783,15 +1783,6 @@
    return NULL;
 }
 
-void _init_thread(void)
-{
-   GdkRGBA *foreground = malloc(sizeof(GdkRGBA));
-
-   foreground->alpha = foreground->red = foreground->green = foreground->blue = 0.0;
-   pthread_setspecific(_dw_fg_color_key, foreground);
-   pthread_setspecific(_dw_bg_color_key, NULL);
-}
-
 /* Try to load the WebKitGtk shared libary */
 #ifdef USE_WEBKIT
 void init_webkit(void)
@@ -1879,7 +1870,7 @@
    pthread_key_create(&_dw_bg_color_key, NULL);
    pthread_key_create(&_dw_mutex_key, NULL);
 
-   _init_thread();
+   _dw_init_thread();
 
    /* Create a global object for glib activities */
    _DWObject = g_object_new(G_TYPE_OBJECT, NULL);
@@ -8323,6 +8314,37 @@
    return DW_ERROR_NONE;
 }
 
+/* 
+ * Generally an internal function called from a newly created
+ * thread to setup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they create threads that require access to Dynamic Windows.
+ */
+void API _dw_init_thread(void)
+{
+   GdkRGBA *foreground = malloc(sizeof(GdkRGBA));
+
+   foreground->alpha = foreground->red = foreground->green = foreground->blue = 0.0;
+   pthread_setspecific(_dw_fg_color_key, foreground);
+   pthread_setspecific(_dw_bg_color_key, NULL);
+}
+
+/* 
+ * Generally an internal function called from a terminating
+ * thread to cleanup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they exit threads that require access to Dynamic Windows.
+ */
+void API _dw_deinit_thread(void)
+{
+   GdkRGBA *foreground, *background;
+   
+   if((foreground = pthread_getspecific(_dw_fg_color_key)))
+      free(foreground);
+   if((background = pthread_getspecific(_dw_bg_color_key)))
+      free(background);
+}
+
 /*
  * Setup thread independent color sets.
  */
@@ -8330,21 +8352,17 @@
 {
    void (*threadfunc)(void *) = NULL;
    void **tmp = (void **)data;
-   GdkRGBA *foreground, *background;
 
    threadfunc = (void (*)(void *))tmp[0];
 
    /* Initialize colors */
-   _init_thread();
+   _dw_init_thread();
 
    threadfunc(tmp[1]);
    free(tmp);
 
    /* Free colors */
-   if((foreground = pthread_getspecific(_dw_fg_color_key)))
-      free(foreground);
-   if((background = pthread_getspecific(_dw_bg_color_key)))
-      free(background);
+   _dw_deinit_thread();
 }
 
 /*
--- a/mac/dw.m	Thu Sep 05 17:58:40 2013 +0000
+++ b/mac/dw.m	Mon Sep 09 19:18:36 2013 +0000
@@ -10911,27 +10911,32 @@
 #endif
 }
 
-/*
- * Setup thread independent pools.
- */
-void _dwthreadstart(void *data)
-{
-    void (*threadfunc)(void *) = NULL;
-    void **tmp = (void **)data;
-    NSColor *color;
-
+/* 
+ * Generally an internal function called from a newly created
+ * thread to setup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they create threads that require access to Dynamic Windows.
+ */
+void API _dw_init_thread(void)
+{
     /* If we aren't using garbage collection we need autorelease pools */
 #if !defined(GARBAGE_COLLECT)
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     pthread_setspecific(_dw_pool_key, pool);
 #endif
     _init_colors();
-
-    threadfunc = (void (*)(void *))tmp[0];
-
-    /* Start our thread function */
-    threadfunc(tmp[1]);
-
+}
+
+/* 
+ * Generally an internal function called from a terminating
+ * thread to cleanup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they exit threads that require access to Dynamic Windows.
+ */
+void API _dw_deinit_thread(void)
+{
+    NSColor *color;
+    
     /* Release the pool when we are done so we don't leak */
     color = pthread_getspecific(_dw_fg_color_key);
     [color release];
@@ -10941,7 +10946,26 @@
     pool = pthread_getspecific(_dw_pool_key);
     [pool drain];
 #endif
+}
+
+/*
+ * Setup thread independent pools.
+ */
+void _dwthreadstart(void *data)
+{
+    void (*threadfunc)(void *) = NULL;
+    void **tmp = (void **)data;
+
+    _dw_init_thread();
+    
+    threadfunc = (void (*)(void *))tmp[0];
+
+    /* Start our thread function */
+    threadfunc(tmp[1]);
+
     free(tmp);
+    
+    _dw_deinit_thread();
 }
 
 /*
--- a/os2/dw.c	Thu Sep 05 17:58:40 2013 +0000
+++ b/os2/dw.c	Mon Sep 09 19:18:36 2013 +0000
@@ -11912,28 +11912,66 @@
    return 0;
 }
 
+/* 
+ * Generally an internal function called from a newly created
+ * thread to setup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they create threads that require access to Dynamic Windows.
+ */
+void API _dw_init_thread(void)
+{
+   HAB thishab = WinInitialize(0);
+   HMQ thishmq = WinCreateMsgQueue(thishab, 0);
+   void **threadinfo = (void **)malloc(sizeof(void *) * 2);
+   
+   threadinfo[0] = (void *)thishab;
+   threadinfo[1] = (void *)thishmq;
+   
+   _threadstore() = (void *)threadinfo;
+   
+#ifdef UNICODE
+   /* Set the codepage to 1208 (UTF-8) */
+   WinSetCp(thishmq, 1208);
+#endif
+}
+
+/* 
+ * Generally an internal function called from a terminating
+ * thread to cleanup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they exit threads that require access to Dynamic Windows.
+ */
+void API _dw_deinit_thread(void)
+{
+   void **threadinfo = (void **)_threadstore();
+   
+   if(threadinfo)
+   {
+      HAB thishab = (HAB)threadinfo[0];
+      HMQ thishmq = (HMQ)threadinfo[1];
+      
+      WinDestroyMsgQueue(thishmq);
+      WinTerminate(thishab);
+      free(threadinfo);
+   }
+}
+
 /*
  * Encapsulate the message queues on OS/2.
  */
 void _dwthreadstart(void *data)
 {
-   HAB thishab = WinInitialize(0);
-   HMQ thishmq = WinCreateMsgQueue(thishab, 0);
    void (API_FUNC threadfunc)(void *) = NULL;
    void **tmp = (void **)data;
 
-#ifdef UNICODE
-   /* Set the codepage to 1208 (UTF-8) */
-   WinSetCp(thishmq, 1208);
-#endif
+   _dw_init_thread();
 
    threadfunc = (void (API_FUNC)(void *))tmp[0];
    threadfunc(tmp[1]);
 
    free(tmp);
 
-   WinDestroyMsgQueue(thishmq);
-   WinTerminate(thishab);
+   _dw_deinit_thread();
 }
 
 /*
--- a/os2/dw.def	Thu Sep 05 17:58:40 2013 +0000
+++ b/os2/dw.def	Mon Sep 09 19:18:36 2013 +0000
@@ -24,6 +24,9 @@
   dw_app_dir                             @25
   dw_main_quit                           @26
   dw_shutdown                            @27
+  
+  _dw_init_thread                        @30
+  _dw_deinit_thread                      @31
 
   dw_box_new                             @40
   dw_groupbox_new                        @41
--- a/os2/dw.lnk	Thu Sep 05 17:58:40 2013 +0000
+++ b/os2/dw.lnk	Mon Sep 09 19:18:36 2013 +0000
@@ -19,6 +19,9 @@
 export dw_app_dir.25
 export dw_main_quit.26
 export dw_shutdown.27
+  
+export _dw_init_thread.30
+export _dw_deinit_thread.31
 
 export dw_box_new.40
 export dw_groupbox_new.41
--- a/win/dw-mingw.def	Thu Sep 05 17:58:40 2013 +0000
+++ b/win/dw-mingw.def	Mon Sep 09 19:18:36 2013 +0000
@@ -23,6 +23,9 @@
   dw_app_dir                             @25
   dw_main_quit                           @26
   dw_shutdown                            @27
+  
+  _dw_init_thread                        @30
+  _dw_deinit_thread                      @31
 
   dw_box_new                             @40
   dw_groupbox_new                        @41
--- a/win/dw.c	Thu Sep 05 17:58:40 2013 +0000
+++ b/win/dw.c	Mon Sep 09 19:18:36 2013 +0000
@@ -3761,27 +3761,6 @@
 }
 #endif
 
-/* Initialize thread local values to the defaults */
-void _init_thread(void)
-{
-    COLORREF foreground = RGB(128,128,128);
-    COLORREF background = DW_RGB_TRANSPARENT;
-#ifdef GDIPLUS
-    ARGB gpfore = MAKEARGB(255, 128, 128, 128);
-    GpBrush *brush;
-    GpPen *pen;
-    
-    GdipCreatePen1(gpfore, 1.0, UnitPixel, &pen);
-    TlsSetValue(_gpPen, (LPVOID)pen);
-    GdipCreateSolidFill(gpfore, &brush);
-    TlsSetValue(_gpBrush, brush);
-#endif    
-    TlsSetValue(_foreground, DW_UINT_TO_POINTER(foreground));
-    TlsSetValue(_background, DW_UINT_TO_POINTER(background));
-    TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground));
-    TlsSetValue(_hBrush, CreateSolidBrush(foreground));
-}
-
 /*
  * Initializes the Dynamic Windows engine.
  * Parameters:
@@ -3978,8 +3957,8 @@
    GdiplusStartup(&gdiplusToken, &si, NULL);
 #endif
    
-   /* GDI+ Needs to be initialized before calling _init_thread(); */
-   _init_thread();
+   /* GDI+ Needs to be initialized before calling _dw_init_thread(); */
+   _dw_init_thread();
 
    if((huxtheme = LoadLibrary(TEXT("uxtheme"))))
       _SetWindowTheme = (HRESULT (WINAPI *)(HWND, LPCWSTR, LPCWSTR ))GetProcAddress(huxtheme, "SetWindowTheme");
@@ -11385,13 +11364,40 @@
    return 0;
 }
 
-/*
- * Encapsulate thread creation on Win32.
- */
-void _dwthreadstart(void *data)
-{
-   void (* threadfunc)(void *) = NULL;
-   void **tmp = (void **)data;
+/* 
+ * Generally an internal function called from a newly created
+ * thread to setup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they create threads that require access to Dynamic Windows.
+ */
+void API _dw_init_thread(void)
+{
+    COLORREF foreground = RGB(128,128,128);
+    COLORREF background = DW_RGB_TRANSPARENT;
+#ifdef GDIPLUS
+    ARGB gpfore = MAKEARGB(255, 128, 128, 128);
+    GpBrush *brush;
+    GpPen *pen;
+    
+    GdipCreatePen1(gpfore, 1.0, UnitPixel, &pen);
+    TlsSetValue(_gpPen, (LPVOID)pen);
+    GdipCreateSolidFill(gpfore, &brush);
+    TlsSetValue(_gpBrush, brush);
+#endif    
+    TlsSetValue(_foreground, DW_UINT_TO_POINTER(foreground));
+    TlsSetValue(_background, DW_UINT_TO_POINTER(background));
+    TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground));
+    TlsSetValue(_hBrush, CreateSolidBrush(foreground));
+}
+
+/* 
+ * Generally an internal function called from a terminating
+ * thread to cleanup the Dynamic Windows environment for the thread.
+ * However it is exported so language bindings can call it when
+ * they exit threads that require access to Dynamic Windows.
+ */
+void API _dw_deinit_thread(void)
+{
    HPEN hPen;
    HBRUSH hBrush;
 #ifdef GDIPLUS
@@ -11399,12 +11405,6 @@
    GpPen *pen;
 #endif       
 
-   _init_thread();
-
-   threadfunc = (void (*)(void *))tmp[0];
-   threadfunc(tmp[1]);
-
-   free(tmp);
    if((hPen = TlsGetValue(_hPen)))
        DeleteObject(hPen);
    if((hBrush = TlsGetValue(_hBrush)))
@@ -11418,6 +11418,23 @@
 }
 
 /*
+ * Encapsulate thread creation on Win32.
+ */
+void _dwthreadstart(void *data)
+{
+   void (* threadfunc)(void *) = NULL;
+   void **tmp = (void **)data;
+
+   _dw_init_thread();
+
+   threadfunc = (void (*)(void *))tmp[0];
+   threadfunc(tmp[1]);
+
+   free(tmp);
+   _dw_deinit_thread();
+}
+
+/*
  * Creates a new thread with a starting point of func.
  * Parameters:
  *       func: Function which will be run in the new thread.
--- a/win/dw.def	Thu Sep 05 17:58:40 2013 +0000
+++ b/win/dw.def	Mon Sep 09 19:18:36 2013 +0000
@@ -23,6 +23,9 @@
   dw_app_dir                             @25
   dw_main_quit                           @26
   dw_shutdown                            @27
+  
+  _dw_init_thread                        @30
+  _dw_deinit_thread                      @31
 
   dw_box_new                             @40
   dw_groupbox_new                        @41