fork(1) download
  1. #include <iostream>
  2. #include <memory>
  3. #include <mutex>
  4. #include <condition_variable>
  5. #include <atomic>
  6.  
  7.  
  8. typedef ::std::unique_lock<::std::mutex> TLock;
  9.  
  10. using namespace std;
  11. template<typename T>
  12. class TQueueElement
  13. {
  14. public:
  15. T _data;
  16. std::shared_ptr<TQueueElement<T> > _prev;
  17. mutable ::std::mutex _lockElem;
  18.  
  19. public:
  20. TQueueElement(T data):_data(data),_prev(nullptr){};
  21. virtual ~TQueueElement(){};
  22.  
  23.  
  24. };
  25.  
  26. template<typename T>
  27. class TQueue
  28. {
  29. private:
  30. mutable ::std::mutex _lockHead;
  31. mutable ::std::mutex _lockTail;
  32. ::std::condition_variable _pushToQueue;
  33. std::atomic<bool> _isEmpty;
  34. std::shared_ptr<TQueueElement<T> > _tail;
  35. std::shared_ptr<TQueueElement<T> > _head;
  36.  
  37. public:
  38. TQueue():_lockHead(),_isEmpty(true){};
  39. virtual ~TQueue(){};
  40.  
  41. ///получаем элемент из очереди
  42. T pop()
  43. {
  44. TLock lock(_lockTail);//блокируем все получения из очереди
  45. if (_tail==nullptr)
  46. {
  47. TLock lockHead(_lockHead);
  48. if (_tail==nullptr)
  49. {
  50. _isEmpty=true;
  51. lockHead.unlock();
  52. _pushToQueue.wait(lock,[this](){return !_isEmpty;});//если очередь пуста ожидаем пока в ней чтото появиться
  53. }
  54. }
  55. {
  56. TLock lockTail(_tail->_lockElem); //блокируем последний элемент в очереди возможно к нему попробуют обратиться во время запихивания в очередь
  57. auto data=_tail->_data;
  58. _tail=_tail->_prev;
  59. return data;
  60. }
  61.  
  62. }
  63.  
  64. void push(T data)
  65. {
  66. auto el=std::shared_ptr<TQueueElement<T> >(new TQueueElement<T>(data));//заранее создаем элемент очереди
  67. TLock lock(_lockHead);
  68. if (_isEmpty)//если очередь пуста говорим что наш элемент пока первый и последний
  69. {
  70. {
  71. TLock lock(_lockTail);
  72. _head=el;
  73. _tail=el;
  74. _isEmpty=false;
  75. }
  76. _pushToQueue.notify_all();
  77. }else//если очередь не пуста
  78. {
  79. {
  80. TLock lockHead(_head->_lockElem); //блокируем голову от возможного обращения с хвоста
  81. _head->_prev=el; //выставляем ссылку на новую голову у старой
  82. }
  83. _head=el;//выставляем новую голову
  84. }
  85. }
  86.  
  87.  
  88.  
  89. };
  90.  
  91.  
  92. int main() {
  93. TQueue<int> q;
  94. q.push(7);
  95. q.pop();
  96. // your code goes here
  97. return 0;
  98. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
Standard output is empty