/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed 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 "axis2_thread_unix.h"


AXIS2_DECLARE(axis2_threadattr_t*)
axis2_threadattr_create(axis2_allocator_t* allocator)
{
    int stat = 0;
	axis2_threadattr_t *new = NULL;

    new = AXIS2_MALLOC(allocator, sizeof(axis2_threadattr_t));
	if(NULL == 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_DECLARE(axis2_status_t)
threadattr_cleanup(void *data)
{
    axis2_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_DECLARE(axis2_status_t) 
axis2_threadattr_detach_set(axis2_threadattr_t *attr, axis2_bool_t detached)
{
    if (0 == pthread_attr_setdetachstate(&attr->attr, DETACH_ARG(detached)))
	{
        return AXIS2_SUCCESS;
    }
	return AXIS2_FAILURE;
}

AXIS2_DECLARE(axis2_status_t)
axis2_threadattr_detach_get(axis2_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)
{
    axis2_thread_t *thread = (axis2_thread_t*)opaque;
    return thread->func(thread, thread->data);
}

AXIS2_DECLARE(axis2_thread_t*)
axis2_thread_create(axis2_allocator_t* allocator, axis2_threadattr_t *attr,
						axis2_thread_start_t func, void *data)
{
    axis2_status_t stat;
    pthread_attr_t *temp = NULL;
	axis2_thread_t *new = NULL;

    new = (axis2_thread_t *)AXIS2_MALLOC(allocator, sizeof(axis2_thread_t));

    if (NULL == new) 
	{
        return NULL;
    }
    new->td = (pthread_t *)AXIS2_MALLOC(allocator, sizeof(pthread_t));
    if (NULL == new->td) 
	{
        return NULL;
    }

    new->data = data;
    new->func = func;

    if (NULL != attr)
	{
        temp = &attr->attr;
	}
    else
	{
        temp = NULL;
	}

    if ((stat = pthread_create(new->td, temp, dummy_worker, new)) == 0) 
	{
        return new;
    }
    return NULL;
}

AXIS2_DECLARE(axis2_os_thread_t)
axis2_os_thread_current(void)
{
    return pthread_self();
}

AXIS2_DECLARE(int)
axis2_os_thread_equal(axis2_os_thread_t tid1, axis2_os_thread_t tid2)
{
    return pthread_equal(tid1, tid2);
}

AXIS2_DECLARE(axis2_status_t)
axis2_thread_exit(axis2_thread_t *thd)
{
    pthread_exit(NULL);
    return AXIS2_SUCCESS;
}

AXIS2_DECLARE(axis2_status_t)
axis2_thread_join(axis2_thread_t *thd)
{
    void *thread_stat;
    if (0 == pthread_join(*thd->td,(void *)&thread_stat)) 
	{
        return AXIS2_SUCCESS;
    }
 	return AXIS2_FAILURE;
}

AXIS2_DECLARE(axis2_status_t)
axis2_thread_detach(axis2_thread_t *thd)
{
    if (0 == pthread_detach(*(thd->td)))
	{
        return AXIS2_SUCCESS;
    }
    return AXIS2_FAILURE;
}

void axis2_thread_yield(void)
{
	return;
}

AXIS2_DECLARE(axis2_os_thread_t*)
axis2_os_thread_get(axis2_thread_t *thd)
{
	if(NULL == thd)
	{
		return NULL;
	}
	return thd->td;
}

AXIS2_DECLARE(axis2_thread_once_t*)
axis2_thread_once_init(axis2_allocator_t* allocator)
{
    static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
    axis2_thread_once_t *control = AXIS2_MALLOC(allocator, 
						sizeof(axis2_thread_once_t));
	if(NULL == control)
	{
		return NULL;;
	}
    (control)->once = once_init;
    return control;
}

AXIS2_DECLARE(axis2_status_t)
axis2_thread_once(axis2_thread_once_t *control, void (*func)(void))
{
    return pthread_once(&control->once, func);
}

/*************************Thread locking functions*****************************/
AXIS2_DECLARE(axis2_thread_mutex_t *)
axis2_thread_mutex_create(axis2_allocator_t *allocator, unsigned int flags)
{
    axis2_thread_mutex_t *new_mutex = NULL;
		
    new_mutex = AXIS2_MALLOC(allocator, sizeof(axis2_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_DECLARE(axis2_status_t) 
axis2_thread_mutex_lock(axis2_thread_mutex_t *mutex)
{
	return pthread_mutex_lock(&mutex->mutex);
}

AXIS2_DECLARE(axis2_status_t) 
axis2_thread_mutex_unlock(axis2_thread_mutex_t *mutex)
{
    if(pthread_mutex_unlock(&mutex->mutex) != 0)
	{
		return AXIS2_FAILURE;
	}
	return AXIS2_SUCCESS;
}

AXIS2_DECLARE(axis2_status_t) 
axis2_thread_mutex_destroy(axis2_thread_mutex_t *mutex)
{
	if(0 != pthread_mutex_destroy(&mutex->mutex))
	{
		return AXIS2_FAILURE;
	}
    AXIS2_FREE(mutex->allocator, mutex);
	return AXIS2_SUCCESS;
}
