|
| 1 | +#pragma once |
| 2 | + |
| 3 | +template <typename T> class cow final { |
| 4 | +public: |
| 5 | + cow() = default; |
| 6 | + |
| 7 | + template <typename... Ts> |
| 8 | + explicit cow(Ts &&... ts) : t_(new T(std::forward<Ts>(ts)...)) { |
| 9 | + t_->increment_use_count(); |
| 10 | + } |
| 11 | + |
| 12 | + cow(const cow &rhs) { |
| 13 | + if (!rhs.t_->is_unshareable()) { |
| 14 | + t_ = rhs.t_; |
| 15 | + t_->increment_use_count(); |
| 16 | + } else { |
| 17 | + t_ = new T(*t_); |
| 18 | + } |
| 19 | + } |
| 20 | + |
| 21 | + cow &operator=(const cow &rhs) { |
| 22 | + auto copy(rhs); |
| 23 | + swap(copy); |
| 24 | + return *this; |
| 25 | + } |
| 26 | + |
| 27 | + cow(cow &&rhs) { swap(rhs); } |
| 28 | + |
| 29 | + cow &operator=(cow &&rhs) { |
| 30 | + swap(rhs); |
| 31 | + return *this; |
| 32 | + } |
| 33 | + |
| 34 | + ~cow() { |
| 35 | + if (t_->is_unshareable()) { |
| 36 | + delete t_; |
| 37 | + } else { |
| 38 | + t_->decrement_use_count(); |
| 39 | + if (t_->get_use_count() == 0) { |
| 40 | + delete t_; |
| 41 | + } |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + void swap(cow &rhs) { |
| 46 | + using std::swap; |
| 47 | + swap(t_, rhs.t_); |
| 48 | + } |
| 49 | + |
| 50 | + const T &operator*() const { return *t_; } |
| 51 | + |
| 52 | + T &write(bool mark_unshareable) { |
| 53 | + if (!t_->is_unshareable() && t_->get_use_count() != 1) { |
| 54 | + |
| 55 | + } else { |
| 56 | + |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | +private: |
| 61 | + T *t_ = nullptr; |
| 62 | +}; |
| 63 | + |
| 64 | +class cow_base { |
| 65 | +public: |
| 66 | + cow_base() = default; |
| 67 | + cow_base(const cow_base &) {} |
| 68 | + cow_base &operator=(const cow_base &) {} |
| 69 | + cow_base(cow_base &&) {} |
| 70 | + cow_base &operator=(cow_base &&) {} |
| 71 | + |
| 72 | + void increment_use_count() { use_count_ += 1; } |
| 73 | + void decrement_use_count() { use_count_ -= 1; } |
| 74 | + std::size_t get_use_count() const { return use_count_; } |
| 75 | + |
| 76 | + void set_unshareable(bool u) { use_count_ = u ? unshareable : 1; } |
| 77 | + bool is_unshareable() { return use_count_ == unshareable; } |
| 78 | + |
| 79 | +protected: |
| 80 | + ~cow_base() = default; |
| 81 | + |
| 82 | +private: |
| 83 | + static const std::size_t unshareable = |
| 84 | + std::numeric_limits<std::size_t>::max(); |
| 85 | + std::size_t use_count_ = 0; |
| 86 | +}; |
0 commit comments