1#include <Common/COW.h>
2#include <iostream>
3
4
5class IColumn : public COW<IColumn>
6{
7private:
8 friend class COW<IColumn>;
9
10 virtual MutablePtr clone() const = 0;
11 virtual MutablePtr deepMutate() const { return shallowMutate(); }
12
13public:
14 IColumn() = default;
15 IColumn(const IColumn &) = default;
16 virtual ~IColumn() = default;
17
18 virtual int get() const = 0;
19 virtual void set(int value) = 0;
20
21 MutablePtr mutate() const && { return deepMutate(); }
22};
23
24using ColumnPtr = IColumn::Ptr;
25using MutableColumnPtr = IColumn::MutablePtr;
26
27class ConcreteColumn : public COWHelper<IColumn, ConcreteColumn>
28{
29private:
30 friend class COWHelper<IColumn, ConcreteColumn>;
31
32 int data;
33 ConcreteColumn(int data_) : data(data_) {}
34 ConcreteColumn(const ConcreteColumn &) = default;
35
36public:
37 int get() const override { return data; }
38 void set(int value) override { data = value; }
39};
40
41class ColumnComposition : public COWHelper<IColumn, ColumnComposition>
42{
43private:
44 friend class COWHelper<IColumn, ColumnComposition>;
45
46 ConcreteColumn::WrappedPtr wrapped;
47
48 ColumnComposition(int data) : wrapped(ConcreteColumn::create(data)) {}
49 ColumnComposition(const ColumnComposition &) = default;
50
51 IColumn::MutablePtr deepMutate() const override
52 {
53 std::cerr << "Mutating\n";
54 auto res = shallowMutate();
55 res->wrapped = std::move(*wrapped).mutate();
56 return res;
57 }
58
59public:
60 int get() const override { return wrapped->get(); }
61 void set(int value) override { wrapped->set(value); }
62};
63
64
65int main(int, char **)
66{
67 ColumnPtr x = ColumnComposition::create(1);
68 ColumnPtr y = x;
69
70 std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
71 std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
72 std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n";
73
74 {
75 MutableColumnPtr mut = std::move(*y).mutate();
76 mut->set(2);
77
78 std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << ", " << mut->use_count() << "\n";
79 std::cerr << "addresses: " << x.get() << ", " << y.get() << ", " << mut.get() << "\n";
80 y = std::move(mut);
81 }
82
83 std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
84 std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
85 std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n";
86
87 x = ColumnComposition::create(0);
88
89 std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
90 std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
91 std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n";
92
93 {
94 MutableColumnPtr mut = std::move(*y).mutate();
95 mut->set(3);
96
97 std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << ", " << mut->use_count() << "\n";
98 std::cerr << "addresses: " << x.get() << ", " << y.get() << ", " << mut.get() << "\n";
99 y = std::move(mut);
100 }
101
102 std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
103 std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
104
105 return 0;
106}
107
108