TimerComponent.cs 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using System.Collections.Generic;
  2. using Common.Base;
  3. using Common.Helper;
  4. using MongoDB.Bson;
  5. namespace Model
  6. {
  7. public class TimerComponent: Component<World>, IUpdate
  8. {
  9. private class Timer
  10. {
  11. public ObjectId Id { get; set; }
  12. public long Time { get; set; }
  13. public int CallbackId { get; set; }
  14. public Env Env { get; set; }
  15. }
  16. private readonly Dictionary<ObjectId, Timer> timers = new Dictionary<ObjectId, Timer>();
  17. /// <summary>
  18. /// key: time, value: timer id
  19. /// </summary>
  20. private readonly MultiMap<long, ObjectId> timeId = new MultiMap<long, ObjectId>();
  21. private readonly Queue<long> timeoutTimer = new Queue<long>();
  22. public ObjectId Add(long time, int callbackId, Env env)
  23. {
  24. Timer timer = new Timer
  25. {
  26. Id = ObjectId.GenerateNewId(),
  27. Time = time,
  28. CallbackId = callbackId,
  29. Env = env
  30. };
  31. this.timers[timer.Id] = timer;
  32. this.timeId.Add(timer.Time, timer.Id);
  33. return timer.Id;
  34. }
  35. public void Remove(ObjectId id)
  36. {
  37. Timer timer;
  38. if (!this.timers.TryGetValue(id, out timer))
  39. {
  40. return;
  41. }
  42. this.timeId.Remove(timer.Time, timer.Id);
  43. }
  44. public void Update()
  45. {
  46. long timeNow = TimeHelper.Now();
  47. foreach (long time in this.timeId.Keys)
  48. {
  49. if (time > timeNow)
  50. {
  51. break;
  52. }
  53. this.timeoutTimer.Enqueue(time);
  54. }
  55. while (this.timeoutTimer.Count > 0)
  56. {
  57. long key = this.timeoutTimer.Dequeue();
  58. List<ObjectId> timeOutId = this.timeId[key];
  59. foreach (ObjectId id in timeOutId)
  60. {
  61. Timer timer;
  62. if (!this.timers.TryGetValue(id, out timer))
  63. {
  64. continue;
  65. }
  66. this.Remove(id);
  67. World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(timer.CallbackId, timer.Env);
  68. }
  69. }
  70. }
  71. }
  72. }