idmgr.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. * refrenced from : mqtt_cpp/include/mqtt/packet_id_manager.hpp
  11. */
  12. #ifndef __ASIO2_MQTT_ID_MGR_HPP__
  13. #define __ASIO2_MQTT_ID_MGR_HPP__
  14. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #pragma once
  16. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  17. #include <cstdint>
  18. #include <set>
  19. #include <limits>
  20. #include <atomic>
  21. namespace asio2::mqtt
  22. {
  23. template<typename T>
  24. class idmgr;
  25. template<typename Integer>
  26. class idmgr<std::atomic<Integer>>
  27. {
  28. public:
  29. using id_type = std::remove_cv_t<std::remove_reference_t<Integer>>;
  30. static_assert(std::is_integral_v<id_type>);
  31. idmgr() = default;
  32. ~idmgr() = default;
  33. /**
  34. * @brief Get a new unique id
  35. */
  36. inline id_type get() noexcept
  37. {
  38. id_type r = id_.fetch_add(static_cast<id_type>(1));
  39. while (r == 0)
  40. {
  41. r = id_.fetch_add(static_cast<id_type>(1));
  42. }
  43. return r;
  44. }
  45. /**
  46. * @brief Checks whether contains the given id.
  47. */
  48. inline bool contains(id_type id) const noexcept
  49. {
  50. return (id_.load() == id);
  51. }
  52. /**
  53. * @brief Release the id.
  54. */
  55. inline void release(id_type id) noexcept
  56. {
  57. std::ignore = id;
  58. }
  59. /**
  60. * @brief Clear all ids.
  61. */
  62. inline void clear() noexcept
  63. {
  64. id_.store(0);
  65. }
  66. private:
  67. std::atomic<id_type> id_{ static_cast<id_type>(1) };
  68. };
  69. template<typename Integer>
  70. class idmgr<std::set<Integer>>
  71. {
  72. public:
  73. using id_type = std::remove_cv_t<std::remove_reference_t<Integer>>;
  74. static_assert(std::is_integral_v<id_type>);
  75. idmgr() = default;
  76. ~idmgr() = default;
  77. /**
  78. * @brief Get a new unique id, return 0 if failed.
  79. */
  80. id_type get()
  81. {
  82. if (used_.size() == (std::numeric_limits<id_type>::max)())
  83. return static_cast<id_type>(0);
  84. id_type id;
  85. if (used_.empty())
  86. {
  87. id = static_cast<id_type>(1);
  88. }
  89. else
  90. {
  91. id = *(used_.rbegin());
  92. for (;;)
  93. {
  94. id++;
  95. if (id == static_cast<id_type>(0))
  96. id++;
  97. if (used_.find(id) == used_.end())
  98. break;
  99. }
  100. }
  101. used_.emplace(id);
  102. return id;
  103. }
  104. /**
  105. * @brief Checks whether contains the given id.
  106. */
  107. bool contains(id_type id)
  108. {
  109. return (used_.find(id) != used_.end());
  110. }
  111. /**
  112. * @brief Release the id.
  113. */
  114. void release(id_type id)
  115. {
  116. used_.erase(id);
  117. }
  118. /**
  119. * @brief Clear all ids.
  120. */
  121. void clear()
  122. {
  123. used_.clear();
  124. }
  125. private:
  126. std::set<id_type> used_{};
  127. };
  128. }
  129. #endif // !__ASIO2_MQTT_ID_MGR_HPP__