// Copyright 2018 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_UI_LIB_ESCHER_UTIL_OBJECT_POOL_H_
#define SRC_UI_LIB_ESCHER_UTIL_OBJECT_POOL_H_

#include <lib/syslog/cpp/macros.h>

#include <utility>
#include <vector>

namespace escher {

// Default policy for constructing and destroying ObjectPool objects.  Each
// object is constructed and destroyed one-by-one.
//
// When replacing this policy with a different one, clients are free to do
// whatever they want as long as:
// - all 4 of these methods exist, since ObjectPool calls them.
// - a constructor is called before an allocated object is returned
// - a destructor is called before the pool is cleared/destroyed.
// - there is no double construction/destruction
template <typename T>
class DefaultObjectPoolPolicy {
 public:
  // Default construction policy is to use placement-new.
  template <typename... Args>
  inline void InitializePoolObject(T* ptr, Args&&... args) {
    new (ptr) T(std::forward<Args>(args)...);
  }

  // Default destruction policy is to invoke the destructor in-place.
  inline void DestroyPoolObject(T* ptr) { ptr->~T(); }

  // Default block initialization policy is to do nothing; each object is
  // constructed one-by-one via InitializePoolObject().
  inline void InitializePoolObjectBlock(T* objects, size_t block_index, size_t num_objects) {}

  // Default block destruction policy is to do nothing; each object is destroyed
  // one-by-one via DestroyPoolObject().
  inline void DestroyPoolObjectBlock(T* objects, size_t block_index, size_t num_objects) {}
};

// An ObjectPool is an allocator for objects of type T.  The underlying memory
// is allocated in contiguous chunks.  The default policy is to construct the
// objects as they are allocated (via InitializePoolObject()) and destroy them
// as they are freed (via DestroyPoolObject()).  However, some objects such as
// Vulkan descriptor sets must be allocated in batches.  For these cases, the
// ObjectPool can be parameterized with a different PolicyT object.
template <typename T, typename PolicyT = DefaultObjectPoolPolicy<T>>
class ObjectPool {
 public:
  template <typename... Args>
  ObjectPool(Args&&... args) : policy_(std::forward<Args>(args)...) {}
  ~ObjectPool() { Clear(); }

  // Allocate an object from the pool, constructing it with the specified
  // arguments.
  template <typename... Args>
  T* Allocate(Args&&... args) {
    if (vacants_.empty()) {
      AllocateBlock();
    }
    T* ptr = vacants_.back();
    vacants_.pop_back();

    policy_.InitializePoolObject(ptr, std::forward<Args>(args)...);
    return ptr;
  }

  // Free the object, releasing it back to the pool for subsequent re-use.
  void Free(T* ptr) {
    policy_.DestroyPoolObject(ptr);
    vacants_.push_back(ptr);
  }

  // Return the number of objects that can be held in the initial block
  // allocation.
  static size_t InitialBlockSize() { return 64U; }

  // Return the number of objects that can be held in the "block_index-th"
  // allocation.
  static size_t NumObjectsInBlock(size_t block_index) { return InitialBlockSize() << block_index; }

  // Total number of objects that can be allocated from the pool without
  // changing the amount of underlying memory.
  size_t GetCapacity() const {
    size_t num_objects = 0;
    const size_t num_blocks = blocks_.size();
    for (size_t i = 0; i < num_blocks; ++i) {
      num_objects += NumObjectsInBlock(i);
    }
    return num_objects;
  }

  // Return the number of objects that have been allocated but not freed.
  size_t UnfreedObjectCount() const { return GetCapacity() - vacants_.size(); }

  // Release all pool resources.  Illegal to call while there are still unfreed
  // objects.  ObjectPool only releases memory when Clear() is called.
  void Clear() {
    FX_DCHECK(UnfreedObjectCount() == 0);

    const size_t num_blocks = blocks_.size();
    for (size_t i = 0; i < num_blocks; ++i) {
      const size_t num_objects = NumObjectsInBlock(i);
      policy_.DestroyPoolObjectBlock(blocks_[i].get(), i, num_objects);
    }

    vacants_.clear();
    blocks_.clear();
  }

  using PolicyType = PolicyT;
  const PolicyType& policy() const { return policy_; }

 private:
  // Allocate a new block of objects, and add them all to |vacants_|.  Called
  // by Allocate() when |vacants_| is empty.
  void AllocateBlock() {
    const size_t block_index = blocks_.size();
    const size_t num_objects = NumObjectsInBlock(block_index);
    T* ptr = static_cast<T*>(malloc(num_objects * sizeof(T)));
    blocks_.emplace_back(ptr);
    policy_.InitializePoolObjectBlock(ptr, block_index, num_objects);
    vacants_.reserve(vacants_.capacity() + num_objects);
    for (size_t i = 0; i < num_objects; ++i) {
      vacants_.push_back(ptr + i);
    }
  }

  struct MallocDeleter {
    void operator()(T* ptr) { ::free(ptr); }
  };

  PolicyT policy_;
  std::vector<T*> vacants_;
  std::vector<std::unique_ptr<T, MallocDeleter>> blocks_;
};

}  // namespace escher

#endif  // SRC_UI_LIB_ESCHER_UTIL_OBJECT_POOL_H_
