/*
 * 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 <log4cxx/logstring.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/mutex.h>
#include <log4cxx/helpers/pool.h>
#include <apr_thread_mutex.h>
#include <apr_thread_rwlock.h>
#include <assert.h>
#if !defined(LOG4CXX)
#define LOG4CXX 1
#endif
#include <log4cxx/helpers/aprinitializer.h>

#if defined(NON_BLOCKING)

#if defined(WIN32) || defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#else
// POSIX
#include <semaphore.h>
#endif

#endif // NON_BLOCKING

using namespace log4cxx::helpers;
using namespace log4cxx;


Mutex::Mutex(Pool& p) {
#if APR_HAS_THREADS
        apr_status_t stat = apr_thread_mutex_create(&mutex,
                APR_THREAD_MUTEX_NESTED, p.getAPRPool());
        if (stat != APR_SUCCESS) {
                throw MutexException(stat);
        }
#endif
}

Mutex::Mutex(apr_pool_t* p) {
#if APR_HAS_THREADS
        apr_status_t stat = apr_thread_mutex_create(&mutex,
                APR_THREAD_MUTEX_NESTED, p);
        if (stat != APR_SUCCESS) {
                throw MutexException(stat);
        }
#endif
}


Mutex::~Mutex() {
#if APR_HAS_THREADS
	// LOGCXX-322
	if (APRInitializer::isDestructed)
	{
		return;
	}

	apr_thread_mutex_destroy(mutex);
#endif
}

apr_thread_mutex_t* Mutex::getAPRMutex() const {
    return mutex;
}

#if defined(RW_MUTEX)

RWMutex::RWMutex(Pool& p)
        : id((apr_os_thread_t)-1)
        , count(0)
{
#if APR_HAS_THREADS
        apr_status_t stat = apr_thread_rwlock_create(&mutex,
                p.getAPRPool());
        if (stat != APR_SUCCESS) {
                throw MutexException(stat);
        }
#endif
}

RWMutex::RWMutex(apr_pool_t* p)
        : id((apr_os_thread_t)-1)
        , count(0)
{
#if APR_HAS_THREADS
        apr_status_t stat = apr_thread_rwlock_create(&mutex, p);
        if (stat != APR_SUCCESS) {
                throw MutexException(stat);
        }
#endif
}


RWMutex::~RWMutex() {
#if APR_HAS_THREADS
        apr_thread_rwlock_destroy(mutex);
#endif
}

void RWMutex::rdLock() const
{
#if APR_HAS_THREADS
        apr_status_t stat = apr_thread_rwlock_rdlock(mutex);
#endif
}

void RWMutex::rdUnlock() const
{
#if APR_HAS_THREADS
        apr_status_t stat = apr_thread_rwlock_unlock(mutex);
#endif
}

void RWMutex::wrLock() const
{
#if APR_HAS_THREADS
         apr_os_thread_t self = apr_os_thread_current();
         if (id == self)
         {
             ++count;
         }
         else
         {
             apr_status_t stat = apr_thread_rwlock_wrlock(mutex);
             id = self;
             count = 1;
         }
#endif
}

void RWMutex::wrUnlock() const
{
#if APR_HAS_THREADS
         if (--count == 0)
         {
             id = (apr_os_thread_t)-1;  // id_ = "not a thread"
             apr_status_t stat = apr_thread_rwlock_unlock(mutex);
         }
         else
         {
         }
#endif
}

#endif // RW_MUTEX

#if defined(NON_BLOCKING)

#if defined(WIN32) || defined(_WIN32) || defined(_WIN64)

namespace log4cxx {
	namespace helpers {
		struct SemaphoreImpl
		{
			HANDLE semaphore;
		};
	}
}

static const LONG cMax = 10000; // arbitrary high value

Semaphore::Semaphore(log4cxx::helpers::Pool& p)
	: impl(nullptr)
{
#if APR_HAS_THREADS
	impl = (SemaphoreImpl*)p.palloc(sizeof(SemaphoreImpl));
	if (nullptr == impl) {
		throw MutexException(APR_ENOMEM);
	}

	impl->semaphore = CreateSemaphore(
		NULL,  // default security attributes
		0,     // initial count
		cMax,  // maximum count
		NULL); // unnamed semaphore

	if (impl->semaphore == NULL) {
		throw MutexException(APR_ENOSHMAVAIL);
	}
#endif
}

Semaphore::~Semaphore()
{
#if APR_HAS_THREADS
	if (impl && impl->semaphore)
	{
		CloseHandle(impl->semaphore);
	}
#endif
}

void Semaphore::await() const
{
#if APR_HAS_THREADS
	DWORD dwWaitResult = WaitForSingleObject(impl->semaphore, INFINITE);
	if (stat != 0) {
		throw MutexException(1);
	}
#endif
}

void Semaphore::signalAll() const
{
#if APR_HAS_THREADS
	BOOL stat = ReleaseSemaphore(impl->semaphore, 1, NULL);
	if (!stat) {
		throw MutexException(stat);
	}
#endif
}

#else
// POSIX

namespace log4cxx {
    namespace helpers {
        struct SemaphoreImpl
        {
            sem_t semaphore;
        };
    }
}

Semaphore::Semaphore(log4cxx::helpers::Pool& p)
    : impl(nullptr)
{
#if APR_HAS_THREADS
    impl = (SemaphoreImpl*)p.palloc(sizeof(SemaphoreImpl));
    if (nullptr == impl) {
        throw MutexException(APR_ENOMEM);
    }

    int stat = sem_init(&impl->semaphore, 0, 0);
    if (stat != 0) {
        throw MutexException(APR_ENOSHMAVAIL);
    }
#endif
}

Semaphore::~Semaphore()
{
#if APR_HAS_THREADS
    if (impl)
    {
        int stat = sem_destroy(&impl->semaphore);
    }
#endif
}

void Semaphore::await() const
{
#if APR_HAS_THREADS
    int stat = sem_wait(&impl->semaphore);
    if (stat != 0) {
        throw MutexException(stat);
    }
#endif
}

void Semaphore::signalAll() const
{
#if APR_HAS_THREADS
    int stat = sem_post(&impl->semaphore);
    if (stat != 0) {
        throw MutexException(stat);
    }
#endif
}

#endif // POSIX

#endif // NON_BLOCKING
