/*
 * Copyright 2015 Nest Labs, Inc.
 *
 * Licensed 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.
 */

#pragma once

#include <cassert>
#include <memory>
#include <mutex>
#include <condition_variable>

#ifdef __GNUC__
#define FOLLY_CANCELLATION_WARN_UNUSED __attribute__((warn_unused_result))
#else
#define FOLLY_CANCELLATION_WARN_UNUSED
#endif

namespace folly {

class Cancellation;

namespace detail {

/**
 * The shared state object that implements the Cancellation object
 *
 * You must not use this class directly.
 *
 * This object is the <em>actual</em> Cancellation. It implements the
 * std::BasicLockable interface, and therefore may be controlled by
 * objects like std::lock_guard<T>.
 */
struct CancellationSharedState
{
public:
    /* Cancellation shall *only* use the 'protected' or public methods.
     */
    friend class folly::Cancellation;

    CancellationSharedState() {}
    ~CancellationSharedState() {}

    /* non-copyable */
    CancellationSharedState(const CancellationSharedState& o) = delete;
    CancellationSharedState& operator=(const CancellationSharedState& o) = delete;

    /* non-moveable (thread safe move?) */
    CancellationSharedState(CancellationSharedState&& o) = delete;
    CancellationSharedState& operator=(CancellationSharedState&& o) = delete;

    /* std::BasicLockable concept. Locks state. */
    void lock()
    {
        bool have_lock = try_lock();
        if (!have_lock) {
            throw std::logic_error("Cancellation is cancelled, can't lock");
        }
    }

    /* std::BasicLockable concept. Unocks state. */
    void unlock()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        assert(hold_state_refs_ > 0);
        --hold_state_refs_;
        if (hold_state_refs_ == 0) {
            cond_.notify_all();
        }
    }

    /* std::Lockable concept. Attempts to lock state. Returns true if NOT cancelled. */
    bool try_lock()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (is_cancelled_) {
            return false;
        }
        ++hold_state_refs_;
        assert(hold_state_refs_ != 0); /* overflow */
        return true;
    }

protected:

    bool is_cancelled() const
    {
        std::lock_guard<std::mutex> lock(mutex_);
        return is_cancelled_;
    }

    /* Set state to CANCELLED. Blocks if there are active state refs. */
    void cancel()
    {
        // TODO: this implementation is subject to a live-lock
        std::unique_lock<std::mutex> lock(mutex_);
        ++cancel_refs_;
        assert(cancel_refs_ != 0); /* overflow */
        while (hold_state_refs_ > 0) {
            cond_.wait(lock);
        }
        is_cancelled_ = true;
        assert(cancel_refs_ > 0);
        --cancel_refs_;
    }

private:
    mutable std::mutex mutex_;
    mutable std::condition_variable cond_;
    unsigned cancel_refs_ {0};             //< number of cancel() calls currently active
    unsigned hold_state_refs_ {0};         //< number of state refs currently active
    bool is_cancelled_ {false};            //< state. false = not cancelled, true = cancelled.
};

} /* namespace detail */
} /* namespace folly */
