actorid.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #pragma once
  2. #include "defs.h"
  3. #include <util/stream/output.h> // for IOutputStream
  4. #include <util/generic/hash.h>
  5. namespace NActors {
  6. // used as global uniq address of actor
  7. // also could be used to transport service id (12 byte strings placed in hint-localid)
  8. // highest 1 bit of node - mark of service id
  9. // next 11 bits of node-id - pool id
  10. // next 20 bits - node id itself
  11. struct TActorId {
  12. static constexpr ui32 MaxServiceIDLength = 12;
  13. static constexpr ui32 MaxPoolID = 0x000007FF;
  14. static constexpr ui32 MaxNodeId = 0x000FFFFF;
  15. static constexpr ui32 PoolIndexShift = 20;
  16. static constexpr ui32 PoolIndexMask = MaxPoolID << PoolIndexShift;
  17. static constexpr ui32 ServiceMask = 0x80000000;
  18. static constexpr ui32 NodeIdMask = MaxNodeId;
  19. private:
  20. union {
  21. struct {
  22. ui64 LocalId;
  23. ui32 Hint;
  24. ui32 NodeId;
  25. } N;
  26. struct {
  27. ui64 X1;
  28. ui64 X2;
  29. } X;
  30. ui8 Buf[16];
  31. } Raw;
  32. public:
  33. TActorId() noexcept {
  34. Raw.X.X1 = 0;
  35. Raw.X.X2 = 0;
  36. }
  37. explicit TActorId(ui32 nodeId, ui32 poolId, ui64 localId, ui32 hint) noexcept {
  38. Y_VERIFY_DEBUG(poolId <= MaxPoolID);
  39. Raw.N.LocalId = localId;
  40. Raw.N.Hint = hint;
  41. Raw.N.NodeId = nodeId | (poolId << PoolIndexShift);
  42. }
  43. explicit TActorId(ui32 nodeId, const TStringBuf& x) noexcept {
  44. Y_ABORT_UNLESS(x.size() <= MaxServiceIDLength, "service id is too long");
  45. Raw.N.LocalId = 0;
  46. Raw.N.Hint = 0;
  47. Raw.N.NodeId = nodeId | ServiceMask;
  48. memcpy(Raw.Buf, x.data(), x.size());
  49. }
  50. explicit TActorId(ui64 x1, ui64 x2) noexcept {
  51. Raw.X.X1 = x1;
  52. Raw.X.X2 = x2;
  53. }
  54. explicit operator bool() const noexcept {
  55. return Raw.X.X1 != 0 || Raw.X.X2 != 0;
  56. }
  57. ui64 LocalId() const noexcept {
  58. return Raw.N.LocalId;
  59. }
  60. ui32 Hint() const noexcept {
  61. return Raw.N.Hint;
  62. }
  63. ui32 NodeId() const noexcept {
  64. return Raw.N.NodeId & NodeIdMask;
  65. }
  66. bool IsService() const noexcept {
  67. return (Raw.N.NodeId & ServiceMask);
  68. }
  69. TStringBuf ServiceId() const noexcept {
  70. Y_VERIFY_DEBUG(IsService());
  71. return TStringBuf((const char*)Raw.Buf, MaxServiceIDLength);
  72. }
  73. static ui32 PoolIndex(ui32 nodeid) noexcept {
  74. return ((nodeid & PoolIndexMask) >> PoolIndexShift);
  75. }
  76. ui32 PoolID() const noexcept {
  77. return PoolIndex(Raw.N.NodeId);
  78. }
  79. ui64 RawX1() const noexcept {
  80. return Raw.X.X1;
  81. }
  82. ui64 RawX2() const noexcept {
  83. return Raw.X.X2;
  84. }
  85. bool operator<(const TActorId& x) const noexcept {
  86. const ui64 s1 = Raw.X.X1;
  87. const ui64 s2 = Raw.X.X2;
  88. const ui64 x1 = x.Raw.X.X1;
  89. const ui64 x2 = x.Raw.X.X2;
  90. return (s1 != x1) ? (s1 < x1) : (s2 < x2);
  91. }
  92. bool operator!=(const TActorId& x) const noexcept {
  93. return Raw.X.X1 != x.Raw.X.X1 || Raw.X.X2 != x.Raw.X.X2;
  94. }
  95. bool operator==(const TActorId& x) const noexcept {
  96. return !(x != *this);
  97. }
  98. ui64 Hash() const noexcept {
  99. const ui32* x = (const ui32*)Raw.Buf;
  100. const ui64 x1 = x[0] * 0x001DFF3D8DC48F5Dull;
  101. const ui64 x2 = x[1] * 0x179CA10C9242235Dull;
  102. const ui64 x3 = x[2] * 0x0F530CAD458B0FB1ull;
  103. const ui64 x4 = x[3] * 0xB5026F5AA96619E9ull;
  104. const ui64 z1 = x1 + x2;
  105. const ui64 z2 = x3 + x4;
  106. const ui64 sum = 0x5851F42D4C957F2D + z1 + z2;
  107. return (sum >> 32) | (sum << 32);
  108. }
  109. ui32 Hash32() const noexcept {
  110. const ui32* x = (const ui32*)Raw.Buf;
  111. const ui64 x1 = x[0] * 0x001DFF3D8DC48F5Dull;
  112. const ui64 x2 = x[1] * 0x179CA10C9242235Dull;
  113. const ui64 x3 = x[2] * 0x0F530CAD458B0FB1ull;
  114. const ui64 x4 = x[3] * 0xB5026F5AA96619E9ull;
  115. const ui64 z1 = x1 + x2;
  116. const ui64 z2 = x3 + x4;
  117. const ui64 sum = 0x5851F42D4C957F2D + z1 + z2;
  118. return sum >> 32;
  119. }
  120. struct THash {
  121. ui64 operator()(const TActorId& actorId) const noexcept {
  122. return actorId.Hash();
  123. }
  124. };
  125. struct THash32 {
  126. ui64 operator()(const TActorId& actorId) const noexcept {
  127. return actorId.Hash();
  128. }
  129. };
  130. struct TOrderedCmp {
  131. bool operator()(const TActorId &left, const TActorId &right) const noexcept {
  132. Y_VERIFY_DEBUG(!left.IsService() && !right.IsService(), "ordered compare works for plain actorids only");
  133. const ui32 n1 = left.NodeId();
  134. const ui32 n2 = right.NodeId();
  135. return (n1 != n2) ? (n1 < n2) : left.LocalId() < right.LocalId();
  136. }
  137. };
  138. TString ToString() const;
  139. void Out(IOutputStream& o) const;
  140. bool Parse(const char* buf, ui32 sz);
  141. };
  142. static_assert(sizeof(TActorId) == 16, "expect sizeof(TActorId) == 16");
  143. static_assert(MaxPools < TActorId::MaxPoolID); // current implementation of united pool has limit MaxPools on pool id
  144. }
  145. template <>
  146. inline void Out<NActors::TActorId>(IOutputStream& o, const NActors::TActorId& x) {
  147. return x.Out(o);
  148. }
  149. template <>
  150. struct THash<NActors::TActorId> {
  151. inline ui64 operator()(const NActors::TActorId& x) const {
  152. return x.Hash();
  153. }
  154. };
  155. template<> struct std::hash<NActors::TActorId> : THash<NActors::TActorId> {};