Original Post
I really need to add some copy-on-write functionality to this class I have, and I find myself needing to do this every once in a while. So it occurred to me to make some generic COW stuff that any class can use... Anyway I was wondering if this seemed like a good approach before modifying a very large project with it. If not, what is a better approach, and why? On a side note, doing a search on "COW" in gamedev.net turns up many many posts on actual cows, like the animal. The COW base class: And an example using it: So is there anything wrong with this approach as far as anyone can tell? Or is there a better one? Thanks. Cheers -Scott [Edited by - popsoftheyear on October 22, 2008 4:21:02 PM]
template <class T> class COWBase {
void DecRef(int *Ref_, T *Data_) {
if (--(*Ref_)) return;
delete Ref_;
delete Data_;
}
void DecRef() {
DecRef(Ref, Data);
}
void IncRef() {
++(*Ref);
}
int *Ref;
protected:
COWBase() : Ref(new int(1)), Data(new T()) { }
COWBase(const T &Value) : Ref(new int(1)), Data(new T(Value)) { }
COWBase(const COWBase &Copy) : Ref(Copy.Ref), Data(Copy.Data) { IncRef(); }
COWBase &operator= (const COWBase &Copy) {
if (&Copy != this) {
DecRef();
Ref = Copy.Ref;
Data = Copy.Data;
IncRef();
}
return *this;
}
~COWBase() { DecRef(); }
// The class that inherits this will use these...
void COW() {
T *OldData = Data;
int *OldRef = Ref;
Ref = new int(1);
Data = new T(*OldData);
DecRef(OldRef, OldData);
}
// More like... overwrite than copy-on-write
void COW(const T &NewData) {
DecRef();
Ref = new int(1);
Data = new T(NewData);
}
public:
T *Data;
};
struct ImageData {
ImageData() : Width(0), Height(0) { }
ImageData(int Width_, int Height_) : Width(Width_), Height(Height_) { }
int Width, Height;
};
// You would make this publicly inherited if you wanted public access to the "Data" variable
class Image : private COWBase<ImageData> {
public:
Image() {
Data->Width = 0;
Data->Height = 0;
}
// If you define your own assignment op or copy constructor you will need to explicitly
// call the COWBase version, otherwise it will take care of it for you.
Image &operator= (const Image &Copy) {
COWBase::operator= (Copy);
return *this;
}
~Image() {
}
void SetWH(int W, int H) {
COW(ImageData(W, H));
//Data->Width = W;
//Data->Height = H;
}
};