LockFreeQueue.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #pragma once
  2. #include <iostream>
  3. #include <atomic>
  4. #include <vector>
  5. using namespace std;
  6. template<typename T>
  7. struct Node
  8. {
  9. T data; //数据
  10. atomic_bool hasData; //是否有数据
  11. };
  12. template<typename T>
  13. class LockFreeQueue
  14. {
  15. public:
  16. LockFreeQueue(int size = 1024)
  17. :msg(size)
  18. {
  19. r_index = 0;
  20. w_index = 0;
  21. };
  22. bool enqueue(T& value); // 入队列
  23. bool dequeue(T& value); // 出队列
  24. private:
  25. vector<Node<T>> msg; // 消息队列
  26. atomic<size_t> r_index; // 读索引(不考虑溢出情况)
  27. atomic<size_t> w_index; // 写索引(不考虑溢出情况)
  28. };
  29. template<typename T>
  30. bool LockFreeQueue<T>::enqueue(T& value)
  31. {
  32. size_t l_w_index = w_index.load(std::memory_order_relaxed);
  33. Node<T>* node = NULL;
  34. // CAS比较是否和预期一致,一致则对写索引递增1,不一致则重试
  35. do
  36. {
  37. //队列是否已满
  38. if (l_w_index >= r_index.load(std::memory_order_relaxed) + msg.size()) {
  39. return false;
  40. }
  41. // 判断是否有数据
  42. size_t index = l_w_index % msg.size();
  43. node = &msg[index];
  44. if (node->hasData.load(std::memory_order_relaxed))
  45. {
  46. return false;
  47. }
  48. } while (!w_index.compare_exchange_weak(l_w_index, l_w_index + 1, std::memory_order_relaxed));
  49. //写数据
  50. node->data = std::move(value);//左值转右值,避免拷贝带来的浪费
  51. node->hasData.store(true);
  52. return true;
  53. }
  54. template<typename T>
  55. bool LockFreeQueue<T>::dequeue(T& value)
  56. {
  57. size_t l_r_index = r_index.load(std::memory_order_relaxed);;
  58. Node<T>* node = NULL;
  59. // CAS比较是否和预期一致,一致则对读索引递增1,不一致则重试
  60. do
  61. {
  62. //队列是否为空
  63. if (l_r_index > w_index.load(std::memory_order_relaxed))
  64. {
  65. return false;
  66. }
  67. // 判断是否有数据
  68. size_t index = l_r_index % msg.size();
  69. node = &msg[index];
  70. if (!node->hasData.load(std::memory_order_relaxed))
  71. {
  72. return false;
  73. }
  74. } while (!r_index.compare_exchange_weak(l_r_index, l_r_index + 1, std::memory_order_relaxed));
  75. //读数据
  76. value = std::move(node->data);
  77. node->hasData.store(false);
  78. return true;
  79. }