PeerList.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2025-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_PEERLIST_HPP
  14. #define ZT_PEERLIST_HPP
  15. #include "Constants.hpp"
  16. #include "SharedPtr.hpp"
  17. #include "Peer.hpp"
  18. namespace ZeroTier {
  19. /**
  20. * A list of peers
  21. *
  22. * This is a simple vector optimized for the case where there will almost always
  23. * be zero or one element. In that case it doesn't allocate. If there's more than
  24. * one element, it will grow to include all elements.
  25. *
  26. * It's used to return lookups in Topology where there will almost always be zero
  27. * or one peers returned but where there technically (but very rarely) can be more.
  28. */
  29. class PeerList
  30. {
  31. public:
  32. ZT_INLINE PeerList() noexcept:
  33. m_onePeer(),
  34. m_peers(&m_onePeer),
  35. m_peerCount(0)
  36. {}
  37. ZT_INLINE PeerList(const PeerList &pl)
  38. {
  39. const unsigned int pc = pl.m_peerCount;
  40. if (likely(pc <= 1)) {
  41. m_onePeer = pl.m_onePeer;
  42. m_peers = &m_onePeer;
  43. } else {
  44. m_peers = new SharedPtr<Peer>[pc];
  45. for (unsigned int i = 0;i < pc;++i)
  46. m_peers[i] = pl.m_peers[i];
  47. }
  48. m_peerCount = pc;
  49. }
  50. ZT_INLINE ~PeerList()
  51. {
  52. if (unlikely(m_peers != &m_onePeer))
  53. delete[] m_peers;
  54. }
  55. ZT_INLINE PeerList &operator=(const PeerList &pl)
  56. {
  57. if (&pl != this) {
  58. if (unlikely(m_peers != &m_onePeer))
  59. delete[] m_peers;
  60. if (likely(pl.m_peerCount <= 1)) {
  61. m_onePeer = pl.m_onePeer;
  62. m_peers = &m_onePeer;
  63. } else {
  64. m_onePeer.zero();
  65. m_peers = new SharedPtr<Peer>[pl.m_peerCount];
  66. for (unsigned int i = 0;i < pl.m_peerCount;++i)
  67. m_peers[i] = pl.m_peers[i];
  68. }
  69. m_peerCount = pl.m_peerCount;
  70. }
  71. return *this;
  72. }
  73. /**
  74. * Resize the peer list to store a given number of members
  75. *
  76. * To populate the list, this must be called first followed by each member
  77. * being set with the [] operator. List content after this call is undefined
  78. * and may contain old data if the object is being re-used.
  79. *
  80. * @param s New size of list
  81. */
  82. ZT_INLINE void resize(const unsigned int s)
  83. {
  84. if (unlikely(m_peers != &m_onePeer))
  85. delete[] m_peers;
  86. m_peerCount = s;
  87. if (likely(s <= 1)) {
  88. m_peers = &m_onePeer;
  89. } else {
  90. m_peers = new SharedPtr<Peer>[s];
  91. }
  92. }
  93. ZT_INLINE SharedPtr <Peer> &operator[](const unsigned int i) noexcept
  94. { return m_peers[i]; }
  95. ZT_INLINE const SharedPtr <Peer> &operator[](const unsigned int i) const noexcept
  96. { return m_peers[i]; }
  97. ZT_INLINE unsigned int size() const noexcept
  98. { return m_peerCount; }
  99. private:
  100. SharedPtr <Peer> m_onePeer;
  101. SharedPtr <Peer> *m_peers;
  102. unsigned int m_peerCount;
  103. };
  104. } // namespace ZeroTier
  105. #endif