/* 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 "apr.h"
#include "apr_private.h"
#include "apr_general.h"
#include "apr_strings.h"
#include "win32/apr_arch_thread_rwlock.h"
#include "apr_portable.h"

static apr_status_t thread_rwlock_cleanup(void *data)
{
    apr_thread_rwlock_t *rwlock = data;
    
    if (! CloseHandle(rwlock->read_event))
        return apr_get_os_error();

    if (! CloseHandle(rwlock->write_mutex))
        return apr_get_os_error();
    
    return APR_SUCCESS;
}

APR_DECLARE(apr_status_t)apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
                                                  apr_pool_t *pool)
{
    *rwlock = apr_palloc(pool, sizeof(**rwlock));

    (*rwlock)->pool        = pool;
    (*rwlock)->readers     = 0;

    if (! ((*rwlock)->read_event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
        *rwlock = NULL;
        return apr_get_os_error();
    }

    if (! ((*rwlock)->write_mutex = CreateMutex(NULL, FALSE, NULL))) {
        CloseHandle((*rwlock)->read_event);
        *rwlock = NULL;
        return apr_get_os_error();
    }

    apr_pool_cleanup_register(pool, *rwlock, thread_rwlock_cleanup,
                              apr_pool_cleanup_null);

    return APR_SUCCESS;
}

static apr_status_t apr_thread_rwlock_rdlock_core(apr_thread_rwlock_t *rwlock,
                                                  DWORD  milliseconds)
{
    DWORD   code = WaitForSingleObject(rwlock->write_mutex, milliseconds);

    if (code == WAIT_FAILED || code == WAIT_TIMEOUT)
        return APR_FROM_OS_ERROR(code);

    /* We've successfully acquired the writer mutex, we can't be locked
     * for write, so it's OK to add the reader lock.  The writer mutex
     * doubles as race condition protection for the readers counter.   
     */
    InterlockedIncrement(&rwlock->readers);
    
    if (! ResetEvent(rwlock->read_event))
        return apr_get_os_error();
    
    if (! ReleaseMutex(rwlock->write_mutex))
        return apr_get_os_error();
    
    return APR_SUCCESS;
}

APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
{
    return apr_thread_rwlock_rdlock_core(rwlock, INFINITE);
}

APR_DECLARE(apr_status_t) 
apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
{
    return apr_thread_rwlock_rdlock_core(rwlock, 0);
}

static apr_status_t 
apr_thread_rwlock_wrlock_core(apr_thread_rwlock_t *rwlock, DWORD milliseconds)
{
    DWORD   code = WaitForSingleObject(rwlock->write_mutex, milliseconds);

    if (code == WAIT_FAILED || code == WAIT_TIMEOUT)
        return APR_FROM_OS_ERROR(code);

    /* We've got the writer lock but we have to wait for all readers to
     * unlock before it's ok to use it.
     */
    if (rwlock->readers) {
        /* Must wait for readers to finish before returning, unless this
         * is an trywrlock (milliseconds == 0):
         */
        code = milliseconds
          ? WaitForSingleObject(rwlock->read_event, milliseconds)
          : WAIT_TIMEOUT;
        
        if (code == WAIT_FAILED || code == WAIT_TIMEOUT) {
            /* Unable to wait for readers to finish, release write lock: */
            if (! ReleaseMutex(rwlock->write_mutex))
                return apr_get_os_error();
            
            return APR_FROM_OS_ERROR(code);
        }
    }

    return APR_SUCCESS;
}

APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
{
    return apr_thread_rwlock_wrlock_core(rwlock, INFINITE);
}

APR_DECLARE(apr_status_t)apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
{
    return apr_thread_rwlock_wrlock_core(rwlock, 0);
}

APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
{
    apr_status_t rv = 0;

    /* First, guess that we're unlocking a writer */
    if (! ReleaseMutex(rwlock->write_mutex))
        rv = apr_get_os_error();
    
    if (rv == APR_FROM_OS_ERROR(ERROR_NOT_OWNER)) {
        /* Nope, we must have a read lock */
        if (rwlock->readers &&
            ! InterlockedDecrement(&rwlock->readers) &&
            ! SetEvent(rwlock->read_event)) {
            rv = apr_get_os_error();
        }
        else {
            rv = 0;
        }
    }

    return rv;
}

APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
{
    return apr_pool_cleanup_run(rwlock->pool, rwlock, thread_rwlock_cleanup);
}

APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)
