/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <algorithm>
#include <atomic>
#include <string>

#include "runtime/global_config.h"
#include "runtime/service_engine.h"
#include "utils/factory_store.h"
#include "utils/fmt_logging.h"
#include "utils/utils.h"
#include "utils/zlock_provider.h"
#include "utils/zlocks.h"

namespace dsn {

namespace lock_checker {
__thread int zlock_exclusive_count;
__thread int zlock_shared_count;

void check_wait_safety()
{
    if (zlock_exclusive_count + zlock_shared_count > 0) {
        LOG_WARNING("wait inside locks may lead to deadlocks - current thread owns {} exclusive "
                    "locks and {} shared locks now.",
                    zlock_exclusive_count,
                    zlock_shared_count);
    }
}

void check_dangling_lock()
{
    if (zlock_exclusive_count + zlock_shared_count > 0) {
        LOG_WARNING("locks should not be hold at this point - current thread owns {} exclusive "
                    "locks and {} shared locks now.",
                    zlock_exclusive_count,
                    zlock_shared_count);
    }
}
} // namespace lock_checker

zlock::zlock(bool recursive)
{
    if (recursive) {
        lock_provider *last = utils::factory_store<lock_provider>::create(
            dsn::service_engine::instance().spec().lock_factory_name.c_str(),
            dsn::PROVIDER_TYPE_MAIN,
            nullptr);
        _h = last;
    } else {
        lock_nr_provider *last = utils::factory_store<lock_nr_provider>::create(
            dsn::service_engine::instance().spec().lock_nr_factory_name.c_str(),
            dsn::PROVIDER_TYPE_MAIN,
            nullptr);
        _h = last;
    }
}

zlock::~zlock() { delete _h; }

void zlock::lock()
{
    _h->lock();
    ++lock_checker::zlock_exclusive_count;
}

bool zlock::try_lock()
{
    auto r = _h->try_lock();
    if (r) {
        ++lock_checker::zlock_exclusive_count;
    }
    return r;
}

void zlock::unlock()
{
    --lock_checker::zlock_exclusive_count;
    _h->unlock();
}

zrwlock_nr::zrwlock_nr()
{
    rwlock_nr_provider *last = utils::factory_store<rwlock_nr_provider>::create(
        service_engine::instance().spec().rwlock_nr_factory_name.c_str(),
        dsn::PROVIDER_TYPE_MAIN,
        nullptr);
    _h = last;
}

zrwlock_nr::~zrwlock_nr() { delete _h; }

void zrwlock_nr::lock_read()
{
    _h->lock_read();
    ++lock_checker::zlock_shared_count;
}

void zrwlock_nr::unlock_read()
{
    --lock_checker::zlock_shared_count;
    _h->unlock_read();
}

bool zrwlock_nr::try_lock_read()
{
    auto r = _h->try_lock_read();
    if (r)
        ++lock_checker::zlock_shared_count;
    return r;
}

void zrwlock_nr::lock_write()
{
    _h->lock_write();
    ++lock_checker::zlock_exclusive_count;
}

void zrwlock_nr::unlock_write()
{
    --lock_checker::zlock_exclusive_count;
    _h->unlock_write();
}

bool zrwlock_nr::try_lock_write()
{
    auto r = _h->try_lock_write();
    if (r)
        ++lock_checker::zlock_exclusive_count;
    return r;
}

zsemaphore::zsemaphore(int initial_count)
{
    semaphore_provider *last = utils::factory_store<semaphore_provider>::create(
        service_engine::instance().spec().semaphore_factory_name.c_str(),
        PROVIDER_TYPE_MAIN,
        initial_count,
        nullptr);
    _h = last;
}

zsemaphore::~zsemaphore() { delete _h; }

void zsemaphore::signal(int count) { _h->signal(count); }

bool zsemaphore::wait(int timeout_milliseconds)
{
    if (static_cast<unsigned int>(timeout_milliseconds) == TIME_MS_MAX) {
        lock_checker::check_wait_safety();
        _h->wait();
        return true;
    } else {
        return _h->wait(timeout_milliseconds);
    }
}

zevent::zevent(bool manualReset, bool initState /* = false*/)
{
    _manualReset = manualReset;
    _signaled = initState;
    if (_signaled) {
        _sema.signal();
    }
}

zevent::~zevent() {}

void zevent::set()
{
    bool nonsignaled = false;
    if (std::atomic_compare_exchange_strong(&_signaled, &nonsignaled, true)) {
        _sema.signal();
    }
}

void zevent::reset()
{
    if (_manualReset) {
        bool signaled = true;
        if (std::atomic_compare_exchange_strong(&_signaled, &signaled, false)) {
        }
    }
}

bool zevent::wait(int timeout_milliseconds)
{
    if (_manualReset) {
        if (std::atomic_load(&_signaled))
            return true;

        _sema.wait(timeout_milliseconds);
        return std::atomic_load(&_signaled);
    }

    else {
        bool signaled = true;
        if (std::atomic_compare_exchange_strong(&_signaled, &signaled, false))
            return true;

        _sema.wait(timeout_milliseconds);
        return std::atomic_compare_exchange_strong(&_signaled, &signaled, false);
    }
}
} // namespace dsn
