How to implement try_pop() method in queue in c++?

Viewed 241

Below is queue example in "C++ concurrency in action 2nd". This example is single threaded queue, which will be modified to explain thread safe.

template<typename T>
class queue {
 private:
  struct node {
    T data;
    std::unique_ptr<node> next;
    node(T data_) : data(std::move(data_)) {}
  };
  std::unique_ptr<node> head;
  node* tail;
 public:
  queue() : tail(nullptr) {};
  queue(const queue& other) = delete;
  queue& operator=(const queue& other) = delete;

  std::shared_ptr<T> try_pop() {
    if (!head) return std::shared_ptr<T>();
    std::shared_ptr<T> const res(std::make_shared<T>(std::move(head->data)));
    std::unique_ptr<node> const old_head = std::move(head);
    head = std::move(old_head->next);
    if(!head) tail = nullptr;
    return res;
  }

  void push(T new_value) {
    std::unique_ptr<node> p(new node(std::move(new_value)));
    node* const new_tail = p.get();
    if(tail) {
      tail->next = std::move(p);
    } else {
      head = std::move(p);
    }
    tail = new_tail;
  }
};

I can understand this queue works fine, but the way try_pop() is implemented seems to be weird. Is it better way to do like below ?

  std::shared_ptr<T> try_pop() {
    if (!head) return std::shared_ptr<T>();
    std::shared_ptr<T> const res(std::make_shared<T>(std::move(head->data)));

//    std::unique_ptr<node> const old_head = std::move(head);
//    head = std::move(old_head->next);

    head = std::move(head->next);

    if(!head) tail = nullptr;
    return res;
  }

Why head should be copied to old_head on this? Is there any reason I missed?

0 Answers
Related