MessageQueue.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. class MessageBase
  7. {
  8. private:
  9. unsigned int m_time;
  10. unsigned int m_id;
  11. static unsigned int s_messageCount;
  12. MessageBase(const MessageBase&);
  13. public:
  14. MessageBase(unsigned int time) : m_time(time), m_id(s_messageCount++) { }
  15. virtual ~MessageBase() { }
  16. void BeginTimer() { m_time += GetTickCount(); };
  17. unsigned int GetTime() { return m_time; };
  18. unsigned int GetId() { return m_id; };
  19. virtual HRESULT Call(LPCWSTR fileName) = 0;
  20. struct Comparator
  21. {
  22. bool operator()(MessageBase const* const& lhs, MessageBase const* const& rhs) const
  23. {
  24. return lhs->m_time > rhs->m_time;
  25. }
  26. };
  27. };
  28. class MessageQueue
  29. {
  30. std::multimap<unsigned int, MessageBase*> m_queue;
  31. public:
  32. void Push(MessageBase *message)
  33. {
  34. message->BeginTimer();
  35. m_queue.insert(std::make_pair(message->GetTime(), message));
  36. }
  37. MessageBase* PopAndWait()
  38. {
  39. Assert(!m_queue.empty());
  40. auto it = m_queue.begin();
  41. MessageBase *tmp = it->second;
  42. m_queue.erase(it);
  43. int waitTime = tmp->GetTime() - GetTickCount();
  44. if(waitTime > 0)
  45. {
  46. Sleep(waitTime);
  47. }
  48. return tmp;
  49. }
  50. bool IsEmpty()
  51. {
  52. return m_queue.empty();
  53. }
  54. void RemoveById(unsigned int id)
  55. {
  56. // Search for the message with the correct id, and delete it. Can be updated
  57. // to a hash to improve speed, if necessary.
  58. for(auto it = m_queue.begin(); it != m_queue.end(); ++it)
  59. {
  60. MessageBase *msg = it->second;
  61. if(msg->GetId() == id)
  62. {
  63. m_queue.erase(it);
  64. delete msg;
  65. break;
  66. }
  67. }
  68. }
  69. HRESULT ProcessAll(LPCWSTR fileName)
  70. {
  71. while(!IsEmpty())
  72. {
  73. MessageBase *msg = PopAndWait();
  74. // Omit checking return value for async function, since it shouldn't affect others.
  75. msg->Call(fileName);
  76. delete msg;
  77. }
  78. return S_OK;
  79. }
  80. };
  81. //
  82. // A custom message helper class to assist defining messages handled by callback functions.
  83. //
  84. template <class Func, class CustomBase>
  85. class CustomMessage : public CustomBase
  86. {
  87. private:
  88. Func m_func;
  89. public:
  90. CustomMessage(unsigned int time, const typename CustomBase::CustomArgType& customArg, const Func& func) :
  91. CustomBase(time, customArg), m_func(func)
  92. {}
  93. virtual HRESULT Call(LPCWSTR fileName) override
  94. {
  95. return m_func(*this);
  96. }
  97. };