diff options
| author | ylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68> | 2022-01-19 14:15:49 +0000 |
|---|---|---|
| committer | ylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68> | 2022-01-19 14:15:49 +0000 |
| commit | 82c5bb14c6723c97b7a0ad3335e67be0e4571e52 (patch) | |
| tree | 652d76b9f45f71eef7e07f311304755e1ffd4858 /threadproc/beos/thread.c | |
| parent | fdf36c29c4a3ac0f7c7433635ec52c4397ca814c (diff) | |
| download | libapr-82c5bb14c6723c97b7a0ad3335e67be0e4571e52.tar.gz | |
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.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897207 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'threadproc/beos/thread.c')
| -rw-r--r-- | threadproc/beos/thread.c | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 988f8f4ff..6a3e05806 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -62,32 +62,44 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, 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_create(apr_thread_t **new, apr_threadattr_t (*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_create(apr_thread_t **new, apr_threadattr_t /* 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_thread_t *thd, apr_status_t retval) 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_data_set(void *data, const char *key, 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); } |
