Queue.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #ifndef QUEUE_H__
  2. #define QUEUE_H__
  3. #include <queue>
  4. #include <vector>
  5. #include <mutex>
  6. #include <thread>
  7. #include <condition_variable>
  8. #include <functional>
  9. #include <utility>
  10. namespace i2p
  11. {
  12. namespace util
  13. {
  14. template<typename Element>
  15. class Queue
  16. {
  17. public:
  18. void Put (Element e)
  19. {
  20. std::unique_lock<std::mutex> l(m_QueueMutex);
  21. m_Queue.push (std::move(e));
  22. m_NonEmpty.notify_one ();
  23. }
  24. template<template<typename, typename...>class Container, typename... R>
  25. void Put (const Container<Element, R...>& vec)
  26. {
  27. if (!vec.empty ())
  28. {
  29. std::unique_lock<std::mutex> l(m_QueueMutex);
  30. for (const auto& it: vec)
  31. m_Queue.push (std::move(it));
  32. m_NonEmpty.notify_one ();
  33. }
  34. }
  35. Element GetNext ()
  36. {
  37. std::unique_lock<std::mutex> l(m_QueueMutex);
  38. auto el = GetNonThreadSafe ();
  39. if (!el)
  40. {
  41. m_NonEmpty.wait (l);
  42. el = GetNonThreadSafe ();
  43. }
  44. return el;
  45. }
  46. Element GetNextWithTimeout (int usec)
  47. {
  48. std::unique_lock<std::mutex> l(m_QueueMutex);
  49. auto el = GetNonThreadSafe ();
  50. if (!el)
  51. {
  52. m_NonEmpty.wait_for (l, std::chrono::milliseconds (usec));
  53. el = GetNonThreadSafe ();
  54. }
  55. return el;
  56. }
  57. void Wait ()
  58. {
  59. std::unique_lock<std::mutex> l(m_QueueMutex);
  60. m_NonEmpty.wait (l);
  61. }
  62. bool Wait (int sec, int usec)
  63. {
  64. std::unique_lock<std::mutex> l(m_QueueMutex);
  65. return m_NonEmpty.wait_for (l, std::chrono::seconds (sec) + std::chrono::milliseconds (usec)) != std::cv_status::timeout;
  66. }
  67. bool IsEmpty ()
  68. {
  69. std::unique_lock<std::mutex> l(m_QueueMutex);
  70. return m_Queue.empty ();
  71. }
  72. int GetSize ()
  73. {
  74. std::unique_lock<std::mutex> l(m_QueueMutex);
  75. return m_Queue.size ();
  76. }
  77. void WakeUp () { m_NonEmpty.notify_all (); };
  78. Element Get ()
  79. {
  80. std::unique_lock<std::mutex> l(m_QueueMutex);
  81. return GetNonThreadSafe ();
  82. }
  83. Element Peek ()
  84. {
  85. std::unique_lock<std::mutex> l(m_QueueMutex);
  86. return GetNonThreadSafe (true);
  87. }
  88. private:
  89. Element GetNonThreadSafe (bool peek = false)
  90. {
  91. if (!m_Queue.empty ())
  92. {
  93. auto el = m_Queue.front ();
  94. if (!peek)
  95. m_Queue.pop ();
  96. return el;
  97. }
  98. return nullptr;
  99. }
  100. private:
  101. std::queue<Element> m_Queue;
  102. std::mutex m_QueueMutex;
  103. std::condition_variable m_NonEmpty;
  104. };
  105. }
  106. }
  107. #endif