From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- util/src/platforms/windows/thread_windows.c | 326 ++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 util/src/platforms/windows/thread_windows.c (limited to 'util/src/platforms/windows/thread_windows.c') diff --git a/util/src/platforms/windows/thread_windows.c b/util/src/platforms/windows/thread_windows.c new file mode 100644 index 0000000..67af332 --- /dev/null +++ b/util/src/platforms/windows/thread_windows.c @@ -0,0 +1,326 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +DWORD tls_axutil_thread = 0; + +AXIS2_EXTERN axutil_threadattr_t *AXIS2_CALL +axutil_threadattr_create( + axutil_allocator_t * allocator) +{ + axutil_threadattr_t *new = NULL; + + new = AXIS2_MALLOC(allocator, sizeof(axutil_threadattr_t)); + if(!new) + { + /*AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE) */ + return NULL; + } + new->detach = 0; + new->stacksize = 0; + + return new; +} + +/* Destroy the threadattr object */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +threadattr_cleanup( + void *data) +{ + /*axutil_threadattr_t *attr = data;*/ + /*nothing to clean up */ + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_threadattr_detach_set( + axutil_threadattr_t * attr, + axis2_bool_t detached) +{ + attr->detach = detached; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_threadattr_detach_get( + axutil_threadattr_t * attr, + const axutil_env_t * env) +{ + if(1 == attr->detach) + { + return AXIS2_TRUE; + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_threadattr_stacksize_set( + axutil_threadattr_t * attr, + size_t stacksize) +{ + attr->stacksize = stacksize; + return AXIS2_SUCCESS; +} + +static void * +dummy_worker( + void *opaque) +{ + axutil_thread_t *thd = (axutil_thread_t *)opaque; + TlsSetValue(tls_axutil_thread, thd->td); + return thd->func(thd, thd->data); +} + +AXIS2_EXTERN axutil_thread_t *AXIS2_CALL +axutil_thread_create( + axutil_allocator_t * allocator, + axutil_threadattr_t * attr, + axutil_thread_start_t func, + void *data) +{ + HANDLE handle; + unsigned long temp; + axutil_thread_t *new = NULL; + + new = (axutil_thread_t *)AXIS2_MALLOC(allocator, sizeof(axutil_thread_t)); + + if(!new) + { + return NULL; + } + + new->data = data; + new->func = func; + new->td = NULL; + new->try_exit = AXIS2_FALSE; + + /* Use 0 for Thread Stack Size, because that will default the stack to the + * same size as the calling thread. + */ + if((handle = + CreateThread(NULL, attr && + attr->stacksize > 0 ? attr->stacksize : 0, + (unsigned long (AXIS2_THREAD_FUNC *) (void *)) + dummy_worker, new, 0, &temp)) == 0) + { + return NULL; + } + + if(attr && attr->detach) + { + CloseHandle(handle); + } + else + new->td = handle; + + return new; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_exit( + axutil_thread_t * thd, + axutil_allocator_t * allocator) +{ + axis2_status_t status = AXIS2_SUCCESS; + + if(thd) + { + if(thd->td && (axis2_os_thread_current() != thd->td)) + { + TerminateThread(thd->td, 0); + axutil_thread_join(thd); + AXIS2_FREE(allocator, thd); + return status; + } + AXIS2_FREE(allocator, thd); + } + if(status) + { + ExitThread(0); + } + + return status; +} + +AXIS2_EXTERN axis2_os_thread_t AXIS2_CALL +axis2_os_thread_current( + void) +{ + HANDLE hthread = (HANDLE)TlsGetValue(tls_axutil_thread); + HANDLE hproc; + + if(hthread) + { + return hthread; + } + + hproc = GetCurrentProcess(); + hthread = GetCurrentThread(); + if(!DuplicateHandle(hproc, hthread, hproc, &hthread, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + return NULL; + } + TlsSetValue(tls_axutil_thread, hthread); + return hthread; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_os_thread_equal( + axis2_os_thread_t tid1, + axis2_os_thread_t tid2) +{ + return (tid1 == tid2); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_join( + axutil_thread_t * thd) +{ + axis2_status_t rv = AXIS2_SUCCESS, rv1; + + if(!thd->td) + { + /* Can not join on detached threads */ + return AXIS2_FAILURE; + } + rv1 = WaitForSingleObject(thd->td, INFINITE); + if(rv1 == WAIT_OBJECT_0 || rv1 == WAIT_ABANDONED) + { + /*rv = AXIS2_INCOMPLETE; */ + } + else + rv = AXIS2_FAILURE; + CloseHandle(thd->td); + thd->td = NULL; + + return rv; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_detach( + axutil_thread_t * thd) +{ + if(thd->td && CloseHandle(thd->td)) + { + thd->td = NULL; + return AXIS2_SUCCESS; + } + else + { + return AXIS2_FAILURE; + } +} + +AXIS2_EXTERN axis2_os_thread_t AXIS2_CALL +axis2_os_thread_get( + axutil_thread_t * thd, + const axutil_env_t * env) +{ + return thd->td; +} + +/** + * function is used to allocate a new key. This key now becomes valid for all threads in our process. + * When a key is created, the value it points to defaults to NULL. Later on each thread may change + * its copy of the value as it wishes. + */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_key_create( + axutil_threadkey_t * axis2_key) +{ + DWORD tls_key = axis2_key->key; + if ((tls_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) + { + return AXIS2_FAILURE; + } + else + { + return AXIS2_SUCCESS; + } +} + +/** + * This function is used to get the value of a given key + * @return void*. A key's value is simply a void pointer (void*) + */ +AXIS2_EXTERN void *AXIS2_CALL +axutil_thread_getspecific( + axutil_threadkey_t * axis2_key) +{ + void *value = NULL; + DWORD tls_key = axis2_key->key; + value = TlsGetValue(tls_key); + return value; +} + +/** + * This function is used to get the value of a given key + * @param keys value. A key's value is simply a void pointer (void*), so we can + * store in it anything that we want + */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_setspecific( + axutil_threadkey_t * axis2_key, + void *value) +{ + DWORD tls_key = axis2_key->key; + if(!TlsSetValue(tls_key, value)) + { + return AXIS2_FAILURE; + } + else + { + return AXIS2_SUCCESS; + } +} + +AXIS2_EXTERN void AXIS2_CALL +axutil_thread_key_free( + axutil_threadkey_t * axis2_key) +{ + DWORD tls_key = axis2_key->key; + TlsFree(tls_key); +} + +AXIS2_EXTERN axutil_thread_once_t *AXIS2_CALL +axutil_thread_once_init( + axutil_allocator_t * allocator) +{ + axutil_thread_once_t *control = NULL; + control = AXIS2_MALLOC(allocator, sizeof(*control)); + if(control) + { + control->value = 0; + } + return control; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axutil_thread_once( + axutil_thread_once_t * control, + void + (*func)( + void)) +{ + if(!InterlockedExchange(&control->value, 1)) + { + func(); + } + return AXIS2_SUCCESS; +} -- cgit v1.1-32-gdbae