blob: 29c54128917b5a95771f7ec1e2003e3695b7dc8c [file] [log] [blame]
/*
* 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 <config.h>
#include "axutil_thread_unix.h"
AXIS2_EXTERN axutil_threadattr_t *AXIS2_CALL
axutil_threadattr_create(
axutil_allocator_t * allocator)
{
int stat = 0;
axutil_threadattr_t *new = NULL;
new = AXIS2_MALLOC(allocator, sizeof(axutil_threadattr_t));
if(!new)
return NULL;
stat = pthread_attr_init(&(new->attr));
if(stat != 0)
{
AXIS2_FREE(allocator, new);
return NULL;
}
return new;
}
/* Destroy the threadattr object */
AXIS2_EXTERN axis2_status_t AXIS2_CALL
threadattr_cleanup(
void *data)
{
axutil_threadattr_t *attr = data;
int rv;
rv = pthread_attr_destroy(&(attr->attr));
if(0 != rv)
{
return AXIS2_FAILURE;
}
return AXIS2_SUCCESS;
}
#define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_threadattr_detach_set(
axutil_threadattr_t * attr,
axis2_bool_t detached)
{
if(0 == pthread_attr_setdetachstate(&(attr->attr), DETACH_ARG(detached)))
{
return AXIS2_SUCCESS;
}
return AXIS2_FAILURE;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_threadattr_detach_get(
axutil_threadattr_t * attr)
{
int state = 0;
pthread_attr_getdetachstate(&(attr->attr), &state);
if(state == 1)
{
return AXIS2_TRUE;
}
return AXIS2_FALSE;
}
static void *
dummy_worker(
void *opaque)
{
axutil_thread_t *thread = (axutil_thread_t *)opaque;
return thread->func(thread, thread->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)
{
axis2_status_t stat;
pthread_attr_t *temp = NULL;
axutil_thread_t *new = NULL;
new = (axutil_thread_t *)AXIS2_MALLOC(allocator, sizeof(axutil_thread_t));
if(!new)
return NULL;
new->td = (pthread_t *)AXIS2_MALLOC(allocator, sizeof(pthread_t));
if(!new->td)
{
AXIS2_FREE(allocator, new);
return NULL;
}
new->data = data;
new->func = func;
new->try_exit = AXIS2_FALSE;
if(attr)
temp = &(attr->attr);
if((stat = pthread_create(new->td, temp, dummy_worker, new)) == 0)
{
return new;
}
AXIS2_FREE(allocator, new->td);
AXIS2_FREE(allocator, new);
return NULL;
}
AXIS2_EXTERN axis2_os_thread_t AXIS2_CALL
axis2_os_thread_current(
void)
{
return pthread_self();
}
AXIS2_EXTERN int AXIS2_CALL
axis2_os_thread_equal(
axis2_os_thread_t tid1,
axis2_os_thread_t tid2)
{
return pthread_equal(tid1, tid2);
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_exit(
axutil_thread_t * thd,
axutil_allocator_t * allocator)
{
axis2_bool_t same_thread = AXIS2_TRUE;
if(thd)
{
while(!thd->try_exit)
{
sleep(1);
}
if(thd->td)
{
same_thread = pthread_equal(pthread_self(), *thd->td);
if(!same_thread)
{
pthread_kill(*(thd->td), 0);
axutil_thread_join(thd);
}
AXIS2_FREE(allocator, thd->td);
}
AXIS2_FREE(allocator, thd);
}
if(same_thread)
{
pthread_exit(NULL);
}
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_join(
axutil_thread_t * thd)
{
void *thread_stat;
if(0 == pthread_join(*(thd->td), (void *)(&thread_stat)))
{
return AXIS2_SUCCESS;
}
return AXIS2_FAILURE;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_detach(
axutil_thread_t * thd)
{
if(0 == pthread_detach(*(thd->td)))
{
thd->try_exit = AXIS2_TRUE;
return AXIS2_SUCCESS;
}
return AXIS2_FAILURE;
}
void
axutil_thread_yield(
void)
{
return;
}
/**
* 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)
{
int rc = -1;
pthread_key_t key = axis2_key->key;
rc = pthread_key_create(&key, NULL);
if(0 == rc)
return AXIS2_SUCCESS;
else
return AXIS2_FAILURE;
}
/**
* 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;
pthread_key_t key = axis2_key->key;
value = pthread_getspecific(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)
{
int rc = -1;
pthread_key_t key = axis2_key->key;
rc = pthread_setspecific(key, value);
if(0 == rc)
return AXIS2_SUCCESS;
else
return AXIS2_FAILURE;
}
AXIS2_EXTERN void AXIS2_CALL
axutil_thread_key_free(
axutil_threadkey_t * axis2_key)
{
pthread_key_t key = axis2_key->key;
pthread_key_delete(key);
}
AXIS2_EXTERN axis2_os_thread_t *AXIS2_CALL
axis2_os_thread_get(
axutil_thread_t * thd)
{
if(!thd)
{
return NULL;
}
return thd->td;
}
AXIS2_EXTERN axutil_thread_once_t *AXIS2_CALL
axutil_thread_once_init(
axutil_allocator_t * allocator)
{
#if defined(AXIS2_SOLARIS) && (__GNUC__ <= 3)
static const pthread_once_t once_init =
{ PTHREAD_ONCE_INIT};
#else
static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
#endif
axutil_thread_once_t *control = AXIS2_MALLOC(allocator, sizeof(axutil_thread_once_t));
if(!control)
{
return NULL;
}
(control)->once = once_init;
return control;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_once(
axutil_thread_once_t * control,
void
(*func)(
void))
{
return pthread_once(&(control->once), func);
}
/*************************Thread locking functions*****************************/
AXIS2_EXTERN axutil_thread_mutex_t *AXIS2_CALL
axutil_thread_mutex_create(
axutil_allocator_t * allocator,
unsigned int flags)
{
axutil_thread_mutex_t *new_mutex = NULL;
new_mutex = AXIS2_MALLOC(allocator, sizeof(axutil_thread_mutex_t));
new_mutex->allocator = allocator;
if(pthread_mutex_init(&(new_mutex->mutex), NULL) != 0)
{
AXIS2_FREE(allocator, new_mutex);
return NULL;
}
return new_mutex;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_lock(
axutil_thread_mutex_t * mutex)
{
return pthread_mutex_lock(&(mutex->mutex));
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_unlock(
axutil_thread_mutex_t * mutex)
{
if(pthread_mutex_unlock(&(mutex->mutex)) != 0)
{
return AXIS2_FAILURE;
}
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_destroy(
axutil_thread_mutex_t * mutex)
{
if(0 != pthread_mutex_destroy(&(mutex->mutex)))
{
return AXIS2_FAILURE;
}
AXIS2_FREE(mutex->allocator, mutex);
return AXIS2_SUCCESS;
}