2016-11-28 29 views
-1

Вдохновленный this code, я пытаюсь реализовать Reader/Writer vector, который может безопасно звонить push_back() одновременно по темам.Сделайте безопасный документ Reader/Writer

После этого класса я мог бы создать метод erase(), позвонив по номеру std::swap(), который меняет целевой объект и последний элемент, а затем удаляет последний элемент в коллекции. Таким образом, я предполагаю, что производительность должна быть справедливой, поскольку удаление элемента в середине коллекции не вызывает перемещение всех элементов, следующих за целевым элементом в коллекции.

К сожалению, следующий код:

#include <vector> 
#include <boost/thread/shared_mutex.hpp> //shared_mutex 
#include <memory> //shared_ptr 
#include <utility> //swap() 

template <class T> 
class readers_writer_vector 
{ 
    std::shared_ptr<boost::shared_mutex> pm; 
    std::vector<T> data; 
public: 
    readers_writer_vector() : 
     pm(new std::shared_ptr<boost::shared_mutex>){} 
    void push_back(const T& item){ 
     boost::unique_lock<boost::shared_mutex> lock(*pm); //wrong design 
     data.push_back(item); 
    } 
}; 

int main() 
{ 
    readers_writer_vector<int> db; 
    db.push_back(1); 
    return 0; 
} 

дает следующие ошибки компиляции:

/usr/include/c++/4.9/bits/shared_ptr_base.h:871:39: error: cannot convert ‘std::shared_ptr<boost::shared_mutex>*’ to ‘boost::shared_mutex*’ in initialization 
     : _M_ptr(__p), _M_refcount(__p) 

// g++ -std=c++11 -Iboost -lboost t.cpp 

Как это исправить? Пожалуйста!

EDIT:

Задача реализации гораздо сложнее, чем я думал. Это не заняло слишком много времени, прежде чем я столкнулся с проблемой, о которой @Danh предупредил. Теперь я получаю эти ошибки:

t.cpp:28:8: note: ‘i::i(const i&)’ is implicitly deleted because the default definition would be ill-formed: 
struct i { 
     ^
t.cpp:28:8: error: use of deleted function  ‘readers_writer_vector<T>::readers_writer_vector(const readers_writer_vector<T>&) [with T = z]’ 
t.cpp:13:2: note: declared here 
    readers_writer_vector(readers_writer_vector const&) = delete; 

с этой версией:

template <class T> 
class readers_writer_vector 
{ 
    booster::shared_mutex m; 
    std::vector<T> data; 
public: 
    readers_writer_vector() = default; 
    readers_writer_vector(readers_writer_vector const&) = delete; 
    void push_back(const T& item){ 
     booster::unique_lock<booster::shared_mutex> lock(m); 
     data.push_back(item); 
    } 
    typename std::vector<T>::reference back(){ 
     return data.back(); 
    } 
}; 

struct z { 
    int zipcode; 
    std::string address; 
}; 

struct i { 
    int id; 
    readers_writer_vector<z> zipcodes; 
}; 

int main() 
{ 
    readers_writer_vector<i> db; 
    db.push_back(i()); 
    auto &ii=db.back(); 
    ii.id=1; 
    ii.zipcodes.push_back(z()); 

    auto &zz=ii.zipcodes.back(); 
    zz.zipcode=11; 
    zz.address="aa"; 

    return 0; 
} 

В дополнении к фиксации существующих ошибок, я должен реализовать итераторы для readers_writer_vector, чтобы сделать этот класс полезным.

Я размышлял, должен ли я продолжать ...

ответ

3

Поскольку pm является std::shared_ptr<boost::shared_mutex> не std::shared_ptr<boost::shared_mutex>*. Вы можете использовать это:

readers_writer_vector() : 
    pm(std::make_shared<boost::shared_mutex>()){} 

Во всяком случае, зачем вам нужен указатель/умный указатель? Это лучше подходит:

template <class T> 
class readers_writer_vector 
{ 
    boost::shared_mutex pm; 
    std::vector<T> data; 
public: 
    void push_back(const T& item){ 
     boost::unique_lock<boost::shared_mutex> lock(pm); 
     data.push_back(item); 
    } 
}; 
+0

Я использовал умный указатель, потому что думал, что нужно положить мьютекс прямо в контейнер, например 'std :: vector v;', не будет компилироваться согласно @ T.E.D. «Несчастный факт заключается в том, что мьютекс нельзя напрямую помещать в контейнер. Контейнеры должны иметь возможность безопасно перемещать свое содержимое, и вы не можете сделать это с помощью мьютекса. »И код, иллюстрированный @Adrian Maire. –

+0

общий мьютекс между контейнером для меня не имеет смысла – Danh

+0

Я не собираюсь делиться мьютексом между контейнерами.Теперь я полагаю, что T.E.D. говорил о моем использовании. –

1

Инициализация pm неправильного типа; у вас есть фактически

std::shared_ptr<> pm = new std::shared_ptr<>; 

Вы не можете назначить общий указатель указателя на общий указатель.

Заменить Инициализатор с

pm(new boost::shared_mutex) 

или сделать мьютекс элемент напрямую, а не использовать общий указатель.