
/*
 * 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 <axutil_thread.h>
#include <platforms/windows/axutil_thread_mutex_windows.h>

static axis2_status_t
thread_mutex_cleanup(
    void *data)
{
    axutil_thread_mutex_t *lock = NULL;
    axutil_allocator_t *allocator = NULL;
    if (!data)
        return AXIS2_FAILURE;

    lock = (axutil_thread_mutex_t *) data;
    allocator = lock->allocator;

    if (lock->type == thread_mutex_critical_section)
    {
        DeleteCriticalSection(&lock->section);
    }
    else
    {
        if (!CloseHandle(lock->handle))
        {
            return AXIS2_FAILURE;
        }
    }

    AXIS2_FREE(allocator, lock);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axutil_thread_mutex_t *AXIS2_CALL
axutil_thread_mutex_create(
    axutil_allocator_t * allocator,
    unsigned int flags)
{
    axutil_thread_mutex_t *mutex = NULL;

    mutex =
        (axutil_thread_mutex_t *) AXIS2_MALLOC(allocator,
                                               sizeof(axutil_thread_mutex_t));
    mutex->allocator = allocator;

    if (flags == AXIS2_THREAD_MUTEX_DEFAULT)    /*unnested */
    {
        /* Use an auto-reset signaled event, ready to accept one
         * waiting thread.
         */
        mutex->type = thread_mutex_unnested_event;
        mutex->handle = CreateEvent(NULL, FALSE, TRUE, NULL);
    }
    else
    {
        /* TODO :support critical_section and nested_mutex */
    }

    return mutex;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_lock(
    axutil_thread_mutex_t * mutex)
{
    if (mutex->type == thread_mutex_critical_section)
    {
        EnterCriticalSection(&mutex->section);
    }
    else
    {
        DWORD rv = WaitForSingleObject(mutex->handle, INFINITE);
        if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED))
        {
            return AXIS2_FAILURE;
            /*can be either BUSY or an os specific error */
        }
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_trylock(
    axutil_thread_mutex_t * mutex)
{

    if (mutex->type == thread_mutex_critical_section)
    {
        /* TODO :implement trylock for critical section */
    }
    else
    {
        DWORD rv = WaitForSingleObject(mutex->handle, 0);
        if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED))
        {
            /*can be either BUSY or an os specific error */
            return AXIS2_FAILURE;
        }
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_unlock(
    axutil_thread_mutex_t * mutex)
{
    if (mutex->type == thread_mutex_critical_section)
    {
        LeaveCriticalSection(&mutex->section);
    }
    else if (mutex->type == thread_mutex_unnested_event)
    {
        if (!SetEvent(mutex->handle))
        {
            /*os specific error */
            return AXIS2_FAILURE;
        }
    }
    else if (mutex->type == thread_mutex_nested_mutex)
    {
        if (!ReleaseMutex(mutex->handle))
        {
            /*os specific error */
            return AXIS2_FAILURE;
        }
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_thread_mutex_destroy(
    axutil_thread_mutex_t * mutex)
{
    return thread_mutex_cleanup((void *) mutex);
}
