I have a question regarding the term thread-safety. Let me give an example:
#include
#include
/// A thread-safe vector
class Th
What you have provided is thread-safe. However the problem with this is that you can't add methods that allow access to the elements without loosing thread safety. Also this kind of thread-safety is very inefficient. Sometimes you want to iterate over the whole container and sometimes you want to add many elements one after another.
As an alternative you can put the responsibility for locking on the caller. This is much more efficient.
/// A lockable vector
class LockableVector
{
public:
using mutex_type = std::shared_timed_mutex;
using read_lock = std::shared_lock;
using write_lock = std::unique_lock;
// default ctor
LockableVector() {}
// move-ctor
LockableVector(LockableVector&& lv)
: LockableVector(std::move(lv), lv.lock_for_writing()) {}
// move-assign
LockableVector& operator=(LockableVector&& lv)
{
lv.lock_for_writing();
v = std::move(lv.v);
return *this;
}
read_lock lock_for_reading() { return read_lock(m); }
write_lock lock_for_writing() { return write_lock(m); }
// add double to vector
void add(double d) {
v.emplace_back(d);
}
// return length of vector
int length() {
return v.size();
}
// iteration
auto begin() { return v.begin(); }
auto end() { return v.end(); }
private:
// hidden, locked move-ctor
LockableVector(LockableVector&& lv, write_lock)
: v(std::move(lv.v)) {}
mutex_type m;
std::vector v;
};
int main()
{
LockableVector v;
// add lots of elements
{ /// create a scope for the lock
auto lock = v.lock_for_writing();
for(int i = 0; i < 10; ++i)
v.add(i);
}
// print elements
{ /// create a scope for the lock
auto lock = v.lock_for_reading();
std::cout << std::fixed << std::setprecision(3);
for(auto d: v)
std::cout << d << '\n';
}
}
Also by having both read and write locks you increase efficiency because you can have multiple readers at the same time when no thread is currently writing.