/*************************************************************************
 * Copyright (C) [2023-2024] by Cambricon, Inc.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *************************************************************************/
#ifndef CSRC_OPS_OP_DESCRIPTOR_BASE_DESCRIPTOR_H_
#define CSRC_OPS_OP_DESCRIPTOR_BASE_DESCRIPTOR_H_

#include <deque>
#include <mutex>
#include "common/utils.h"

namespace tmo {
namespace op_desc {

static constexpr int OpCreateStage = 0;

// Add BaseDescPool is only for store different op
// desc pool in a specific container.
template <typename T>
class TMO_HIDDEN OpDescPool {
 public:
  using desc_unique_ptr = std::unique_ptr<T>;
  OpDescPool() { createMultiItems(); }

  // delete copy construct and assign construct.
  DELETE_COPY_ASSIGN_CONSTRUCT(OpDescPool);

  desc_unique_ptr get() {
    auto ptr = std::make_unique<T>();
    return desc_unique_ptr(ptr.release());
  }

  ~OpDescPool() {
    std::lock_guard<std::mutex> lock(this->mutex_);
    for (size_t i = 0; i < this->container_.size(); ++i) {
      this->container_[i].release();
    }
    this->container_.clear();
  }

 private:
  void createMultiItems() {
    for (int i = 0; i < OpCreateStage; ++i) {
      container_.emplace_back(std::make_unique<T>());
    }
  }
  // variable
  std::mutex mutex_;
  std::deque<std::unique_ptr<T>> container_;
};

}  // namespace op_desc
}  // namespace tmo

#endif  // CSRC_OPS_OP_DESCRIPTOR_BASE_DESCRIPTOR_H_
