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

#pragma once

#include <stdint.h>

#include <fbl/intrusive_double_list.h>
#include <zircon/types.h>

namespace ioscheduler {

// Operation type.
// These are used to determine respective ordering restrictions of the ops in a stream.
enum class OpType : uint32_t {
    // Operations that can optionally be reordered.

    kOpTypeUnknown = 0, // Always reordered.
    kOpTypeRead    = 1, // Read ordering.
    kOpTypeWrite   = 2, // Write order.
    kOpTypeDiscard = 3, // Write order.
    kOpTypeRename  = 4, // Read and Write order.
    kOpTypeSync    = 5, // Write order.
    kOpTypeCommand = 6, // Read and Write order.

    // Operations that cannot be reordered.

    kOpTypeOrderedUnknown = 32, // Always ordered.

    // Barrier operations.

    // Prevent reads from being reordered ahead of this barrier op. No read
    // after this barrier can be issued until this operation has completed.
    kOpTypeReadBarrier          = 64,

    // Prevent writes from being reordered after this barrier op. This
    // operation completes after all previous writes in the stream have been
    // issued.
    kOpTypeWriteBarrier         = 65,

    // Prevent writes from being reordered after this barrier op. This
    // instruction completes after all previous writes in the stream have been
    // completed.
    kOpTypeWriteCompleteBarrier = 66,

    // Combined effects of kOpTypeReadBarrier and kOpTypeWriteBarrier.
    kOpTypeFullBarrier          = 67,

    // Combined effects of kOpTypeReadBarrier and kOpTypeWriteCompleteBarrier.
    kOpTypeFullCompleteBarrier  = 68,
};

constexpr uint32_t kOpFlagComplete =    (1u << 0);
constexpr uint32_t kOpFlagGroupLeader = (1u << 8);

constexpr uint32_t kOpGroupNone = 0;

// class StreamOp.
// The library schedules operations, or ops of type StreamOp. An IO operation is a discrete
// unit of IO that is meaningful to the client. StreamOps are allocated and freed by the client.
// The Scheduler interacts with these via the SchedulerClient interface. A reference to each op
// acquired through this interface is retained until the Release() method is called.
class StreamOp : public fbl::DoublyLinkedListable<StreamOp*> {
public:
    StreamOp() {
        StreamOp(OpType::kOpTypeUnknown, 0, kOpGroupNone, 0, nullptr);
    }

    StreamOp(OpType type, uint32_t stream_id, uint32_t group_id, uint32_t group_members,
             void* cookie)
             : type_(type), stream_id_(stream_id), group_id_(group_id),
               group_members_(group_members), result_(ZX_OK), cookie_(cookie) {}

    DISALLOW_COPY_ASSIGN_AND_MOVE(StreamOp);

    OpType type() { return type_; }
    void set_ype(OpType type) { type_ = type; }

    uint32_t stream() { return stream_id_; }
    void set_stream(uint32_t stream_id) { stream_id_ = stream_id; }

    uint32_t group() { return group_id_; }
    void set_group(uint32_t gid) { group_id_ = gid; }

    uint32_t members() { return group_members_; }
    void set_members(uint32_t group_members) { group_members_ = group_members; }

    zx_status_t result() { return result_; }
    void set_result(zx_status_t result) { result_ = result; }

    void* cookie() { return cookie_; }
    void set_cookie(void* cookie) { cookie_ = cookie; }

private:
    fbl::DoublyLinkedListNodeState<StreamOp*> node_state_;

    OpType type_;               // Type of operation.
    uint32_t stream_id_;        // Stream into which this op is queued.
    uint32_t group_id_;         // Group of operations.
    uint32_t group_members_;    // Number of members in the group.
    zx_status_t result_;        // Status code of the released operation.
    void* cookie_;              // User-defined per-op cookie.
};

// UniqueOp is a wrapper around StreamOp designed to clarify the ownership of an op pointer.
// It supports move-only semantics, and must be either move()'d or release()'d before destruction.
// Since StreamOp is allocated by the client, it cannot be deleted by this wrapper. Notably,
// UniqueOp's destructor DOES NOT delete and will assert if its container is non-null.
class UniqueOp {
public:
    // Constructors
    constexpr UniqueOp() : op_(nullptr) {}
    constexpr UniqueOp(decltype(nullptr)) : UniqueOp() {}
    explicit UniqueOp(StreamOp* op) : op_(op) {}

    // Copy construction.
    UniqueOp(const UniqueOp& r) = delete;
    // Assignment
    UniqueOp& operator=(const UniqueOp& r) = delete;

    // Move construction.
    UniqueOp(UniqueOp&& r) : op_(r.op_) { r.op_ = nullptr; }

    ~UniqueOp() {
        ZX_DEBUG_ASSERT(op_ == nullptr);
    }

    // Move assignment.
    UniqueOp& operator=(UniqueOp&& r) {
        ZX_DEBUG_ASSERT(op_ == nullptr);
        op_ = r.op_;
        r.op_ = nullptr;
        return *this;
    }

    void set(StreamOp* op) {
        ZX_DEBUG_ASSERT(op_ == nullptr);
        op_ = op;
    }

    StreamOp* release() {
        StreamOp* old = op_;
        op_ = nullptr;
        return old;
    }

    StreamOp* get() const { return op_; }
    StreamOp& operator*() const { return *op_; }
    StreamOp* operator->() const { return op_; }
    explicit operator bool() const { return !!op_; }
    bool operator==(decltype(nullptr)) const  { return (op_ == nullptr); }
    bool operator!=(decltype(nullptr)) const  { return (op_ != nullptr); }
    bool operator==(const UniqueOp& other) const { return (op_ == other.op_); }
    bool operator!=(const UniqueOp& other) const { return (op_ != other.op_); }

private:
    StreamOp* op_ = nullptr;
};

} // namespace ioscheduler
