// Copyright 2016 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.

#ifndef FBL_INTRUSIVE_SINGLE_LIST_H_
#define FBL_INTRUSIVE_SINGLE_LIST_H_

#include <zircon/assert.h>
#include <fbl/intrusive_container_utils.h>
#include <fbl/intrusive_pointer_traits.h>
#include <fbl/macros.h>

#include <utility>

// Usage Notes:
//
// fbl::SinglyLinkedList<> is a templated intrusive container class which
// allows users to manage singly linked lists of objects.
//
// The bookkeeping storage required to exist on a list is a property of the
// objects stored on the list eliminating the need for runtime bookkeeping
// allocation/deallocation to add/remove members to/from the container.
//
// Lists store pointers to the objects, not the objects themselves, and are
// templated based on the specific type of pointer to be stored.  Supported
// pointer types are....
// 1) T*            : raw unmanaged pointers
// 2) unique_ptr<T> : unique managed pointers.
// 3) RefPtr<T>     : managed pointers to ref-counted objects.
//
// Lists of managed pointer types hold references to objects and follow the
// rules of the particular managed pointer patterns.  Destroying or clearing a
// list of managed pointers will release the references to the objects and may
// end the lifecycle of an object if the reference held by the list happened to
// be the last.
//
// Lists of unmanaged pointer types perform no lifecycle management.  It is up to
// the user of the list class to make sure that lifecycles are managed properly.
// As an added safety, a list of unmanaged pointers will ZX_ASSERT if it is
// destroyed with elements still in it.
//
// Objects may exist in multiple lists (or other containers) through the use of
// custom trait classes.  It should be noted that it is possible to make
// different types lists of unique_ptr<T> for a given T, but there is little
// point in doing so as it is impossible to exist on multiple lists at the same
// time without violating the fundamental rules of unique_ptr<T> patterns.
//
// Default traits and a helper base class are provided to make it easy to
// implement list-able objects intended to exist on only one type of list.
//
////////////////////////////////////////////////////////////////////////////////
// Example: A simple list of unmanaged pointers to Foo objects
//
// class Foo : public fbl::SinglyLinkedListable<Foo*> {
//      ...
// };
//
// void Test() {
//     fbl::SinglyLinkedList<Foo*> list;
//
//     for (size_t i = 0; SOME_NUMBER; ++i)
//         list.push_front(new Foo(...));
//
//     for (const auto& foo : list)
//         foo.print();
//
//     while (!list.is_empty())
//         delete list.pop_front();
// }
//
////////////////////////////////////////////////////////////////////////////////
// Example: A simple list of unique pointers to Foo objects
//
// class Foo : public fbl::SinglyLinkedListable<unique_ptr<Foo>> {
//      ...
// };
//
// void Test() {
//     fbl::SinglyLinkedList<unique_ptr<Foo>> list;
//
//     for (size_t i = 0; SOME_NUMBER; ++i) {
//         unique_ptr<Foo> new_foo(new Foo(...));
//         list.push_front(std::move(new_foo));
//     }
//
//     for (const auto& foo : list)
//         foo.print();
//
//     list.clear();    // Could also just let the list go out of scope.
// }
//
////////////////////////////////////////////////////////////////////////////////
// Example: A more complicated example of a list of ref-counted objects which
// can exist on 3 different types of lists at the same time.
//
// class Foo : public fbl::SinglyLinkedListable<fbl::RefPtr<Foo>>
//           , public fbl::RefCounted<Foo> {
// public:
//     using NodeState = SinglyLinkedListNodeState<Foo>;
//     struct TypeATraits { static NodeState& node_state(Foo& foo) { return foo.type_a_state_; } }
//     struct TypeBTraits { static NodeState& node_state(Foo& foo) { return foo.type_b_state_; } }
//
//     /* Class implementation goes here */
//
// private:
//     friend struct TypeATraits;
//     friend struct TypeBTraits;
//     NodeState type_a_state_;
//     NodeState type_b_state_;
// };
//
// void Test() {
//     using DefaultList = fbl::SinglyLinkedList<fbl::RefPtr<Foo>>;
//     using TypeAList   = fbl::SinglyLinkedList<fbl::RefPtr<Foo>, Foo::TypeATraits>;
//     using TypeBList   = fbl::SinglyLinkedList<fbl::RefPtr<Foo>, Foo::TypeBTraits>;
//
//     DefaultList default_list;
//     TypeAList a_list;
//     TypeAList b_list;
//
//     for (size_t i = 0; SOME_NUMBER; ++i) {
//         RefPtr new_foo = AdoptRef(new Foo(...));
//
//         switch (i & 0x3) {
//             case 0: break;
//             case 1: a_list.push_front(new_foo); break;
//             case 2: b_list.push_front(new_foo); break;
//             case 3:
//                 a_list.push_front(new_foo);
//                 b_list.push_front(new_foo);
//                 break;
//         }
//
//         default_list.push_front(std::move(new_foo));
//     }
//
//     for (const auto& foo : default_list) foo.print();
//     for (const auto& foo : a_list) foo.print();
//     for (const auto& foo : b_list) foo.print();
//
//     default_list.clear();  // case 0 Foo's get cleaned up.
//     a_list.clear();        // case 1 Foo's get cleaned up.
//     b_list.clear();        // case 2 and 3 Foo's get cleaned up.
// }

namespace fbl {

// Fwd decl of classes used by tests.
namespace tests {
namespace intrusive_containers {
class SinglyLinkedListChecker;
template <typename> class SequenceContainerTestEnvironment;
}  // namespace tests
}  // namespace intrusive_containers

// SinglyLinkedListNodeState<T>
//
// The state needed to be a member of a SinglyLinkedList<T>.  All members of a
// specific type SinglyLinkedList<T> must expose a SinglyLinkedListNodeState<T>
// to the list implementation via the supplied traits.  See
// DefaultSinglyLinkedListTraits<T>
template <typename T>
struct SinglyLinkedListNodeState {
    using PtrTraits = internal::ContainerPtrTraits<T>;
    constexpr SinglyLinkedListNodeState() { }
    ~SinglyLinkedListNodeState() {
        // Note; this ASSERT can only be enforced for lists made of managed
        // pointer types.  Lists formed from unmanaged pointers can potentially
        // leave next_ in a non-null state during destruction if the list is
        // cleared using "clear_unsafe".
        ZX_DEBUG_ASSERT(!PtrTraits::IsManaged || (next_ == nullptr));
    }

    bool IsValid() const     { return true; }
    bool InContainer() const { return (next_ != nullptr); }

private:
    template <typename, typename> friend class SinglyLinkedList;
    template <typename> friend class tests::intrusive_containers::SequenceContainerTestEnvironment;
    friend class tests::intrusive_containers::SinglyLinkedListChecker;

    typename PtrTraits::RawPtrType next_ = nullptr;
};

// DefaultSinglyLinkedListNodeState<T>
//
// The default implementation of traits needed to be a member of a singly linked
// list.  Any valid traits implementation must expose a static node_state method
// compatible with DefaultSinglyLinkedListTraits<T>::node_state(...).  To use
// the default traits, an object may...
//
// 1) Be friends with DefaultSinglyLinkedListTraits<T> and have a private
//    sll_node_state_ member.
// 2) Have a public sll_node_state_ member (not recommended)
// 3) Derive from SinglyLinkedListable<T> (easiest)
template <typename T>
struct DefaultSinglyLinkedListTraits {
    using PtrTraits = internal::ContainerPtrTraits<T>;
    static SinglyLinkedListNodeState<T>& node_state(typename PtrTraits::RefType obj) {
        return obj.sll_node_state_;
    }
};

// SinglyLinkedListable<T>
//
// A helper class which makes it simple to exist on a singly linked list.
// Simply derive your object from SinglyLinkedListable and you are done.
template <typename T>
struct SinglyLinkedListable {
public:
    bool InContainer() const { return sll_node_state_.InContainer(); }

private:
    friend struct DefaultSinglyLinkedListTraits<T>;
    SinglyLinkedListNodeState<T> sll_node_state_;
};

template <typename T, typename _NodeTraits = DefaultSinglyLinkedListTraits<T>>
class SinglyLinkedList {
private:
    // Private fwd decls of the iterator implementation.
    template <typename IterTraits> class iterator_impl;
    struct iterator_traits;
    struct const_iterator_traits;

public:
    // Aliases used to reduce verbosity and expose types/traits to tests
    using PtrTraits     = internal::ContainerPtrTraits<T>;
    using NodeTraits    = _NodeTraits;
    using PtrType       = typename PtrTraits::PtrType;
    using RawPtrType    = typename PtrTraits::RawPtrType;
    using ValueType     = typename PtrTraits::ValueType;
    using CheckerType   = ::fbl::tests::intrusive_containers::SinglyLinkedListChecker;
    using ContainerType = SinglyLinkedList<T, NodeTraits>;

    // Declarations of the standard iterator types.
    using iterator       = iterator_impl<iterator_traits>;
    using const_iterator = iterator_impl<const_iterator_traits>;

    // Singly linked lists do not support constant order erase (erase using an
    // iterator or direct object reference).
    static constexpr bool SupportsConstantOrderErase = false;
    static constexpr bool SupportsConstantOrderSize = false;
    static constexpr bool IsAssociative = false;
    static constexpr bool IsSequenced = true;

    // Default construction gives an empty list.
    constexpr SinglyLinkedList() { }

    // Rvalue construction is permitted, but will result in the move of the list
    // contents from one instance of the list to the other (even for unmanaged
    // pointers)
    SinglyLinkedList(SinglyLinkedList<T, NodeTraits>&& other_list) {
        swap(other_list);
    }

    // Rvalue assignment is permitted for managed lists, and when the target is
    // an empty list of unmanaged pointers.  Like Rvalue construction, it will
    // result in the move of the source contents to the destination.
    SinglyLinkedList& operator=(SinglyLinkedList&& other_list) {
        ZX_DEBUG_ASSERT(PtrTraits::IsManaged || is_empty());

        clear();
        swap(other_list);

        return *this;
    }

    ~SinglyLinkedList() {
        // It is considered an error to allow a list of unmanaged pointers to
        // destruct of there are still elements in it.  Managed pointer lists
        // will automatically release their references to their elements.
        ZX_DEBUG_ASSERT(PtrTraits::IsManaged || is_empty());
        clear();
    }

    // Standard begin/end, cbegin/cend iterator accessors.
    iterator        begin()       { return iterator(head_); }
    const_iterator  begin() const { return const_iterator(head_); }
    const_iterator cbegin() const { return const_iterator(head_); }

    iterator          end()       { return iterator(sentinel()); }
    const_iterator    end() const { return const_iterator(sentinel()); }
    const_iterator   cend() const { return const_iterator(sentinel()); }

    // make_iterator : construct an iterator out of a reference to an object.
    iterator make_iterator(ValueType& obj) { return iterator(&obj); }

    // is_empty
    //
    // True if the list has at least one element in it, false otherwise.
    bool is_empty() const {
        ZX_DEBUG_ASSERT(head_ != nullptr);
        return internal::is_sentinel_ptr(head_);
    }

    // front
    //
    // Return a reference to the element at the front of the list without
    // removing it.  It is an error to call front on an empty list.
    typename PtrTraits::RefType      front()       { ZX_DEBUG_ASSERT(!is_empty()); return *head_; }
    typename PtrTraits::ConstRefType front() const { ZX_DEBUG_ASSERT(!is_empty()); return *head_; }

    // push_front
    //
    // Push an element onto the front of the lists.  Lvalue and Rvalue
    // versions are supplied in order to support move semantics.  It
    // is an error to attempt to push a nullptr instance of PtrType.
    void push_front(const PtrType& ptr) { push_front(PtrType(ptr)); }
    void push_front(PtrType&& ptr) {
        ZX_DEBUG_ASSERT(ptr != nullptr);

        auto& ptr_ns = NodeTraits::node_state(*ptr);
        ZX_DEBUG_ASSERT(!ptr_ns.InContainer());

        ptr_ns.next_ = head_;
        head_        = PtrTraits::Leak(ptr);
    }

    // insert_after
    //
    // Insert an element after iter in the list.  It is an error to attempt to
    // push a nullptr instance of PtrType, or to attempt to push with iter ==
    // end().
    void insert_after(const iterator& iter, const PtrType& ptr) {
        insert_after(iter, PtrType(ptr));
    }
    void insert_after(const iterator& iter, PtrType&& ptr) {
        ZX_DEBUG_ASSERT(iter.IsValid());
        ZX_DEBUG_ASSERT(ptr != nullptr);

        auto& iter_ns = NodeTraits::node_state(*iter.node_);
        auto& ptr_ns  = NodeTraits::node_state(*ptr);
        ZX_DEBUG_ASSERT(!ptr_ns.InContainer());

        ptr_ns.next_  = iter_ns.next_;
        iter_ns.next_ = PtrTraits::Leak(ptr);
    }

    // pop_front
    //
    // Removes the head of the list and transfer the pointer to the
    // caller.  If the list is empty, return a nullptr instance of
    // PtrType.
    PtrType pop_front() {
        if (is_empty())
            return PtrType(nullptr);

        auto& head_ns = NodeTraits::node_state(*head_);
        PtrType ret = PtrTraits::Reclaim(head_);

        head_ = head_ns.next_;
        head_ns.next_ = nullptr;

        return ret;
    }

    // clear
    //
    // Clear out the list, unlinking all of the elements in the process.  For
    // managed pointer types, this will release all references held by the list
    // to the objects which were in it.
    void clear() {
        while (!is_empty()) {
            auto& head_ns = NodeTraits::node_state(*head_);
            RawPtrType tmp = head_;
            head_ = head_ns.next_;
            head_ns.next_ = nullptr;
            PtrTraits::Reclaim(tmp);
        }
    }

    // clear_unsafe
    //
    // A special clear operation which just resets the internal container
    // structure, but leaves all of the node-state(s) of the current element(s)
    // alone.
    //
    // Only usable with containers of unmanaged pointers (Very Bad things can happen
    // if you try this with containers of managed pointers).
    //
    // Note: While this can be useful in special cases (such as resetting a free
    // list for a pool/slab allocator during destruction), you normally do not
    // want this behavior.  Think carefully before calling this!
    void clear_unsafe() {
        static_assert(PtrTraits::IsManaged == false,
                     "clear_unsafe is not allowed for containers of managed pointers");
        head_ = sentinel();
    }

    // erase_next
    //
    // Remove the element in the list which follows iter.  If there is no
    // element in the list which follows iter, return a nullptr instance of
    // PtrType.  It is an error to attempt to erase_next an invalid iterator
    // (either an uninitialized iterator, or an iterator which is equal to
    // end())
    PtrType erase_next(const iterator& iter) {
        ZX_DEBUG_ASSERT(iter.IsValid());
        auto& iter_ns = NodeTraits::node_state(*iter);

        if (internal::is_sentinel_ptr(iter_ns.next_))
            return PtrType(nullptr);

        auto& next_ns = NodeTraits::node_state(*iter_ns.next_);

        PtrType ret = PtrTraits::Reclaim(iter_ns.next_);
        iter_ns.next_ = next_ns.next_;
        next_ns.next_ = nullptr;
        return ret;
    }

    // swap
    //
    // swaps the contest of two lists.
    void swap(SinglyLinkedList<T, NodeTraits>& other) {
        auto tmp = head_;
        head_ = other.head_;
        other.head_ = tmp;
    }

    // size_slow
    //
    // count the elements in the list in O(n) fashion
    size_t size_slow() const {
        size_t size = 0;

        for (auto iter = cbegin(); iter != cend(); ++iter)
            size++;

        return size;
    }

    // erase_if
    //
    // Find the first member of the list which satisfies the predicate given by
    // 'fn' and erase it from the list, returning a referenced pointer to the
    // removed element.  Return nullptr if no member satisfies the predicate.
    template <typename UnaryFn>
    PtrType erase_if(UnaryFn fn) {
        using ConstRefType  = typename PtrTraits::ConstRefType;

        if (is_empty())
            return PtrType(nullptr);

        auto iter = begin();
        if (fn(static_cast<ConstRefType>(*iter)))
            return pop_front();

        for (auto prev = iter++; iter != end(); prev = iter++) {
            if (fn(static_cast<ConstRefType>(*iter)))
                return erase_next(prev);
        }

        return PtrType(nullptr);
    }

    // find_if
    //
    // Find the first member of the list which satisfies the predicate given by
    // 'fn' and return an iterator in the list which refers to it.  Return end()
    // if no member satisfies the predicate.
    template <typename UnaryFn>
    const_iterator find_if(UnaryFn fn) const {
        for (auto iter = begin(); iter.IsValid(); ++iter) {
            if (fn(*iter))
                return iter;
        }

        return end();
    }

    template <typename UnaryFn>
    iterator find_if(UnaryFn fn) {
        const_iterator citer = const_cast<const ContainerType*>(this)->find_if(fn);
        return iterator(citer.node_);
    }

    // replace_if (copy)
    //
    // Find the first member of the list which satisfies the predicate given by
    // 'fn' and replace it in the list, returning a referenced pointer to the
    // replaced element.  If no member satisfies the predicate, simply return
    // nullptr instead.
    template <typename UnaryFn>
    PtrType replace_if(UnaryFn fn, const PtrType& ptr) {
        using ConstRefType  = typename PtrTraits::ConstRefType;
        ZX_DEBUG_ASSERT(ptr != nullptr);

        auto& ptr_ns = NodeTraits::node_state(*ptr);
        ZX_DEBUG_ASSERT(!ptr_ns.InContainer());

        auto iter = begin();
        if (iter.IsValid()) {
            RawPtrType* prev_next_ptr = &head_;

            while (iter.IsValid()) {
                auto& iter_ns = NodeTraits::node_state(*iter);

                if (fn(static_cast<ConstRefType>(*iter))) {
                    PtrType new_ref = ptr;
                    RawPtrType replaced;

                    replaced       = *prev_next_ptr;
                    *prev_next_ptr = PtrTraits::Leak(new_ref);
                    ptr_ns.next_   = iter_ns.next_;
                    iter_ns.next_  = nullptr;

                    return PtrTraits::Reclaim(replaced);
                }

                prev_next_ptr = &iter_ns.next_;
                ++iter;
            }
        }

        return nullptr;
    }

    // replace_if (move)
    //
    // Same as the copy version, except that if no member satisfies the
    // predicate, the original reference is returned instead of nullptr.
    template <typename UnaryFn>
    PtrType replace_if(UnaryFn fn, PtrType&& ptr) {
        using ConstRefType  = typename PtrTraits::ConstRefType;
        ZX_DEBUG_ASSERT(ptr != nullptr);

        auto& ptr_ns = NodeTraits::node_state(*ptr);
        ZX_DEBUG_ASSERT(!ptr_ns.InContainer());

        auto iter = begin();
        if (iter.IsValid()) {
            RawPtrType* prev_next_ptr = &head_;

            while (iter.IsValid()) {
                auto& iter_ns = NodeTraits::node_state(*iter);

                if (fn(static_cast<ConstRefType>(*iter))) {
                    RawPtrType replaced;

                    replaced       = *prev_next_ptr;
                    *prev_next_ptr = PtrTraits::Leak(ptr);
                    ptr_ns.next_   = iter_ns.next_;
                    iter_ns.next_  = nullptr;

                    return PtrTraits::Reclaim(replaced);
                }

                prev_next_ptr = &iter_ns.next_;
                ++iter;
            }
        }

        return std::move(ptr);
    }

private:
    // The traits of a non-const iterator
    struct iterator_traits {
        using RefType    = typename PtrTraits::RefType;
        using RawPtrType = typename PtrTraits::RawPtrType;
    };

    // The traits of a const iterator
    struct const_iterator_traits {
        using RefType    = typename PtrTraits::ConstRefType;
        using RawPtrType = typename PtrTraits::ConstRawPtrType;
    };

    // The shared implementation of the iterator
    template <class IterTraits>
    class iterator_impl {
    public:
        iterator_impl() { }
        iterator_impl(const iterator_impl& other) { node_ = other.node_; }

        iterator_impl& operator=(const iterator_impl& other) {
            node_ =  other.node_;
            return *this;
        }

        bool IsValid() const { return (node_ != nullptr) && !internal::is_sentinel_ptr(node_); }
        bool operator==(const iterator_impl& other) const { return node_ == other.node_; }
        bool operator!=(const iterator_impl& other) const { return node_ != other.node_; }

        // Prefix
        iterator_impl& operator++() {
            if (!IsValid()) return *this;

            node_ = NodeTraits::node_state(*node_).next_;

            return *this;
        }

        // Postfix
        iterator_impl operator++(int) {
            iterator_impl ret(*this);
            ++(*this);
            return ret;
        }

        typename PtrTraits::PtrType CopyPointer() const {
            return IsValid() ? PtrTraits::Copy(node_) : nullptr;
        }

        typename IterTraits::RefType operator*() const {
            ZX_DEBUG_ASSERT(IsValid());
            return *node_;
        }

        typename IterTraits::RawPtrType operator->() const {
            ZX_DEBUG_ASSERT(IsValid());
            return node_;
        }

    private:
        friend class SinglyLinkedList<T, NodeTraits>;

        explicit iterator_impl(typename IterTraits::RawPtrType node)
            : node_(const_cast<typename PtrTraits::RawPtrType>(node)) { }

        typename PtrTraits::RawPtrType node_ = nullptr;
    };

    // The test framework's 'checker' class is our friend.
    friend CheckerType;

    // move semantics only
    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(SinglyLinkedList);

    // Note: the sentinel value we use for singly linked list is a bit different
    // from the sentinel value we use for everything else.  Instead of being the
    // this pointer of the container with the sentinel bit set, the sentinel is
    // just the bit with nothing else (aka; nullptr | kContainerSentinelBit).
    //
    // The reasons which drive this decision are as follows.
    // 1) When swapping lists, if the sentinel value was list specific, we would
    //    need to update the sentinel values at the end of each list.  This would
    //    be an O(n) operation for a SLL, whereas it is an O(1) operation for
    //    every other container.
    // 2) The sentinel value used by a list cannot simply be nullptr, or the
    //    node state for an element which is list-able would not be able to
    //    distinguish between an element which was not InContainer() and one
    //    which was InContainer, but located at the end of the list.
    constexpr RawPtrType sentinel() const {
        return internal::make_sentinel<RawPtrType>(nullptr);
    }

    // State consists of just a head pointer.
    RawPtrType head_ = sentinel();
};

// Explicit declaration of constexpr storage.
template <typename T, typename NodeTraits>
constexpr bool SinglyLinkedList<T, NodeTraits>::SupportsConstantOrderErase;
template <typename T, typename NodeTraits>
constexpr bool SinglyLinkedList<T, NodeTraits>::SupportsConstantOrderSize;
template <typename T, typename NodeTraits>
constexpr bool SinglyLinkedList<T, NodeTraits>::IsAssociative;
template <typename T, typename NodeTraits>
constexpr bool SinglyLinkedList<T, NodeTraits>::IsSequenced;

}  // namespace fbl

#endif  // FBL_INTRUSIVE_SINGLE_LIST_H_
