/*
 * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved.
 *
 * This source code and/or documentation ("Licensed Deliverables") are
 * subject to NVIDIA intellectual property rights under U.S. and
 * international Copyright laws.
 */

#pragma once

#include <cuda_runtime.h>

namespace cugraph::ops::cuda {

/**
 * @brief A simple wrapper class for `cudaStream_t`
 */
class stream {
 public:
  /** Creates a new cuda stream and owns it's lifetime */
  stream();

  /**
   * @brief This will just compose the cuda stream but not own it
   *
   * @note we don't mark this as explicit since we want to allow implicitly
   *       converting `nullptr` or any stream to a non-owned stream
   *
   * @param[in] st cuda stream
   */
  stream(cudaStream_t st);  // NOLINT(google-explicit-constructor)

  /**
   * @brief This will just compose the cuda stream but not own it
   *
   * @param[in] other cuda stream
   */
  stream(const stream& other);

  /** this destroys our stream if owned and composes other, but not own it */
  stream& operator=(const stream& other);

  /** destroy the stream if it is owned by this class */
  ~stream();

  /** Synchronize on the underlying cuda stream */
  void sync();

  /** returns the underlying raw cuda stream */
  cudaStream_t operator()() const { return st_; }

 private:
  /** whether the underlying cuda stream's lifetime is owned by this class */
  bool is_owned_{false};
  /** the cuda stream */
  cudaStream_t st_{nullptr};
};  // class stream

}  // namespace cugraph::ops::cuda
