You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClientState.cs 5.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace Discord.WebSocket
  6. {
  7. internal class ClientState
  8. {
  9. private const double AverageChannelsPerGuild = 10.22; //Source: Googie2149
  10. private const double AverageUsersPerGuild = 47.78; //Source: Googie2149
  11. private const double CollectionMultiplier = 1.05; //Add 5% buffer to handle growth
  12. private readonly ConcurrentDictionary<ulong, SocketChannel> _channels;
  13. private readonly ConcurrentDictionary<ulong, SocketDMChannel> _dmChannels;
  14. private readonly ConcurrentDictionary<ulong, SocketGuild> _guilds;
  15. private readonly ConcurrentDictionary<ulong, SocketGlobalUser> _users;
  16. private readonly ConcurrentHashSet<ulong> _groupChannels;
  17. internal IReadOnlyCollection<SocketChannel> Channels => _channels.ToReadOnlyCollection();
  18. internal IReadOnlyCollection<SocketDMChannel> DMChannels => _dmChannels.ToReadOnlyCollection();
  19. internal IReadOnlyCollection<SocketGroupChannel> GroupChannels => _groupChannels.Select(x => GetChannel(x) as SocketGroupChannel).ToReadOnlyCollection(_groupChannels);
  20. internal IReadOnlyCollection<SocketGuild> Guilds => _guilds.ToReadOnlyCollection();
  21. internal IReadOnlyCollection<SocketGlobalUser> Users => _users.ToReadOnlyCollection();
  22. internal IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels =>
  23. _dmChannels.Select(x => x.Value as ISocketPrivateChannel).Concat(
  24. _groupChannels.Select(x => GetChannel(x) as ISocketPrivateChannel))
  25. .ToReadOnlyCollection(() => _dmChannels.Count + _groupChannels.Count);
  26. public ClientState(int guildCount, int dmChannelCount)
  27. {
  28. double estimatedChannelCount = guildCount * AverageChannelsPerGuild + dmChannelCount;
  29. double estimatedUsersCount = guildCount * AverageUsersPerGuild;
  30. _channels = new ConcurrentDictionary<ulong, SocketChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedChannelCount * CollectionMultiplier));
  31. _dmChannels = new ConcurrentDictionary<ulong, SocketDMChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(dmChannelCount * CollectionMultiplier));
  32. _guilds = new ConcurrentDictionary<ulong, SocketGuild>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier));
  33. _users = new ConcurrentDictionary<ulong, SocketGlobalUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier));
  34. _groupChannels = new ConcurrentHashSet<ulong>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(10 * CollectionMultiplier));
  35. }
  36. internal SocketChannel GetChannel(ulong id)
  37. {
  38. SocketChannel channel;
  39. if (_channels.TryGetValue(id, out channel))
  40. return channel;
  41. return null;
  42. }
  43. internal SocketDMChannel GetDMChannel(ulong userId)
  44. {
  45. SocketDMChannel channel;
  46. if (_dmChannels.TryGetValue(userId, out channel))
  47. return channel;
  48. return null;
  49. }
  50. internal void AddChannel(SocketChannel channel)
  51. {
  52. _channels[channel.Id] = channel;
  53. var dmChannel = channel as SocketDMChannel;
  54. if (dmChannel != null)
  55. _dmChannels[dmChannel.Recipient.Id] = dmChannel;
  56. else
  57. {
  58. var groupChannel = channel as SocketGroupChannel;
  59. if (groupChannel != null)
  60. _groupChannels.TryAdd(groupChannel.Id);
  61. }
  62. }
  63. internal SocketChannel RemoveChannel(ulong id)
  64. {
  65. SocketChannel channel;
  66. if (_channels.TryRemove(id, out channel))
  67. {
  68. var dmChannel = channel as SocketDMChannel;
  69. if (dmChannel != null)
  70. {
  71. SocketDMChannel ignored;
  72. _dmChannels.TryRemove(dmChannel.Recipient.Id, out ignored);
  73. }
  74. else
  75. {
  76. var groupChannel = channel as SocketGroupChannel;
  77. if (groupChannel != null)
  78. _groupChannels.TryRemove(id);
  79. }
  80. return channel;
  81. }
  82. return null;
  83. }
  84. internal SocketGuild GetGuild(ulong id)
  85. {
  86. SocketGuild guild;
  87. if (_guilds.TryGetValue(id, out guild))
  88. return guild;
  89. return null;
  90. }
  91. internal void AddGuild(SocketGuild guild)
  92. {
  93. _guilds[guild.Id] = guild;
  94. }
  95. internal SocketGuild RemoveGuild(ulong id)
  96. {
  97. SocketGuild guild;
  98. if (_guilds.TryRemove(id, out guild))
  99. return guild;
  100. return null;
  101. }
  102. internal SocketGlobalUser GetUser(ulong id)
  103. {
  104. SocketGlobalUser user;
  105. if (_users.TryGetValue(id, out user))
  106. return user;
  107. return null;
  108. }
  109. internal SocketGlobalUser GetOrAddUser(ulong id, Func<ulong, SocketGlobalUser> userFactory)
  110. {
  111. return _users.GetOrAdd(id, userFactory);
  112. }
  113. internal SocketGlobalUser RemoveUser(ulong id)
  114. {
  115. SocketGlobalUser user;
  116. if (_users.TryRemove(id, out user))
  117. return user;
  118. return null;
  119. }
  120. }
  121. }