mardi 21 juillet 2015

segmentation fault at runtime using future c++

I am getting a segmentation fault on the commented instruction at the end of the code snippet during runtime. Did I use properly the future? The queue works(seems to work) fine in single thread. When I try popping the element asynchronously, I get a segmentation fault.

#include <iostream>
#include <memory>
#include <atomic>
#include <thread>
#include <future>
#include <assert.h>
using std::cout;

template<typename T>
class Queue
{ private:
    struct element
    {
      T data;
      element* previous;
      element():previous(nullptr){}
    };

    std::atomic<element*> head;
    std::atomic<element*> tail;
  public:
    Queue():head(new element), tail( head.load() ){}

    ~Queue()
    {
      while( element* const old_head = head.load() )
      {
        head.store(old_head->previous);
        delete old_head;
      }
    }

    T* pop()
    {
      element* old_head = head.load();
      if( old_head == tail.load() ){return nullptr;}

      head.store( old_head->previous );

      T* const result = new T(old_head->data);
      delete old_head;
      return result;
    }

    void push(T new_value)
    {
      element* new_data = new element;
      new_data->data = new_value;

      element* const old_tail = tail.load();
      std::swap(old_tail->data, new_value);

      element* p = new element;
      old_tail -> previous = p;
      tail.store(p);
      assert( tail.load() != head.load() );
    }

 };

int main()
{
  Queue<double> aDoubleQueue;

  assert( nullptr == aDoubleQueue.pop() );
  aDoubleQueue.push(17.0);
  assert( 17.0 == *aDoubleQueue.pop() );
  aDoubleQueue.push(17.0);
  aDoubleQueue.push(19.0);
  assert( 17.0 == *aDoubleQueue.pop() );
  assert( 19.0 == *aDoubleQueue.pop() );
  assert( nullptr == aDoubleQueue.pop() );

  aDoubleQueue.push(17.0);
  std::future< double* > popped = std::async(&Queue<double>::pop, &aDoubleQueue );
  popped.wait();  
  if( nullptr == popped.get()){ cout << "\n nullptr";}
  else
  { cout << "\n !nullptr";
    // double* a = popped.get(); // causes a segmentation fault
  }
  return 0;
}

Aucun commentaire:

Enregistrer un commentaire