Can anyone point me to a thread-safe implementation of the Copy-on-write (COW) idiom? The sample code on this site looks good -- is it thread-safe?
In case anyone is wondering what I will be using it for: I have a Foo class that has a std::map<int,double> member. Foo objects are copied very frequently in my code, but the copies rarely modify the contained map. I found that COW gives me a 22% performance boost, compared to copying the whole map contents in the Foo copy constructor, but my COW implementation crashes when multiple threads are used.
UPDATE:
Okay, here is the code, reduced to a minimal example, since you asked for it:
First, a reference-counting map:
class RcMap {
public:
typedef std::map<int,double> Container;
typedef Container::const_iterator const_iterator;
typedef Container::iterator iterator;
RcMap() : count_(1) {}
RcMap(const RcMap& other) : count_(1) {
m_ = other.Get();
}
unsigned Count() const { return count_; }
unsigned IncCount() { return ++count_; }
unsigned DecCount() {
if(count_ > 0) --count_;
return count_;
}
void insert(int i, double d) {
m_.insert(std::make_pair(i,d));
}
iterator begin() { return m_.begin(); }
iterator end() { return m_.end(); }
const_iterator begin() const { return m_.begin(); }
const_iterator end() const { return m_.end(); }
protected:
const Container& Get() const { return m_; }
private:
void operator=(const RcMap&); // disallow
Container m_;
unsigned count_;
};
And here is the class Foo that contains such a map RcMap, using a Copy-on-write mechanism:
class Foo {
public:
Foo() : m_(NULL) {}
Foo(const Foo& other) : m_(other.m_) {
if (m_) m_->IncCount();
}
Foo& operator= (const Foo& other) {
RcMap* const old = m_;
m_ = other.m_;
if(m_ != 0)
m_->IncCount();
if (old != 0 && old->DecCount() == 0) {
delete old;
}
return *this;
}
virtual ~Foo() {
if(m_ != 0 && m_->DecCount() == 0){
delete m_;
m_ = 0;
}
}
const RcMap& GetMap() const {
if(m_ == 0)
return EmptyStaticRcMap();
return *m_;
}
RcMap& GetMap() {
if(m_ == 0)
m_ = new RcMap();
if (m_->Count() > 1) {
RcMap* d = new RcMap(*m_);
m_->DecCount();
m_ = d;
}
assert(m_->Count() == 1);
return *m_;
}
static const RcMap& EmptyStaticRcMap(){
static const RcMap empty;
return empty;
}
private:
RcMap* m_;
};
I haven't yet been able to reproduce the crash using this minimal example, but in my original code it happens when I use the copy constructor or assignment operator of Foo objects in parallel. But maybe someone can spot the thread-safety bug?
COW is inherently thread-safe, since the original is essentially immutable, and only the thread that induces the copy sees the copied version in the process of being created. You only need to watch for two things:
Make sure the original doesn't get deleted by another thread while the copy is occurring. This an orthogonal problem, though (e.g., you could use thread-safe ref-counting).
Make sure all the read operations you perform while copying are thread-safe. This is rarely a problem, but sometimes a read might populate a cache, for instance.
In fact, if this assumption is violated, that's a problem with the read operation not being thread-safe, and will probably affect more code than just the COW.
RcMap's reference counts need to be made atomic in order to be thread safe. In G++ 4.1, you an use the atomic builtins to implement this.
If you're copying a mutable map (it looks like you are), then don't decrease the reference count on the original object until after the copy is complete. (Because otherwise you may wind up allowing writes to the object you're copying, thereby breaking thread safety.)
Better yet, use a fully immutable map implementation (that makes copies and updates even cheaper by using shared substructure) if you can. There's a previous question on this topic that's currently unanswered.
Related
I have a function that should return either a new vector or a reference to an existing one. I need this because in some situations the vector is already created and owned by somebody else and I want to avoid copying it.
One option is to return std::variant<std::vector<int>, std::vector<int>&>, but then the caller needs to add logic to discern what was returned. (NOT ALLOWED)
Another option is to use a wrapper class (I avoid templates for clarity):
class VectorContainer {
VectorContainer() : v(std::vector<int>()), v_ptr(nullptr) {}
VectorContainer(std::vector<int>& ref): v_ptr(&ref) {}
std::vector<int>& get() {
if (v_ptr == nullptr) return v;
return *v_ptr;
}
private:
std::vector<int> v;
std::vector<int>* v_ptr;
};
VectorContainer f();
The reference is guaranteed to outlive VectorContainer and additionally, the code that owns the vector is fixed and you cannot change it. I believe this disallows using something like a shared pointer.
Is there an existing class in the standard library? If not, how can I do this?
Your approach is close, but I would suggest having the reference always refer to the proper object:
class VectorContainer {
private:
std::vector<int> v_own;
public:
std::vector<int>& data;
VectorContainer(std::vector<int> own) : v_own{std::move(own)}, data{v_own} {}
VectorContainer(std::vector<int>& ref) : v_own{}, data{ref} {}
~VectorContainer() = default;
VectorContainer& operator=(VectorContainer const&) = delete;
VectorContainer& operator=(VectorContainer&&) = delete;
VectorContainer(VectorContainer const& from) :
v_own{from.v_own},
data{(&from.v_own == &from.data)?v_own:from.data} {
}
VectorContainer(VectorContainer&& from) :
v_own{std::move(from.v_own)},
data{(&from.v_own == &from.data)?v_own:from.data} {
}
};
Here you always access data or you could hide data and add a wrapper like this:
std::vector<int>& operator*() const {
return data;
}
// or a conversion operator to std::vector<int>&
Either way, whether or not there is indirection is hidden from the user. You always see a reference. Note that lugging around an empty vector has virtually no overhead. The initialisation is minimal.
Example:
struct Example {
std::vector<int> v{1,2,3};
VectorContainer example(bool const b) {
if (b)
return VectorContainer(std::vector{0}); // new vector
else
return VectorContainer(v); // reference to v
}
};
I am designing an input iterator type that enumerates all running processes in a system.
This is similar to an iterator I designed to enumerate modules in a process. The module iterator takes a 'process' object in the constructor, and a default constructed iterator is considered to be the off-the-end iterator.
Example:
hadesmem::ModuleIterator beg(process);
hadesmem::ModuleIterator end;
assert(beg != end);
I do not know what to do about process enumeration though, because there is no 'state' or information that needs to be given to the iterator (everything is handled internally by the iterator using the Windows API).
Example:
// This is obviously a broken design, what is the best way to distinguish between the two?
hadesmem::ProcessIterator beg;
hadesmem::ProcessIterator end;
What is the idiomatic way to deal with this situation? i.e. Where you need to distinguish between the creation of a 'new' iterator and an off-the-end iterator when nothing needs to be given to the iterator constructor.
If it's relevant, I am able to use C++11 in this library, as long as it's supported by VC11, GCC 4.7, and ICC 12.1.
Thanks.
EDIT:
To clarify, I know that it's not possible to distinguish between the two in the form I've posted above, so what I'm asking is more of a 'design' question than anything else... Maybe I'm just overlooking something obvious though (wouldn't be the first time).
What you really want to do is create a kind of ProcessList object, and base the iterators on that. I wouldn't want to be enumerating all processes or something every time I increment an iterator.
If you create a class that holds the parameters that go into the CreateToolhelp32Snapshot() representing the snapshot you're iterating over, you'll have a natural factory for the iterators. Something like this should work (I'm not on Windows, so not tested):
class Process;
class Processes {
DWORD what, who;
public:
Processes(DWORD what, DWORD who) : what(what), who(who) {}
class const_iterator {
HANDLE snapshot;
LPPROCESSENTRY32 it;
explicit const_iterator(HANDLE snapshot, LPPROCESSENTRY32 it)
: snapshot(snapshot), it(it) {}
public:
const_iterator() : snapshot(0), it(0) {}
// the two basic functions, implement iterator requirements with these:
const_iterator &advance() {
assert(snapshot);
if ( it && !Process32Next(snapshot, &it))
it = 0;
return *this;
}
const Process dereference() const {
assert(snapshot); assert(it);
return Process(it);
}
bool equals(const const_iterator & other) const {
return handle == other.handle && it == other.it;
}
};
const_iterator begin() const {
const HANDLE snapshot = CreateToolhelp32Snapshot(what, who);
if (snapshot) {
LPPROCESSENTRY32 it;
if (Process32First(snapshot, &it))
return const_iterator(snapshot, it);
}
return end();
}
const_iterator end() const {
return const_iterator(snapshot, 0);
}
};
inline bool operator==(Processes::const_iterator lhs, Processes::const_iterator rhs) {
return lhs.equals(rhs);
}
inline bool operator!=(Processes::const_iterator lhs, Processes::const_iterator rhs) {
return !operator==(lhs, rhs);
}
Usage:
int main() {
const Processes processes( TH32CS_SNAPALL, 0 );
for ( const Process & p : processes )
// ...
return 0;
}
You could use the named constructor idiom.
class ProcessIterator
private:
ProcessIterator(int) //begin iterator
ProcessIterator(char) //end iterator
//no default constructor, to prevent mistakes
public:
friend ProcessIterator begin() {return ProcessIterator(0);}
friend ProcessIterator end() {return ProcessIterator('\0');}
}
int main() {
for(auto it=ProcessIterator::begin(); it!=ProcessIterator::end(); ++it)
//stuff
}
I was implementing (for training purpose) a Bubble Sort template function:
template<typename iterInput,
typename predicate>
void BubbleSort(iterInput first1,iterInput last1,predicate func)
{
bool swapped(false);
do
{
swapped = false;
iterInput begin = first1;
iterInput beginMinus = first1;
++begin;
for (;begin != last1; begin++,beginMinus++)
{
if (func(*beginMinus,*begin) )
{
std::swap(*beginMinus,*begin);
swapped = true;
}
}
}
while(swapped);
}
When I have realized that this function will not work for class with no assignment operator, like this one (forgive me for the bad name):
class NoCopyable
{
public:
explicit NoCopyable(int value) : value_(value) {}
NoCopyable(const NoCopyable& other) : value_(other.value_) {}
~NoCopyable() {}
bool operator<(const NoCopyable& other) { return value_ < other.value_; }
void setValue(int value) { value_ = value; }
std::ostream& print(std::ostream& os) const { return os << value_; }
private:
NoCopyable& operator=(const NoCopyable& other);
int value_;
};
std::ostream& operator<<(std::ostream& os, const NoCopyable& obj)
{
return obj.print(os);
}
struct PrintNoCopyable
{
void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; }
};
The compiler raises this error Error 1 error C2248: 'NoCopyable::operator =' : cannot access private member declared in class 'NoCopyable'
So, I have slightly modify the code using instead of the std::swap function my version of the swap function, here is the code:
template<typename T1,
typename T2>
void noAssignmentSwap(T1& t1,T2& t2)
{
T1 temp(t1);
t1.~T1();
new (&t1) T1(t2);
t2.~T2();
new (&t2) T2(temp);
}
The code compiles and gives the right result. However I am not completely sure, I remember a Sutter's article that suggest you to avoid playing with the objects life time. The article just warns you by playing with fire without actually giving you any real reason. I can see problem in exception safety if the copy constructor of T1 or T2 can throw. However there is the same problem in the standard version if the assignment operator is allowed to throw.
Here the question, can you see any possible drawbacks in this version of swap?
Cheers
Apart from anything else, if a class does not have an assignment operator, its designer probably did not intend it to be swapped. If they did that, they probably disabled copy construction too, so your new swap function still won't work.
As for your assertion that Standard Library containers do not need assignment - that is true so long as you don't want to actually do anything useful with them. Does this code compile for you?
#include <vector>
using namespace std;
struct A {
private:
void operator=( const A &);
};
int main() {
vector <A> v;
v.push_back( A() );
v[0] = A(); // assignment needed here
}
I think it won't.
The difference is that when the assignment operator fails, you still have the same number of objects.
If you destroy one object and fail to create a new one, one object is lost! If it was part of a container, the container's state is probably also invalid.
You need a copy ctor instead of an assignment operator, but the two are sufficiently similar that at least in a typical case, you'll have both or you'll have neither. IOW, I don't think this generally accomplishes much.
I'd class it right along side the xor-swap trick: interesting, but generally useless.
It might be confusing to a future maintainer of the code.
Is there a way to code a write-only reference to an object? For example, suppose there was a mutex class:
template <class T> class mutex {
protected:
T _data;
public:
mutex();
void lock(); //locks the mutex
void unlock(); //unlocks the mutex
T& data(); //returns a reference to the data, or throws an exception if lock is unowned
};
Is there a way to guarantee that one couldn't do this:
mutex<type> foo;
type& ref;
foo.lock();
foo.data().do_stuff();
ref = foo.data();
foo.unlock();
//I have a unguarded reference to foo now
On the other hand, is it even worth it? I know that some people assume that programmers won't deliberately clobber the system, but then, why do we have private variables in the first place, eh? It'd be nice to just say it's "Undefined Behavior", but that just seems a little bit too insecure.
EDIT: OK, i understand the idea of a setter routine, but how would this be accomplished?
mutex<vector<int> > foo;
foo.lock();
for (int i=0; i < 10; i++) {
foo.data().push_back(i);
}
foo.unlock();
Using a set routine would require a copy for each write:
mutex<vector<int> > foo;
foo.lock();
for (int i=0; i < 10; i++) {
vector<int> copy = foo.read();
copy.push_back(i);
foo.write(copy);
}
though you could trivially optimize in this specific case, if, say, several different threads are all pushing elements, and maybe even erasing a few, this can become quite a bit of excess memory copying (i.e. one per critical section).
Yes, you can create a wrapper class that becomes invalidated when unlock is called and return the wrapper, instead of returning the reference, and you can overload its assignment operator to assign to the reference. The trick is that you need to hang onto a reference to the wrapper's internal data, so that when unlock is called, prior to releasing the lock, you invalidate any wrappers that you have created.
The common way to differentiate between getters and setters is by the const-ness of the object:
template <class T> class mutex {
public:
mutex();
void lock();
void unlock();
T& data(); // cannot be invoked for const objects
const T& data() const; // can be invoked for const objects
protected:
T _data;
};
Now, if you want to have read-only access, make the mutex const:
void read_data(const mutex< std::vector<int> >& data)
{
// only const member functions can be called here
}
You can bind a non-const object to a const reference:
// ...
mutex< std::vector<int> > data;
data.lock();
read_data(data);
data.unlock();
// ...
Note that the lock() and unlock() functions are inherently unsafe in the face of exceptions:
void f(const mutex< std::vector<int> >& data)
{
data.lock();
data.data().push_back(42); // might throw exception
data.unlock(); // will never be reached in push_back() throws
}
The usual way to solve this is RAII (resource acquisition is initialization):
template <class T> class lock;
template <class T> class mutex {
public:
mutex();
protected:
T _data;
private:
friend class lock<T>;
T& data();
void lock();
void unlock();
};
template <class T> class lock {
public:
template <class T> {
lock(mutex<T>& m) m_(m) {m_.lock();}
~lock() {m_.unlock();}
T& data() {return m_.data();}
const T& data() const {return m_.data()}
private:
mutex<T>& m_;
};
Note that I have also moved the accessor functions to the lock class, so that there is no way to access unlocked data.
You can use this like this:
void f(const mutex< std::vector<int> >& data)
{
{
lock< std::vector<int> > lock_1(data);
std::cout << lock1.data()[0]; // fine, too
lock1.data().push_back(42); // fine
}
{
const lock< std::vector<int> > lock_2(data); // note the const
std::cout << lock1.data()[0]; // fine, too
// lock1.data().push_back(42); // compiler error
}
}
You could encapsulate the data as private and expose a write routine. Within that routine you could lock your mutex, giving you similar behavior to what you are shooting for.
You can use a member function as the following:
void set_data(const T& var);
This is how write-only access is applied in C++.
No. There is no way to guarantee anything about reading and writing memory in unsafe languages like C++, where all the memory is treated like one big array.
[Edit] Not sure why all the downvotes; this is correct and relevant.
In safe languages, such as Java or C#, you can certainly guarantee that, for instance, properly-implemented immutable types will stay immutable. Such a guarantee can never be made in C++.
The fear is not so much malicious users as it is accidental invalid-pointers; I have worked on C++ projects where immutable types have been mutated due to an invalid pointer in completely unrelated code, causing bugs that are extremely difficult to track down. This guarantee - which only safe languages can make - is both useful and important.
I need a shared_ptr like object, but which automatically creates a real object when I try to access its members.
For example, I have:
class Box
{
public:
unsigned int width;
unsigned int height;
Box(): width(50), height(100){}
};
std::vector< lazy<Box> > boxes;
boxes.resize(100);
// at this point boxes contain no any real Box object.
// But when I try to access box number 50, for example,
// it will be created.
std::cout << boxes[49].width;
// now vector contains one real box and 99 lazy boxes.
Is there some implementation, or I should to write my own?
It's very little effort to roll your own.
template<typename T>
class lazy {
public:
lazy() : child(0) {}
~lazy() { delete child; }
T &operator*() {
if (!child) child = new T;
return *child;
}
// might dereference NULL pointer if unset...
// but if this is const, what else can be done?
const T &operator*() const { return *child; }
T *operator->() { return &**this; }
const T *operator->() const { return &**this; }
private:
T *child;
};
// ...
cout << boxes[49]->width;
Using boost::optional, you can have such a thing:
// 100 lazy BigStuffs
std::vector< boost::optional<BigStuff> > v(100);
v[49] = some_big_stuff;
Will construct 100 lazy's and assign one real some_big_stuff to v[49]. boost::optional will use no heap memory, but use placement-new to create objects in a stack-allocated buffer. I would create a wrapper around boost::optional like this:
template<typename T>
struct LazyPtr {
T& operator*() { if(!opt) opt = T(); return *opt; }
T const& operator*() const { return *opt; }
T* operator->() { if(!opt) opt = T(); return &*opt; }
T const* operator->() const { return &*opt; }
private:
boost::optional<T> opt;
};
This now uses boost::optional for doing stuffs. It ought to support in-place construction like this one (example on op*):
T& operator*() { if(!opt) opt = boost::in_place(); return *opt; }
Which would not require any copy-ing. However, the current boost-manual does not include that assignment operator overload. The source does, however. I'm not sure whether this is just a defect in the manual or whether its documentation is intentionally left out. So i would use the safer way using a copy assignment using T().
I've never heard of such a thing, but then again there are lots of things I've never heard of. How would the "lazy pointer" put useful data into the instances of the underlying class?
Are you sure that a sparse matrix isn't what you're really looking for?
So far as I know, there's no existing implementation of this sort of thing. It wouldn't be hard to create one though.