bank_base.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. #pragma once
  4. #include <atomic>
  5. #include <deque>
  6. #include <utility>
  7. #include "common/common_types.h"
  8. namespace VideoCommon {
  9. class BankBase {
  10. protected:
  11. const size_t base_bank_size{};
  12. size_t bank_size{};
  13. std::atomic<size_t> references{};
  14. size_t current_slot{};
  15. public:
  16. explicit BankBase(size_t bank_size_) : base_bank_size{bank_size_}, bank_size(bank_size_) {}
  17. virtual ~BankBase() = default;
  18. virtual std::pair<bool, size_t> Reserve() {
  19. if (IsClosed()) {
  20. return {false, bank_size};
  21. }
  22. const size_t result = current_slot++;
  23. return {true, result};
  24. }
  25. virtual void Reset() {
  26. current_slot = 0;
  27. references = 0;
  28. bank_size = base_bank_size;
  29. }
  30. size_t Size() const {
  31. return bank_size;
  32. }
  33. void AddReference(size_t how_many = 1) {
  34. references.fetch_add(how_many, std::memory_order_relaxed);
  35. }
  36. void CloseReference(size_t how_many = 1) {
  37. if (how_many > references.load(std::memory_order_relaxed)) {
  38. UNREACHABLE();
  39. }
  40. references.fetch_sub(how_many, std::memory_order_relaxed);
  41. }
  42. void Close() {
  43. bank_size = current_slot;
  44. }
  45. bool IsClosed() const {
  46. return current_slot >= bank_size;
  47. }
  48. bool IsDead() const {
  49. return IsClosed() && references == 0;
  50. }
  51. };
  52. template <typename BankType>
  53. class BankPool {
  54. private:
  55. std::deque<BankType> bank_pool;
  56. std::deque<size_t> bank_indices;
  57. public:
  58. BankPool() = default;
  59. ~BankPool() = default;
  60. // Reserve a bank from the pool and return its index
  61. template <typename Func>
  62. size_t ReserveBank(Func&& builder) {
  63. if (!bank_indices.empty() && bank_pool[bank_indices.front()].IsDead()) {
  64. size_t new_index = bank_indices.front();
  65. bank_indices.pop_front();
  66. bank_pool[new_index].Reset();
  67. bank_indices.push_back(new_index);
  68. return new_index;
  69. }
  70. size_t new_index = bank_pool.size();
  71. builder(bank_pool, new_index);
  72. bank_indices.push_back(new_index);
  73. return new_index;
  74. }
  75. // Get a reference to a bank using its index
  76. BankType& GetBank(size_t index) {
  77. return bank_pool[index];
  78. }
  79. // Get the total number of banks in the pool
  80. size_t BankCount() const {
  81. return bank_pool.size();
  82. }
  83. };
  84. } // namespace VideoCommon