You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by yl...@apache.org on 2022/01/19 14:15:50 UTC

svn commit: r1897207 - in /apr/apr/trunk: include/apr_thread_proc.h threadproc/beos/thread.c threadproc/netware/thread.c threadproc/os2/thread.c threadproc/unix/thread.c threadproc/win32/thread.c

Author: ylavic
Date: Wed Jan 19 14:15:49 2022
New Revision: 1897207

URL: http://svn.apache.org/viewvc?rev=1897207&view=rev
Log:
apr_thread: Use compiler's TLS to track the current apr_thread_t's pointer.

All modern compilers provide a Thread Local Storage keyword that allows to
store per-thread data efficiently (C++11 's thread_local, C11's _Thread_local,
gcc/clang's __thread or MSVC's __declspec(thread)).

Use that to have an apr_thread_t pointer associated with each thread created
by apr_thread_create() or any native thread (like the process' initial thread)
that registered itself with the new apr_thread_current_create() function.

This mechanism allows to implement apr_thread_current() quite efficiently, if
available, otherwise the function returns NULL.

If available APR_HAS_THREAD_LOCAL is #define'd to 1 and the APR_THREAD_LOCAL
macro is the keyword usable to register TLS variables natively.
Both APR_HAS_THREAD_LOCAL and APR_THREAD_LOCAL are #undef'ined if the compiler
does not provide the mechanism.
This allows to test for the functionality at compile time.

When APR_HAS_THREAD_LOCAL, the user can load his/her own TLS data with:
    apr_thread_data_get(&my_data, my_key, apr_thread_current());

and store them with:
    apr_thread_data_set(my_data, my_key, my_data_cleanup,
                        apr_thread_current());

which can be nice to avoid the proliferation of native TLS keys.


Modified:
    apr/apr/trunk/include/apr_thread_proc.h
    apr/apr/trunk/threadproc/beos/thread.c
    apr/apr/trunk/threadproc/netware/thread.c
    apr/apr/trunk/threadproc/os2/thread.c
    apr/apr/trunk/threadproc/unix/thread.c
    apr/apr/trunk/threadproc/win32/thread.c

Modified: apr/apr/trunk/include/apr_thread_proc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_thread_proc.h?rev=1897207&r1=1897206&r2=1897207&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_thread_proc.h (original)
+++ apr/apr/trunk/include/apr_thread_proc.h Wed Jan 19 14:15:49 2022
@@ -209,9 +209,28 @@ typedef enum {
 
 /* Thread Function definitions */
 
+#undef APR_HAS_THREAD_LOCAL
+
 #if APR_HAS_THREADS
 
 /**
+ * APR_THREAD_LOCAL keyword mapping the compiler's.
+ */
+#if defined(__cplusplus) && __cplusplus >= 201103L
+#define APR_THREAD_LOCAL thread_local
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112
+#define APR_THREAD_LOCAL _Thread_local
+#elif defined(__GNUC__) /* works for clang too */
+#define APR_THREAD_LOCAL __thread
+#elif defined(WIN32) && defined(_MSC_VER)
+#define APR_THREAD_LOCAL __declspec(thread)
+#endif
+
+#ifdef APR_THREAD_LOCAL
+#define APR_HAS_THREAD_LOCAL 1
+#endif
+
+/**
  * Create and initialize a new threadattr variable
  * @param new_attr The newly created threadattr.
  * @param cont The pool to use
@@ -270,6 +289,24 @@ APR_DECLARE(apr_status_t) apr_thread_cre
                                             void *data, apr_pool_t *cont);
 
 /**
+ * Setup the current os_thread as an apr_thread
+ * @param current The current apr_thread set up (or reused)
+ * @param attr The threadattr associated with the current thread
+ * @param pool The parent pool of the current thread
+ * @return APR_SUCCESS, APR_EEXIST if the current thread is already set,
+ *         any error otherwise
+ */
+APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
+                                                    apr_threadattr_t *attr,
+                                                    apr_pool_t *pool);
+/**
+ * Get the current thread
+ * @param The current apr_thread, NULL if it is not an apr_thread or if
+ *        it could not be determined.
+ */
+APR_DECLARE(apr_thread_t *) apr_thread_current(void);
+
+/**
  * Stop the current thread
  * @param thd The thread to stop
  * @param retval The return value to pass back to any thread that cares

Modified: apr/apr/trunk/threadproc/beos/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/beos/thread.c?rev=1897207&r1=1897206&r2=1897207&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/beos/thread.c (original)
+++ apr/apr/trunk/threadproc/beos/thread.c Wed Jan 19 14:15:49 2022
@@ -62,32 +62,44 @@ APR_DECLARE(apr_status_t) apr_threadattr
     return APR_ENOTIMPL;
 }
 
+#ifdef APR_HAS_THREAD_LOCAL
+static APR_THREAD_LOCAL apr_thread_t *current_thread;
+#endif
+
 static void *dummy_worker(void *opaque)
 {
     apr_thread_t *thd = (apr_thread_t*)opaque;
     void *ret;
 
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = thd;
+#endif
+
     apr_pool_owner_set(thd->pool, 0);
     ret = thd->func(thd, thd->data);
     if (thd->detached) {
         apr_pool_destroy(thd->pool);
     }
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     return ret;
 }
 
-APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr,
-                                            apr_thread_start_t func, void *data,
-                                            apr_pool_t *pool)
+static apr_status_t alloc_thread(apr_thread_t **new,
+                                 apr_threadattr_t *attr,
+                                 apr_thread_start_t func, void *data,
+                                 apr_pool_t *pool)
 {
-    int32 temp;
     apr_status_t stat;
     apr_allocator_t *allocator;
     apr_pool_t *p;
-    
+
     /* The thread can be detached anytime (from the creation or later with
      * apr_thread_detach), so it needs its own pool and allocator to not
      * depend on a parent pool which could be destroyed before the thread
-     * exits. The allocator needs no mutex obviously since the pool should 
+     * exits. The allocator needs no mutex obviously since the pool should
      * not be used nor create children pools outside the thread.
      */
     stat = apr_allocator_create(&allocator);
@@ -114,6 +126,22 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     (*new)->exitval = -1;
     (*new)->detached = (attr && apr_threadattr_detach_get(attr) == APR_DETACH);
 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func, void *data,
+                                            apr_pool_t *pool)
+{
+    int32 temp;
+    apr_status_t stat;
+
+    stat = alloc_thread(new, attr, func, data, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
     if (attr)
         temp = attr->attr;
     else
@@ -126,13 +154,46 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     /* Now we try to run it...*/
     if (resume_thread((*new)->td) != B_NO_ERROR) {
         stat = errno;
-        apr_pool_destroy(p);
+        apr_pool_destroy((*new)->pool);
         return stat;
     }
 
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
+                                                    apr_threadattr_t *attr,
+                                                    apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    *current = apr_thread_current();
+    if (*current) {
+        return APR_EEXIST;
+    }
+
+    stat = alloc_thread(current, attr, NULL, NULL, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
+    (*current)->td = apr_os_thread_current();
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = *current;
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_thread_t *) apr_thread_current(void)
+{
+#ifdef APR_HAS_THREAD_LOCAL
+    return current_thread;
+#else
+    return NULL;
+#endif
+}
+
 APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
 {
     return find_thread(NULL);
@@ -149,6 +210,9 @@ APR_DECLARE(void) apr_thread_exit(apr_th
     if (thd->detached) {
         apr_pool_destroy(thd->pool);
     }
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     exit_thread ((status_t)(retval));
 }
 
@@ -197,6 +261,10 @@ void apr_thread_yield()
 
 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        *data = NULL;
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_get(data, key, thread->pool);
 }
 
@@ -204,6 +272,9 @@ APR_DECLARE(apr_status_t) apr_thread_dat
                                               apr_status_t (*cleanup) (void *),
                                               apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
 }
 

Modified: apr/apr/trunk/threadproc/netware/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/netware/thread.c?rev=1897207&r1=1897206&r2=1897207&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/netware/thread.c (original)
+++ apr/apr/trunk/threadproc/netware/thread.c Wed Jan 19 14:15:49 2022
@@ -64,35 +64,44 @@ APR_DECLARE(apr_status_t) apr_threadattr
     return APR_ENOTIMPL;
 }
 
+#ifdef APR_HAS_THREAD_LOCAL
+static APR_THREAD_LOCAL apr_thread_t *current_thread;
+#endif
+
 static void *dummy_worker(void *opaque)
 {
     apr_thread_t *thd = (apr_thread_t *)opaque;
     void *ret;
 
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = thd;
+#endif
+
     apr_pool_owner_set(thd->pool, 0);
     ret = thd->func(thd, thd->data);
     if (thd->detached) {
         apr_pool_destroy(thd->pool);
     }
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     return ret;
 }
 
-apr_status_t apr_thread_create(apr_thread_t **new,
-                                            apr_threadattr_t *attr, 
-                                            apr_thread_start_t func,
-                                            void *data,
-                                            apr_pool_t *pool)
+static apr_status_t alloc_thread(apr_thread_t **new,
+                                 apr_threadattr_t *attr,
+                                 apr_thread_start_t func, void *data,
+                                 apr_pool_t *pool)
 {
     apr_status_t stat;
-    unsigned long flags = NX_THR_BIND_CONTEXT;
-    size_t stack_size = APR_DEFAULT_STACK_SIZE;
     apr_allocator_t *allocator;
     apr_pool_t *p;
-    
+
     /* The thread can be detached anytime (from the creation or later with
      * apr_thread_detach), so it needs its own pool and allocator to not
      * depend on a parent pool which could be destroyed before the thread
-     * exits. The allocator needs no mutex obviously since the pool should 
+     * exits. The allocator needs no mutex obviously since the pool should
      * not be used nor create children pools outside the thread.
      */
     stat = apr_allocator_create(&allocator);
@@ -131,6 +140,24 @@ apr_status_t apr_thread_create(apr_threa
         return APR_ENOMEM;
     }
 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func,
+                                            void *data,
+                                            apr_pool_t *pool)
+{
+    apr_status_t stat;
+    unsigned long flags = NX_THR_BIND_CONTEXT;
+    size_t stack_size = APR_DEFAULT_STACK_SIZE;
+
+    stat = alloc_thread(new, attr, func, data, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
     /* An original stack size of 0 will allow NXCreateThread() to
     *   assign a default system stack size.  An original stack
     *   size of less than 0 will assign the APR default stack size.
@@ -139,11 +166,11 @@ apr_status_t apr_thread_create(apr_threa
     if (attr && (attr->stack_size >= 0)) {
         stack_size = attr->stack_size;
     }
-    
+
     if (attr && attr->detach) {
         flags |= NX_THR_DETACHED;
     }
-    
+
     (*new)->ctx = NXContextAlloc(
         /* void(*start_routine)(void *arg) */ (void (*)(void *)) dummy_worker,
         /* void *arg */                       (*new),
@@ -151,7 +178,7 @@ apr_status_t apr_thread_create(apr_threa
         /* size_t stackSize */                stack_size,
         /* unsigned long flags */             NX_CTX_NORMAL,
         /* int *error */                      &stat);
-                                                                           
+
     (void) NXContextSetName(
         /* NXContext_t ctx */  (*new)->ctx,
         /* const char *name */ (*new)->thread_name);
@@ -162,13 +189,46 @@ apr_status_t apr_thread_create(apr_threa
         /* NXThreadId_t *thread_id */ &(*new)->td);
 
     if (stat) {
-        apr_pool_destroy(p);
+        apr_pool_destroy((*new)->pool);
+        return stat;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
+                                                    apr_threadattr_t *attr,
+                                                    apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    *current = apr_thread_current();
+    if (*current) {
+        return APR_EEXIST;
+    }
+
+    stat = alloc_thread(current, attr, NULL, NULL, pool);
+    if (stat != APR_SUCCESS) {
         return stat;
     }
-        
+
+    (*current)->td = apr_os_thread_current();
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = *current;
+#endif
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_thread_t *) apr_thread_current(void)
+{
+#ifdef APR_HAS_THREAD_LOCAL
+    return current_thread;
+#else
+    return NULL;
+#endif
+}
+
 apr_os_thread_t apr_os_thread_current()
 {
     return NXThreadGetId();
@@ -190,6 +250,9 @@ void apr_thread_exit(apr_thread_t *thd,
     if (thd->detached) {
         apr_pool_destroy(thd->pool);
     }
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     NXThreadExit(NULL);
 }
 
@@ -227,26 +290,21 @@ apr_status_t apr_thread_detach(apr_threa
 apr_status_t apr_thread_data_get(void **data, const char *key,
                                              apr_thread_t *thread)
 {
-    if (thread != NULL) {
-            return apr_pool_userdata_get(data, key, thread->pool);
-    }
-    else {
-        data = NULL;
+    if (thread == NULL) {
+        *data = NULL;
         return APR_ENOTHREAD;
     }
+    return apr_pool_userdata_get(data, key, thread->pool);
 }
 
 apr_status_t apr_thread_data_set(void *data, const char *key,
                               apr_status_t (*cleanup) (void *),
                               apr_thread_t *thread)
 {
-    if (thread != NULL) {
-       return apr_pool_userdata_set(data, key, cleanup, thread->pool);
-    }
-    else {
-        data = NULL;
+    if (thread == NULL) {
         return APR_ENOTHREAD;
     }
+    return apr_pool_userdata_set(data, key, cleanup, thread->pool);
 }
 
 APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,

Modified: apr/apr/trunk/threadproc/os2/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/os2/thread.c?rev=1897207&r1=1897206&r2=1897207&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/os2/thread.c (original)
+++ apr/apr/trunk/threadproc/os2/thread.c Wed Jan 19 14:15:49 2022
@@ -68,30 +68,43 @@ APR_DECLARE(apr_status_t) apr_threadattr
     return APR_ENOTIMPL;
 }
 
+#ifdef APR_HAS_THREAD_LOCAL
+static APR_THREAD_LOCAL apr_thread_t *current_thread;
+#endif
+
 static void dummy_worker(void *opaque)
 {
+#ifdef APR_HAS_THREAD_LOCAL
+  current_thread = thread;
+#endif
+
   apr_thread_t *thread = (apr_thread_t *)opaque;
   apr_pool_owner_set(thread->pool, 0);
   thread->exitval = thread->func(thread, thread->data);
   if (thd->attr->attr & APR_THREADATTR_DETACHED) {
       apr_pool_destroy(thread->pool);
   }
+
+#ifdef APR_HAS_THREAD_LOCAL
+  current_thread = NULL;
+#endif
 }
 
 
 
-APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, 
-                                            apr_thread_start_t func, void *data, 
-                                            apr_pool_t *pool)
+static apr_status_t alloc_thread(apr_thread_t **new,
+                                 apr_threadattr_t *attr,
+                                 apr_thread_start_t func, void *data,
+                                 apr_pool_t *pool)
 {
     apr_status_t stat;
     apr_allocator_t *allocator;
     apr_pool_t *p;
-    
+
     /* The thread can be detached anytime (from the creation or later with
      * apr_thread_detach), so it needs its own pool and allocator to not
      * depend on a parent pool which could be destroyed before the thread
-     * exits. The allocator needs no mutex obviously since the pool should 
+     * exits. The allocator needs no mutex obviously since the pool should
      * not be used nor create children pools outside the thread.
      */
     stat = apr_allocator_create(&allocator);
@@ -124,19 +137,66 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     }
     (*new)->attr = attr;
 
-    (*new)->tid = _beginthread(dummy_worker, NULL, 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func, void *data,
+                                            apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    stat = alloc_thread(new, attr, func, data, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
+    (*new)->tid = _beginthread(dummy_worker, NULL,
                                (*new)->attr->stacksize > 0 ?
                                (*new)->attr->stacksize : APR_THREAD_STACKSIZE,
                                (*new));
     if ((*new)->tid < 0) {
         stat = errno;
-        apr_pool_destroy(p);
+        apr_pool_destroy((*new)->pool);
         return stat;
     }
 
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
+                                                    apr_threadattr_t *attr,
+                                                    apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    *current = apr_thread_current();
+    if (*current) {
+        return APR_EEXIST;
+    }
+
+    stat = alloc_thread(new, attr, NULL, NULL, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
+    (*current)->tid = apr_os_thread_current();
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = *current;
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_thread_t *) apr_thread_current(void)
+{
+#ifdef APR_HAS_THREAD_LOCAL
+    return current_thread;
+#else
+    return NULL;
+#endif
+}
 
 
 APR_DECLARE(apr_os_thread_t) apr_os_thread_current()
@@ -155,6 +215,9 @@ APR_DECLARE(void) apr_thread_exit(apr_th
     if (thd->attr->attr & APR_THREADATTR_DETACHED) {
         apr_pool_destroy(thd->pool);
     }
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     _endthread();
 }
 
@@ -232,6 +295,10 @@ int apr_os_thread_equal(apr_os_thread_t
 
 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        *data = NULL;
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_get(data, key, thread->pool);
 }
 
@@ -241,6 +308,9 @@ APR_DECLARE(apr_status_t) apr_thread_dat
                                               apr_status_t (*cleanup) (void *),
                                               apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
 }
 

Modified: apr/apr/trunk/threadproc/unix/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/unix/thread.c?rev=1897207&r1=1897206&r2=1897207&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/unix/thread.c (original)
+++ apr/apr/trunk/threadproc/unix/thread.c Wed Jan 19 14:15:49 2022
@@ -136,34 +136,44 @@ APR_DECLARE(apr_status_t) apr_threadattr
 #endif
 }
 
+#ifdef APR_HAS_THREAD_LOCAL
+static APR_THREAD_LOCAL apr_thread_t *current_thread;
+#endif
+
 static void *dummy_worker(void *opaque)
 {
     apr_thread_t *thread = (apr_thread_t*)opaque;
     void *ret;
 
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = thread;
+#endif
+
     apr_pool_owner_set(thread->pool, 0);
     ret = thread->func(thread, thread->data);
     if (thread->detached) {
         apr_pool_destroy(thread->pool);
     }
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     return ret;
 }
 
-APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
-                                            apr_threadattr_t *attr,
-                                            apr_thread_start_t func,
-                                            void *data,
-                                            apr_pool_t *pool)
+static apr_status_t alloc_thread(apr_thread_t **new,
+                                 apr_threadattr_t *attr,
+                                 apr_thread_start_t func, void *data,
+                                 apr_pool_t *pool)
 {
     apr_status_t stat;
-    pthread_attr_t *temp;
     apr_allocator_t *allocator;
     apr_pool_t *p;
-    
+
     /* The thread can be detached anytime (from the creation or later with
      * apr_thread_detach), so it needs its own pool and allocator to not
      * depend on a parent pool which could be destroyed before the thread
-     * exits. The allocator needs no mutex obviously since the pool should 
+     * exits. The allocator needs no mutex obviously since the pool should
      * not be used nor create children pools outside the thread.
      */
     stat = apr_allocator_create(&allocator);
@@ -194,6 +204,23 @@ APR_DECLARE(apr_status_t) apr_thread_cre
         return APR_ENOMEM;
     }
 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func,
+                                            void *data,
+                                            apr_pool_t *pool)
+{
+    apr_status_t stat;
+    pthread_attr_t *temp;
+
+    stat = alloc_thread(new, attr, func, data, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
     if (attr)
         temp = &attr->attr;
     else
@@ -203,13 +230,46 @@ APR_DECLARE(apr_status_t) apr_thread_cre
 #ifdef HAVE_ZOS_PTHREADS
         stat = errno;
 #endif
-        apr_pool_destroy(p);
+        apr_pool_destroy((*new)->pool);
+        return stat;
+    }
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
+                                                    apr_threadattr_t *attr,
+                                                    apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    *current = apr_thread_current();
+    if (*current) {
+        return APR_EEXIST;
+    }
+
+    stat = alloc_thread(current, attr, NULL, NULL, pool);
+    if (stat != APR_SUCCESS) {
         return stat;
     }
 
+    *(*current)->td = apr_os_thread_current();
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = *current;
+#endif
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_thread_t *) apr_thread_current(void)
+{
+#ifdef APR_HAS_THREAD_LOCAL
+    return current_thread;
+#else
+    return NULL;
+#endif
+}
+
 APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
 {
     return pthread_self();
@@ -228,6 +288,9 @@ APR_DECLARE(void) apr_thread_exit(apr_th
     if (thd->detached) {
         apr_pool_destroy(thd->pool);
     }
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     pthread_exit(NULL);
 }
 
@@ -297,6 +360,10 @@ APR_DECLARE(void) apr_thread_yield(void)
 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
                                               apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        *data = NULL;
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_get(data, key, thread->pool);
 }
 
@@ -304,6 +371,9 @@ APR_DECLARE(apr_status_t) apr_thread_dat
                               apr_status_t (*cleanup)(void *),
                               apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
 }
 

Modified: apr/apr/trunk/threadproc/win32/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/win32/thread.c?rev=1897207&r1=1897206&r2=1897207&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/win32/thread.c (original)
+++ apr/apr/trunk/threadproc/win32/thread.c Wed Jan 19 14:15:49 2022
@@ -72,35 +72,45 @@ APR_DECLARE(apr_status_t) apr_threadattr
     return APR_ENOTIMPL;
 }
 
+#ifdef APR_HAS_THREAD_LOCAL
+static APR_THREAD_LOCAL apr_thread_t *current_thread;
+#endif
+
 static void *dummy_worker(void *opaque)
 {
     apr_thread_t *thd = (apr_thread_t *)opaque;
     void *ret;
 
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = thd;
+#endif
+
     TlsSetValue(tls_apr_thread, thd->td);
     apr_pool_owner_set(thd->pool, 0);
     ret = thd->func(thd, thd->data);
     if (!thd->td) { /* detached? */
         apr_pool_destroy(thd->pool);
     }
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     return ret;
 }
 
-APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
-                                            apr_threadattr_t *attr,
-                                            apr_thread_start_t func,
-                                            void *data, apr_pool_t *pool)
+static apr_status_t alloc_thread(apr_thread_t **new,
+                                 apr_threadattr_t *attr,
+                                 apr_thread_start_t func, void *data,
+                                 apr_pool_t *pool)
 {
     apr_status_t stat;
-    unsigned temp;
-    HANDLE handle;
     apr_allocator_t *allocator;
     apr_pool_t *p;
-    
+
     /* The thread can be detached anytime (from the creation or later with
      * apr_thread_detach), so it needs its own pool and allocator to not
      * depend on a parent pool which could be destroyed before the thread
-     * exits. The allocator needs no mutex obviously since the pool should 
+     * exits. The allocator needs no mutex obviously since the pool should
      * not be used nor create children pools outside the thread.
      */
     stat = apr_allocator_create(&allocator);
@@ -125,6 +135,23 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     (*new)->data = data;
     (*new)->func = func;
 
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
+                                            apr_threadattr_t *attr,
+                                            apr_thread_start_t func,
+                                            void *data, apr_pool_t *pool)
+{
+    apr_status_t stat;
+    unsigned temp;
+    HANDLE handle;
+
+    stat = alloc_thread(new, attr, func, data, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
     /* Use 0 for default Thread Stack Size, because that will
      * default the stack to the same size as the calling thread.
      */
@@ -133,9 +160,10 @@ APR_DECLARE(apr_status_t) apr_thread_cre
                         (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker,
                         (*new), 0, &temp)) == 0) {
         stat = APR_FROM_OS_ERROR(_doserrno);
-        apr_pool_destroy(p);
+        apr_pool_destroy((*new)->pool);
         return stat;
     }
+
     if (attr && attr->detach) {
         CloseHandle(handle);
     }
@@ -146,6 +174,41 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
+                                                    apr_threadattr_t *attr,
+                                                    apr_pool_t *pool)
+{
+    apr_status_t stat;
+
+    *current = apr_thread_current();
+    if (*current) {
+        return APR_EEXIST;
+    }
+
+    stat = alloc_thread(current, attr, NULL, NULL, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
+
+    if (!(attr && attr->detach)) {
+        (*new)->td = apr_os_thread_current();
+    }
+
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = *current;
+#endif
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_thread_t *) apr_thread_current(void)
+{
+#ifdef APR_HAS_THREAD_LOCAL
+    return current_thread;
+#else
+    return NULL;
+#endif
+}
+
 APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
 {
     thd->exited = 1;
@@ -153,6 +216,9 @@ APR_DECLARE(void) apr_thread_exit(apr_th
     if (!thd->td) { /* detached? */
         apr_pool_destroy(thd->pool);
     }
+#ifdef APR_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
     _endthreadex(0);
 }
 
@@ -209,6 +275,10 @@ APR_DECLARE(void) apr_thread_yield()
 APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
                                              apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        *data = NULL;
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_get(data, key, thread->pool);
 }
 
@@ -216,6 +286,9 @@ APR_DECLARE(apr_status_t) apr_thread_dat
                                              apr_status_t (*cleanup) (void *),
                                              apr_thread_t *thread)
 {
+    if (thread == NULL) {
+        return APR_ENOTHREAD;
+    }
     return apr_pool_userdata_set(data, key, cleanup, thread->pool);
 }
 



Re: svn commit: r1897207 - in /apr/apr/trunk: include/apr_thread_proc.h threadproc/beos/thread.c threadproc/netware/thread.c threadproc/os2/thread.c threadproc/unix/thread.c threadproc/win32/thread.c

Posted by Yann Ylavic <yl...@gmail.com>.
On Tue, Feb 8, 2022 at 7:56 PM Evgeny Kotkov
<ev...@visualsvn.com> wrote:
>
> Yann Ylavic <yl...@apache.org> writes:
>
> > +APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
> > +                                                    apr_threadattr_t *attr,
> > +                                                    apr_pool_t *pool)
> > +{
> > +    apr_status_t stat;
> > +
> > +    *current = apr_thread_current();
> > +    if (*current) {
> > +        return APR_EEXIST;
> > +    }
> > +
> > +    stat = alloc_thread(current, attr, NULL, NULL, pool);
> > +    if (stat != APR_SUCCESS) {
> > +        return stat;
> > +    }
> > +
> > +    if (!(attr && attr->detach)) {
> > +        (*new)->td = apr_os_thread_current();
> > +    }
>
> Hi Yann,
>
> It looks like this hunk doesn't compile on Windows:
>
>   …\threadproc\win32\thread.c(193): error C2065: 'new': undeclared identifier
>   …\threadproc\win32\thread.c(193): error C2100: illegal indirection
>   …\threadproc\win32\thread.c(193): error C2223: left of '->td' must point
>   to struct/union

Thanks, hopefully fixed in r1897879.


Regards;
Yann.

Re: svn commit: r1897207 - in /apr/apr/trunk: include/apr_thread_proc.h threadproc/beos/thread.c threadproc/netware/thread.c threadproc/os2/thread.c threadproc/unix/thread.c threadproc/win32/thread.c

Posted by Evgeny Kotkov <ev...@visualsvn.com>.
Yann Ylavic <yl...@apache.org> writes:

> +APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current,
> +                                                    apr_threadattr_t *attr,
> +                                                    apr_pool_t *pool)
> +{
> +    apr_status_t stat;
> +
> +    *current = apr_thread_current();
> +    if (*current) {
> +        return APR_EEXIST;
> +    }
> +
> +    stat = alloc_thread(current, attr, NULL, NULL, pool);
> +    if (stat != APR_SUCCESS) {
> +        return stat;
> +    }
> +
> +    if (!(attr && attr->detach)) {
> +        (*new)->td = apr_os_thread_current();
> +    }

Hi Yann,

It looks like this hunk doesn't compile on Windows:

  …\threadproc\win32\thread.c(193): error C2065: 'new': undeclared identifier
  …\threadproc\win32\thread.c(193): error C2100: illegal indirection
  …\threadproc\win32\thread.c(193): error C2223: left of '->td' must point
  to struct/union


Thanks,
Evgeny Kotkov