Вдохновленный 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
, чтобы сделать этот класс полезным.
Я размышлял, должен ли я продолжать ...
Я использовал умный указатель, потому что думал, что нужно положить мьютекс прямо в контейнер, например 'std :: vector v;', не будет компилироваться согласно @ T.E.D. «Несчастный факт заключается в том, что мьютекс нельзя напрямую помещать в контейнер. Контейнеры должны иметь возможность безопасно перемещать свое содержимое, и вы не можете сделать это с помощью мьютекса. »И код, иллюстрированный @Adrian Maire. –
общий мьютекс между контейнером для меня не имеет смысла – Danh
Я не собираюсь делиться мьютексом между контейнерами.Теперь я полагаю, что T.E.D. говорил о моем использовании. –