1 /* 2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. 3 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #ifndef VCOWPTR_H 24 #define VCOWPTR_H 25 26 #include <cassert> 27 #include <atomic> 28 29 template <typename T> 30 class vcow_ptr { 31 struct model { 32 std::atomic<std::size_t> mRef{1}; 33 34 model() = default; 35 36 template <class... Args> modelmodel37 explicit model(Args&&... args) : mValue(std::forward<Args>(args)...){} modelmodel38 explicit model(const T& other) : mValue(other){} 39 40 T mValue; 41 }; 42 model* mModel; 43 44 public: 45 using element_type = T; 46 vcow_ptr()47 vcow_ptr() 48 { 49 static model default_s; 50 mModel = &default_s; 51 ++mModel->mRef; 52 } 53 ~vcow_ptr()54 ~vcow_ptr() 55 { 56 if (mModel && (--mModel->mRef == 0)) delete mModel; 57 } 58 59 template <class... Args> vcow_ptr(Args &&...args)60 explicit vcow_ptr(Args&&... args) : mModel(new model(std::forward<Args>(args)...)) 61 { 62 } 63 vcow_ptr(const vcow_ptr & x)64 vcow_ptr(const vcow_ptr& x) noexcept : mModel(x.mModel) 65 { 66 assert(mModel); 67 ++mModel->mRef; 68 } vcow_ptr(vcow_ptr && x)69 vcow_ptr(vcow_ptr&& x) noexcept : mModel(x.mModel) 70 { 71 assert(mModel); 72 x.mModel = nullptr; 73 } 74 75 auto operator=(const vcow_ptr& x) noexcept -> vcow_ptr& 76 { 77 *this = vcow_ptr(x); 78 return *this; 79 } 80 81 auto operator=(vcow_ptr&& x) noexcept -> vcow_ptr& 82 { 83 auto tmp = std::move(x); 84 swap(*this, tmp); 85 return *this; 86 } 87 88 auto operator*() const noexcept -> const element_type& { return read(); } 89 90 auto operator-> () const noexcept -> const element_type* { return &read(); } 91 refCount()92 std::size_t refCount() const noexcept 93 { 94 assert(mModel); 95 96 return mModel->mRef; 97 } 98 unique()99 bool unique() const noexcept 100 { 101 assert(mModel); 102 103 return mModel->mRef == 1; 104 } 105 106 auto write() -> element_type& 107 { 108 if (!unique()) *this = vcow_ptr(read()); 109 110 return mModel->mValue; 111 } 112 113 auto read() const noexcept -> const element_type& 114 { 115 assert(mModel); 116 117 return mModel->mValue; 118 } 119 swap(vcow_ptr & x,vcow_ptr & y)120 friend inline void swap(vcow_ptr& x, vcow_ptr& y) noexcept 121 { 122 std::swap(x.mModel, y.mModel); 123 } 124 }; 125 126 #endif // VCOWPTR_H 127