// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Can't compile this for Zircon userspace yet since libstdc++ isn't available.
#ifndef FIT_NO_STD_FOR_ZIRCON_USERSPACE

#include <lib/fit/scope.h>

namespace fit {

scope::scope()
    : state_(new state()) {}

scope::~scope() {
    state_->exit(true /*scope_was_destroyed*/);
}

scope::state::state() = default;

scope::state::~state() {
    assert(acquired_promise_count_.load(std::memory_order_relaxed) ==
           scope_exited);
    assert(scope_was_destroyed_);
    assert(promise_handle_count_ == 0);
    assert(head_promise_holder_ == nullptr);
}

bool scope::state::exited() const {
    return acquired_promise_count_.load(std::memory_order_relaxed) & scope_exited;
}

void scope::state::exit(bool scope_was_destroyed) {
    promise_holder_base* release_head = nullptr;
    bool delete_self = false;
    {
        std::lock_guard<std::mutex> lock(mutex_);
        assert(!scope_was_destroyed_);
        scope_was_destroyed_ = scope_was_destroyed;

        // Atomically exit the scope.  We cannot do this safely if there are
        // any running promises since they might still be accessing state which
        // is guarded by the scope.  Worse, if a promise re-entrantly destroys
        // the scope during its execution then as a side-effect the promise
        // itself will be destroyed.  So assert!
        uint64_t prior_count = acquired_promise_count_.exchange(
            scope_exited, std::memory_order_relaxed);
        if (!(prior_count & scope_exited)) {
            // Cannot exit fit::scope while any of its promises are running!
            assert(prior_count == 0);

            // Take the promises so they can be deleted outside of the lock.
            release_head = head_promise_holder_;
            head_promise_holder_ = nullptr;
        }

        // If there are no more handles then we can delete the state now.
        delete_self = should_delete_self();
    }

    // Delete aborted promises and self outside of the lock.
    while (release_head) {
        promise_holder_base* release_next = release_head->next;
        delete release_head;
        release_head = release_next;
    }
    if (delete_self) {
        delete this;
    }
}

scope::promise_handle scope::state::adopt_promise(
    promise_holder_base* promise_holder) {
    {
        std::lock_guard<std::mutex> lock(mutex_);
        assert(!scope_was_destroyed_); // otherwise how did we get here?

        // If the scope hasn't been exited yet, link the promise and mint
        // a new handle.  Otherwise we will abort the promise.
        if (!exited()) {
            if (head_promise_holder_) {
                head_promise_holder_->prev = promise_holder;
                promise_holder->next = head_promise_holder_;
            }
            head_promise_holder_ = promise_holder;
            promise_handle_count_++;
            return promise_handle(this, promise_holder);
        }
    }

    // Delete aborted promise outside of the lock.
    delete promise_holder;
    return promise_handle{};
}

void scope::state::drop_promise(promise_handle promise_handle) {
    if (!promise_handle.promise_holder) {
        return; // invalid handle, nothing to do
    }

    {
        std::lock_guard<std::mutex> lock(promise_handle.state->mutex_);

        // If the scope hasn't been exited yet, unlink the promise and
        // prepare to destroy it.  Otherwise, it's already been unlinked
        // and destroyed so release the handle but don't touch the pointer!
        assert(promise_handle.state->promise_handle_count_ > 0);
        promise_handle.state->promise_handle_count_--;
        if (!promise_handle.state->exited()) {
            if (promise_handle.promise_holder->next) {
                promise_handle.promise_holder->next->prev =
                    promise_handle.promise_holder->prev;
            }
            if (promise_handle.promise_holder->prev) {
                promise_handle.promise_holder->prev->next =
                    promise_handle.promise_holder->next;
            } else {
                promise_handle.state->head_promise_holder_ =
                    promise_handle.promise_holder->next;
            }
            // Fallthrough to delete the promise.
        } else if (!promise_handle.state->should_delete_self()) {
            return;
        } else {
            // Fallthrough to delete self.
            promise_handle.promise_holder = nullptr;
        }
    }

    // Delete the promise or scope outside of the lock.
    if (promise_handle.promise_holder) {
        delete promise_handle.promise_holder;
    } else {
        delete promise_handle.state;
    }
}

scope::promise_holder_base* scope::state::try_acquire_promise(
    promise_handle promise_handle) {
    if (promise_handle.promise_holder) {
        uint64_t prior_count = promise_handle.state->acquired_promise_count_.fetch_add(
            1u, std::memory_order_relaxed);
        if (!(prior_count & scope_exited)) {
            return promise_handle.promise_holder;
        }
        promise_handle.state->acquired_promise_count_.fetch_sub(
            1u, std::memory_order_relaxed);
    }
    return nullptr;
}

void scope::state::release_promise(promise_handle promise_handle) {
    promise_handle.state->acquired_promise_count_.fetch_sub(
        1u, std::memory_order_relaxed);
}

} // namespace fit

#endif // FIT_NO_STD_FOR_ZIRCON_USERSPACE
