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

#ifndef SRC_STORAGE_LIB_BUFFER_BLOCKING_RING_BUFFER_H_
#define SRC_STORAGE_LIB_BUFFER_BLOCKING_RING_BUFFER_H_

#include <memory>
#include <mutex>
#include <utility>

#include "src/storage/lib/buffer/ring_buffer.h"

namespace storage {

class BlockingRingBufferReservation;

namespace internal {

class BlockingRingBufferImpl {
 public:
  explicit BlockingRingBufferImpl(std::unique_ptr<RingBuffer> buffer);
  BlockingRingBufferImpl(const BlockingRingBufferImpl&) = delete;
  BlockingRingBufferImpl& operator=(const BlockingRingBufferImpl&) = delete;
  BlockingRingBufferImpl(BlockingRingBufferImpl&& other) = delete;
  BlockingRingBufferImpl& operator=(BlockingRingBufferImpl&& other) = delete;
  ~BlockingRingBufferImpl() = default;

  zx_status_t Reserve(uint64_t blocks,
                      BlockingRingBufferReservation* out) __TA_NO_THREAD_SAFETY_ANALYSIS;

  // Identifies that a RingBufferReservation is going out of scope, implying that there may be
  // additional space in |buffer_| now that the reservation has reset or destroyed. Signals to
  // blocked callers of |Reserve()| that this additional space is available.
  void Wake();

  size_t capacity() const { return buffer_->capacity(); }
  uint32_t BlockSize() const { return buffer_->BlockSize(); }

 private:
  std::unique_ptr<RingBuffer> buffer_;
  std::mutex lock_;
  // Protect this condition variable with the lock itself to avoid missing notifications.
  std::condition_variable cvar_ __TA_GUARDED(lock_);
};

}  // namespace internal

// A wrapper around |RingBuffer| which enables callers to block their calling
// thread while invoking |Reserve| if no space is available. Callers are automatically
// woken up when space is made available.
//
// This class is not movable or copyable.
// This class is thread-safe.
class BlockingRingBuffer {
 public:
  BlockingRingBuffer(const BlockingRingBuffer&) = delete;
  BlockingRingBuffer& operator=(const BlockingRingBuffer&) = delete;
  BlockingRingBuffer(BlockingRingBuffer&& other) = delete;
  BlockingRingBuffer& operator=(BlockingRingBuffer&& other) = delete;
  ~BlockingRingBuffer() = default;

  static zx_status_t Create(storage::VmoidRegistry* vmoid_registry, size_t blocks,
                            uint32_t block_size, const char* label,
                            std::unique_ptr<BlockingRingBuffer>* out);

  // Same as |RingBuffer.Reserve|, but only returns ZX_ERR_NO_SPACE if |blocks| is greater
  // than capacity. In all other cases, blocks the caller until space is available.
  zx_status_t Reserve(uint64_t blocks, BlockingRingBufferReservation* out) {
    return buffer_.Reserve(blocks, out);
  }

  size_t capacity() const { return buffer_.capacity(); }
  uint32_t BlockSize() const { return buffer_.BlockSize(); }

 private:
  BlockingRingBuffer(std::unique_ptr<RingBuffer> buffer);

  internal::BlockingRingBufferImpl buffer_;
};

// A wrapper around |RingBufferReservation| which automatically notifies blocked callers of
// |BlockingRingBuffer.Reserve| when space is made available (on the destruction of an existing
// reservation).
//
// This class is movable, but not copyable.
// This class is thread-compatible.
class BlockingRingBufferReservation final : public RingBufferReservation {
 public:
  BlockingRingBufferReservation() = default;
  BlockingRingBufferReservation(internal::BlockingRingBufferImpl* buffer,
                                RingBufferReservation reservation)
      : RingBufferReservation(std::move(reservation)), buffer_(buffer) {}
  BlockingRingBufferReservation(const BlockingRingBufferReservation&) = delete;
  BlockingRingBufferReservation& operator=(const BlockingRingBufferReservation&) = delete;
  BlockingRingBufferReservation(BlockingRingBufferReservation&& other) = default;
  BlockingRingBufferReservation& operator=(BlockingRingBufferReservation&& other) = default;
  ~BlockingRingBufferReservation();

 private:
  internal::BlockingRingBufferImpl* buffer_ = nullptr;
};

}  // namespace storage

#endif  // SRC_STORAGE_LIB_BUFFER_BLOCKING_RING_BUFFER_H_
