diff options
author | ivan <ivan@13f79535-47bb-0310-9956-ffa450edef68> | 2019-05-19 17:23:14 +0000 |
---|---|---|
committer | ivan <ivan@13f79535-47bb-0310-9956-ffa450edef68> | 2019-05-19 17:23:14 +0000 |
commit | 437b16abfd8da06b85ca4b02213cc975a578c75d (patch) | |
tree | 4b4ca5431b3b66b50679dcaa07dc1142c0c571e9 | |
parent | c02ab86e6d82f9759a5ab1dcf0729414d39f5bcc (diff) | |
download | libapr-437b16abfd8da06b85ca4b02213cc975a578c75d.tar.gz |
Use native one-time initialization [1] to implement apr_thread_once_t on
Windows.
This also fixes problem that apr_thread_once() may return before the other
read completes initialization on Windows.
[1] https://docs.microsoft.com/en-gb/windows/desktop/Sync/one-time-initialization
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@1859517 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | include/arch/win32/apr_arch_threadproc.h | 2 | ||||
-rw-r--r-- | threadproc/win32/thread.c | 28 |
3 files changed, 28 insertions, 5 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes for APR 2.0.0 + *) apr_thread_once: Fix problem that apr_thread_once can return before + the other thread completes initialization on Windows. + *) Windows platform: Remove support for Windows 2000, XP, Vista. The minimum supported OS versions are now Windows 7 / Windows Server 2008 R2. diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h index d3ce9c518..9aee660fd 100644 --- a/include/arch/win32/apr_arch_threadproc.h +++ b/include/arch/win32/apr_arch_threadproc.h @@ -65,7 +65,7 @@ struct apr_procattr_t { }; struct apr_thread_once_t { - long value; + INIT_ONCE once; }; extern apr_status_t apr_threadproc_init(apr_pool_t *pool); diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index c713e1444..3204a1c2c 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -257,19 +257,39 @@ APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control_p, apr_pool_t *p) { - (*control) = apr_pcalloc(p, sizeof(**control)); + apr_thread_once_t *control = apr_pcalloc(p, sizeof(*control)); + + InitOnceInitialize(&control->once); + + *control_p = control; + return APR_SUCCESS; } +static BOOL WINAPI init_once_callback(PINIT_ONCE InitOnce, + PVOID Parameter, + PVOID *Context) +{ + void (*func)(void) = Parameter; + + func(); + + return TRUE; +} + APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, void (*func)(void)) { - if (!InterlockedExchange(&control->value, 1)) { - func(); + PVOID lpContext; + + if (!InitOnceExecuteOnce(&control->once, init_once_callback, func, + &lpContext)) { + return apr_get_os_error(); } + return APR_SUCCESS; } |