thread_safe_queue.puml 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. @startuml
  2. skinparam classAttributeIconSize 0
  3. title Thread_safe_queue 安全线程队列
  4. note left of Thread_safe_queue
  5. /*
  6. * (1)这个实现要求构建工具支持C++11的atomic mutex condition_veriable功能。这是C++11的基础特性,一般2011年以后的C++编译器都能支持。 例如,visual studio 2012以上。
  7. (2)这个类的实现中有两处使用了unique_lock而不是lock_guard,这是data_cond.wait所需要的,unique_lock是lock_guard的增强版。
  8. 通过std::move的使用(前提是我们实现的类型T定义了移动构造函数和移动赋值函数),能利用移动语义带来的性能优势。
  9. 使用shared_ptr<T>返回元素,用户无需释放元素的内存。
  10. 原文链接:https://blog.csdn.net/weixin_41855721/article/details/81703818
  11. 增加了一些功能函数,
  12. 补充了注释说明
  13. termination_queue
  14. // 在退出状态下,所有的功能函数不可用,返回false或者null。
  15. // wait_and_pop不会阻塞。让其直接通过,通过后直接return,不允许做其他的。
  16. pop系列函数
  17. //(1)没有调用termination时,每调用一次出队一个元素,直到队列为空本方法阻塞线程。
  18. //(2)在调用了termination后,本方法永不阻塞,如果原本已经处于阻塞状态,解除阻塞状态。
  19. //(3)返回true时,value值有效。返回false时,value值无效。调用了termination且队列为空时返回false.
  20. 注注注注注意了:模板类不支持分离编译。 模板类的实现必须放在头文件
  21. 为了方便阅读和编程规范,依然将声明和实现分开,就像是把cpp文件的代码复制到h文件的尾部。
  22. 如果将实现放到cpp里面,那么就要为cpp文件加 ifndef define endif 防止重定义。
  23. 然后在调用方include包含cpp文件,但是这样不好。
  24. * */
  25. end note
  26. class Thread_safe_queue << template<class T> >>
  27. {
  28. ==public:==
  29. Thread_safe_queue();
  30. Thread_safe_queue(const Thread_safe_queue& other);
  31. ~Thread_safe_queue();
  32. ..
  33. //(1)没有调用termination时,每调用一次出队一个元素,直到队列为空本方法阻塞线程。
  34. //(2)在调用了termination后,本方法永不阻塞,如果原本已经处于阻塞状态,解除阻塞状态。
  35. //(3)返回true时,value值有效。返回false时,value值无效。调用了termination且队列为空时返回false.
  36. //等待并弹出数据,成功弹出则返回true
  37. // 队列为空则无限等待,termination终止队列,则返回false
  38. bool wait_and_pop(T& value);
  39. ..
  40. //尝试弹出数据,成功弹出则返回true
  41. //队列为空 或者 termination终止队列,返回false
  42. bool try_pop(T& value);
  43. ..
  44. //等待并弹出数据,成功弹出则返回true
  45. // 队列为空则无限等待,termination终止队列,则返回false
  46. std::shared_ptr<T> wait_and_pop();
  47. ..
  48. //尝试弹出数据,成功弹出则返回true
  49. //队列为空 或者 termination终止队列,返回false
  50. std::shared_ptr<T> try_pop();
  51. ..
  52. //插入一项,并唤醒一个线程,
  53. //如果成功插入,则返回true, 失败则返回false
  54. //注:只能唤醒一个线程,防止多线程误判empty()
  55. bool push(T new_value);
  56. ..
  57. //清除队列,只是将队列的实例抛出。T是实例内存,系统自动回收的。
  58. bool clear();
  59. ..
  60. //清除队列,抛出之后还要delete指针。T是动态内存,需要手动回收的。
  61. bool clear_and_delete();
  62. ==public:==
  63. //判空
  64. bool empty();
  65. ..
  66. //获取队列大小
  67. size_t size();
  68. ..
  69. //设置队列为退出状态。并唤醒所有的线程,使其通过wait
  70. // 在退出状态下,所有的功能函数不可用,必须直接返回false或者null。
  71. // wait_and_pop不会阻塞。让其直接通过,通过后直接return,不允许做其他的。
  72. void termination_queue();
  73. ..
  74. //唤醒队列,恢复所有的功能函数。wait_and_pop会继续阻塞。
  75. void wake_queue();
  76. ..
  77. //获取退出状态
  78. bool get_termination_flag();
  79. ..
  80. //判断是否可以直接通过wait, m_data_queue不为空或者m_termination终止时都可以通过等待。
  81. bool is_pass();
  82. ==protected:==
  83. std::mutex m_mutex; //队列的锁
  84. std::queue<std::shared_ptr<T>> m_data_queue; //队列数据,使用智能指针shared_ptr
  85. std::condition_variable m_data_cond; //条件变量
  86. std::atomic<bool> m_termination_flag; //终止标志位
  87. ==private:==
  88. }
  89. @enduml