queue.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #pragma once
  2. #include <atomic>
  3. #include <condition_variable>
  4. #include <functional>
  5. #include <memory>
  6. #include <mutex>
  7. #include <queue>
  8. struct AVPacket;
  9. struct AVFrame;
  10. template <class T>
  11. class Queue {
  12. protected:
  13. // Data
  14. std::queue<T> queue_;
  15. typename std::queue<T>::size_type size_max_;
  16. // Thread gubbins
  17. std::mutex mutex_;
  18. std::condition_variable full_;
  19. std::condition_variable empty_;
  20. // Exit
  21. std::atomic_bool quit_{false};
  22. std::atomic_bool finished_{false};
  23. public:
  24. Queue(const size_t size_max);
  25. bool push(T &&data);
  26. bool pop(T &data);
  27. // The queue has finished accepting input
  28. void finished();
  29. // The queue will cannot be pushed or popped
  30. void quit();
  31. };
  32. using PacketQueue =
  33. Queue<std::unique_ptr<AVPacket, std::function<void(AVPacket*)>>>;
  34. using FrameQueue =
  35. Queue<std::unique_ptr<AVFrame, std::function<void(AVFrame*)>>>;
  36. template <class T>
  37. Queue<T>::Queue(size_t size_max) :
  38. size_max_{size_max} {
  39. }
  40. template <class T>
  41. bool Queue<T>::push(T &&data) {
  42. std::unique_lock<std::mutex> lock(mutex_);
  43. while (!quit_ && !finished_) {
  44. if (queue_.size() < size_max_) {
  45. queue_.push(std::move(data));
  46. empty_.notify_all();
  47. return true;
  48. } else {
  49. full_.wait(lock);
  50. }
  51. }
  52. return false;
  53. }
  54. template <class T>
  55. bool Queue<T>::pop(T &data) {
  56. std::unique_lock<std::mutex> lock(mutex_);
  57. while (!quit_) {
  58. if (!queue_.empty()) {
  59. data = std::move(queue_.front());
  60. queue_.pop();
  61. full_.notify_all();
  62. return true;
  63. } else if (queue_.empty() && finished_) {
  64. return false;
  65. } else {
  66. empty_.wait(lock);
  67. }
  68. }
  69. return false;
  70. }
  71. template <class T>
  72. void Queue<T>::finished() {
  73. finished_ = true;
  74. empty_.notify_all();
  75. }
  76. template <class T>
  77. void Queue<T>::quit() {
  78. quit_ = true;
  79. empty_.notify_all();
  80. full_.notify_all();
  81. }