Click here to Skip to main content
15,881,803 members
Articles / Programming Languages / C++11

The Cow Class: A Copy-On-Write C++ Template

Rate me:
Please Sign up or sign in to vote.
4.74/5 (9 votes)
9 Feb 2020CPOL 14.2K   5   7
Copy your objects only when needed
Often you have an object that would like to be shared in read-only form across the callers, but you would like someone to create copies when it's modified. Here is a small template that will do that for you automatically.

This is part of my multithreading library at github, here.

Code

template <typename T> class cow
{
private:
    mutable std::shared_ptr<T> t;

public:

    template< typename ...Args>
    cow(Args ... args)  { t = std::make_shared<T>(args...); }

    cow(std::shared_ptr<T> t2)
    {
        t = t2;
    }

    operator const std::shared_ptr<T>() const { return t; }
    const T operator *()
    {
        return *t;
    }

    // Write
    shared_ptr<T> operator ->()
    {
        if (t.use_count() == 1)
            return t;

        std::shared_ptr<T> t2 = std::make_shared<T>(*t);
        t = t2;
        return t;
    }

    void write(std::function<void(std::shared_ptr<T> )> f)
    {
        f(operator ->());
    }

};

You have the object to be manipulated in a shared_ptr<> form. The class constructor's take either an existing pointer or they can construct a new object with the aid of variadic template functions. 

When using this class to read data, nothing happens:

 struct FOO
    {
	    int a1 = 0;
	    int a2 = 0;
    };

std::shared_ptr<FOO> x = std::make_shared<FOO>();
cow<FOO> c1(x); // gets the pointer
const FOO& j1 = *c1;
cow<FOO> c2 = c1;

All the above is serviced through  the const operator/const T* cast functions. 

When writing the data, the class duplicates the pointer before writing to it:

c1->a2 = 2; // 1 copy 

Now c1 does not anymore contain the same as the original x, which remains untouched.

c1->a4 = 2; // No copy

There should be another copy but the previous one dissappears because it had a ref of 1, so it's all optimized out.

c2.write([](std::shared_ptr<FOO> t)
 { 
    t->a1 = 10; 
    t->a2 = 20; 
 });

This would allow you to write once without creating uneccesary copies.

Have fun using it!

History

9 - 2 - 2020: First release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Greece Greece
I'm working in C++, PHP , Java, Windows, iOS, Android and Web (HTML/Javascript/CSS).

I 've a PhD in Digital Signal Processing and Artificial Intelligence and I specialize in Pro Audio and AI applications.

My home page: https://www.turbo-play.com

Comments and Discussions

 
PraiseWoah. 5ed. Pin
den2k886-Mar-20 1:04
professionalden2k886-Mar-20 1:04 
Praiseuseful lass Pin
balasubramanian.m12-Feb-20 20:52
balasubramanian.m12-Feb-20 20:52 
GeneralMy vote of 1 Pin
Member 1052334711-Feb-20 23:01
Member 1052334711-Feb-20 23:01 
GeneralRe: My vote of 1 Pin
Michael Chourdakis12-Feb-20 10:26
mvaMichael Chourdakis12-Feb-20 10:26 
Questiona question Pin
Southmountain9-Feb-20 15:08
Southmountain9-Feb-20 15:08 
AnswerVariadic Template Pin
Jon Summers10-Feb-20 4:02
Jon Summers10-Feb-20 4:02 
GeneralMy vote of 5 Pin
Shao Voon Wong9-Feb-20 12:09
mvaShao Voon Wong9-Feb-20 12:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.