/*
 * 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 <decaf/util/concurrent/Mutex.h>

#include <apr_errno.h>
#include <apr_time.h>

using namespace decaf;
using namespace decaf::internal;
using namespace decaf::util;
using namespace decaf::util::concurrent;

////////////////////////////////////////////////////////////////////////////////
Mutex::Mutex() {

    apr_thread_mutex_create( &mutex, APR_THREAD_MUTEX_NESTED, aprPool.getAprPool() );
    this->lock_owner = 0;
    this->lock_count = 0;
}

////////////////////////////////////////////////////////////////////////////////
Mutex::~Mutex() {

    // Unlock the mutex, the destruction of the AprPool will take care
    // of cleaning up the apr_thread_mutex_t allocated in the ctor.
    unlock();
}

////////////////////////////////////////////////////////////////////////////////
void Mutex::lock() throw( lang::Exception ) {

    unsigned long threadId = lang::Thread::getId();

    if( threadId == lock_owner ) {
        lock_count++;
    } else {
        apr_thread_mutex_lock( mutex );
        lock_owner = threadId;
        lock_count = 1;
    }
}

////////////////////////////////////////////////////////////////////////////////
void Mutex::unlock() throw( lang::Exception ) {

    if( lock_owner == 0 ) {
        return;
    }

    if( !isLockOwner() ) {
        throw lang::Exception(
            __FILE__, __LINE__,
            "Mutex::unlock - Failed, not Lock Owner!" );
    }

    lock_count--;

    if(lock_count == 0) {
        lock_owner = 0;
        apr_thread_mutex_unlock( mutex );
    }
}

////////////////////////////////////////////////////////////////////////////////
void Mutex::wait() throw( lang::Exception ) {
    // Delegate to the timed version
    wait( WAIT_INFINITE );
}

////////////////////////////////////////////////////////////////////////////////
void Mutex::wait( unsigned long millisecs )
    throw( lang::Exception ) {

    if( !isLockOwner() ) {
        throw lang::Exception(
            __FILE__, __LINE__,
            "Mutex::wait - Failed, not Lock Owner!");
    }

    // Save the current owner as we are going to unlock and release for
    // someone else to lock on potentially.  When we come back and
    // re-lock we want to restore to the state we were in before.
    unsigned long lock_owner = this->lock_owner;
    unsigned long lock_count = this->lock_count;

    this->lock_owner = 0;
    this->lock_count = 0;

    // Create this threads wait event
    apr_thread_cond_t* waitEvent = NULL;
    apr_thread_cond_create( &waitEvent, aprPool.getAprPool() );

    // Store the event in the queue so that a notify can
    // call it and wake up the thread.
    eventQ.push_back( waitEvent );

    if( millisecs != WAIT_INFINITE ) {
        apr_interval_time_t wait = millisecs * 1000;
        apr_thread_cond_timedwait( waitEvent, mutex, wait );
    } else {
        apr_thread_cond_wait( waitEvent, mutex );
    }

    // Be Sure that the event is now removed
    eventQ.remove( waitEvent );

    // Destroy our wait event now, the notify method will have removed it
    // from the event queue.
    apr_thread_cond_destroy( waitEvent );

    // restore the owner
    this->lock_owner = lock_owner;
    this->lock_count = lock_count;
}

////////////////////////////////////////////////////////////////////////////////
void Mutex::notify() throw( lang::Exception )
{
    if( !isLockOwner() ) {
        throw lang::Exception(
            __FILE__, __LINE__,
            "Mutex::Notify - Failed, not Lock Owner!" );
    }

    if( !eventQ.empty() ) {
        apr_thread_cond_t* event = eventQ.front();
        eventQ.remove( event );
        apr_thread_cond_signal( event );
    }
}

////////////////////////////////////////////////////////////////////////////////
void Mutex::notifyAll() throw( lang::Exception )
{
    if( !isLockOwner() ) {
        throw lang::Exception(
            __FILE__, __LINE__,
            "Mutex::NotifyAll - Failed, not Lock Owner!" );
    }

    while( !eventQ.empty() ) {
        apr_thread_cond_t* event = eventQ.front();
        eventQ.remove( event );
        apr_thread_cond_signal( event );
    }
}
