summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--include/arch/win32/apr_arch_threadproc.h6
-rw-r--r--misc/win32/start.c58
-rw-r--r--threadproc/win32/threadpriv.c17
4 files changed, 83 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 97c46345a..e957ac4b4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,9 @@
Changes for APR 1.3.0
+ *) Implement apr_threadkey_private destructors on WIN32
+ instead silently ignoring them, so that they behave like on
+ the pthreads powered platforms. [Mladen Turk]
+
*) Support MinGW. [John Vandenberg, Justin Erenkrantz]
*) Implement apr_thread_yield on Unix in terms of pthread_yield or
diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h
index 7af8ab686..d4d70d5c9 100644
--- a/include/arch/win32/apr_arch_threadproc.h
+++ b/include/arch/win32/apr_arch_threadproc.h
@@ -17,6 +17,7 @@
#include "apr_private.h"
#include "apr_thread_proc.h"
#include "apr_file_io.h"
+#include "apr_hash.h"
#ifndef THREAD_PROC_H
#define THREAD_PROC_H
@@ -68,5 +69,10 @@ struct apr_thread_once_t {
long value;
};
+#if defined(APR_DECLARE_EXPORT)
+/* Provide to win32/start.c */
+extern apr_hash_t *apr_tls_threadkeys;
+#endif
+
#endif /* ! THREAD_PROC_H */
diff --git a/misc/win32/start.c b/misc/win32/start.c
index e15bf5d83..cab9da55e 100644
--- a/misc/win32/start.c
+++ b/misc/win32/start.c
@@ -18,11 +18,13 @@
#include "apr_general.h"
#include "apr_pools.h"
#include "apr_signal.h"
+#include "apr_hash.h"
#include "ShellAPI.h"
#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */
#include "wchar.h"
#include "apr_arch_file_io.h"
+#include "apr_arch_threadproc.h"
#include "assert.h"
/* This symbol is _private_, although it must be exported.
@@ -187,6 +189,11 @@ APR_DECLARE(apr_status_t) apr_initialize(void)
apr_pool_tag(pool, "apr_initialize");
+#if defined(APR_DECLARE_EXPORT)
+ /* Initialize threadpriv table */
+ apr_tls_threadkeys = apr_hash_make(pool);
+#endif
+
iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
err = WSAStartup((WORD) iVersionRequested, &wsaData);
if (err) {
@@ -203,12 +210,63 @@ APR_DECLARE(apr_status_t) apr_initialize(void)
return APR_SUCCESS;
}
+#if defined(APR_DECLARE_EXPORT)
+typedef (apr_thredkey_destfn_t)(void *data);
+
+static void threadkey_terminate()
+{
+ apr_hash_index_t *hi = apr_hash_first(NULL, apr_tls_threadkeys);
+
+ for (; hi != NULL; hi = apr_hash_next(hi)) {
+ LPDWORD key;
+ apr_hash_this(hi, &key, NULL, NULL);
+ TlsFree(*key);
+ }
+}
+
+static void threadkey_detach()
+{
+ apr_hash_index_t *hi = apr_hash_first(NULL, apr_tls_threadkeys);
+
+ for (; hi != NULL; hi = apr_hash_next(hi)) {
+ apr_thredkey_destfn_t *dest = NULL;
+ LPDWORD key;
+ void *data;
+ apr_hash_this(hi, &key, NULL, (void **)&dest);
+ data = TlsGetValue(*key);
+ (*dest)(data);
+ }
+}
+
+BOOL APIENTRY DllMain(HINSTANCE instance,
+ DWORD reason_for_call,
+ LPVOID lpReserved)
+{
+ switch (reason_for_call) {
+ case DLL_PROCESS_ATTACH:
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ threadkey_detach();
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+#endif /* APR_DECLARE_EXPORT */
+
APR_DECLARE_NONSTD(void) apr_terminate(void)
{
initialized--;
if (initialized) {
return;
}
+#if defined(APR_DECLARE_EXPORT)
+ threadkey_terminate();
+#endif
apr_pool_terminate();
WSACleanup();
diff --git a/threadproc/win32/threadpriv.c b/threadproc/win32/threadpriv.c
index 0cbfe620e..b1001e107 100644
--- a/threadproc/win32/threadpriv.c
+++ b/threadproc/win32/threadpriv.c
@@ -16,11 +16,16 @@
#include "apr_arch_threadproc.h"
#include "apr_thread_proc.h"
+#include "apr_hash.h"
#include "apr_general.h"
#include "apr_lib.h"
#include "apr_errno.h"
#include "apr_portable.h"
+#if defined(APR_DECLARE_EXPORT)
+apr_hash_t *apr_tls_threadkeys = NULL;
+#endif
+
APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
void (*dest)(void *),
apr_pool_t *pool)
@@ -33,6 +38,10 @@ APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
(*key)->pool = pool;
if (((*key)->key = TlsAlloc()) != 0xFFFFFFFF) {
+#if defined(APR_DECLARE_EXPORT)
+ apr_hash_set(apr_tls_threadkeys, &((*key)->key),
+ sizeof(DWORD), dest);
+#endif
return APR_SUCCESS;
}
return apr_get_os_error();
@@ -59,7 +68,11 @@ APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv,
APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key)
{
if (TlsFree(key->key)) {
- return APR_SUCCESS;
+#if defined(APR_DECLARE_EXPORT)
+ apr_hash_set(apr_tls_threadkeys, &(key->key),
+ sizeof(DWORD), NULL);
+#endif
+ return APR_SUCCESS;
}
return apr_get_os_error();
}
@@ -97,5 +110,5 @@ APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key,
}
(*key)->key = *thekey;
return APR_SUCCESS;
-}
+}