/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/include/util/impl/shared_ptr.H $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ /* implied. See the License for the specific language governing */ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ #ifndef __UTIL_IMPL_SHARED_PTR_H #define __UTIL_IMPL_SHARED_PTR_H #include #include #include #include namespace std { namespace __impl { class shared_ptr_count { public: shared_ptr_count() : count(1) {}; ~shared_ptr_count() = default; void increment() { __sync_add_and_fetch(&count, 1); }; bool decrement() { return 0 == __sync_add_and_fetch(&count, -1); }; size_t use_count() { return count; }; private: size_t count; }; } template class shared_ptr { public: typedef T element_type; constexpr shared_ptr() : count(nullptr), pointer(nullptr), owner(nullptr) {}; constexpr shared_ptr(nullptr_t) : count(nullptr), pointer(nullptr), owner(nullptr) {}; template explicit shared_ptr(U* ptr) { _setup(ptr); } template shared_ptr(const shared_ptr& r, T* ptr) { _copy(r); pointer = ptr; } shared_ptr(const shared_ptr& r) { _copy(r); } template shared_ptr(const shared_ptr& r) { _copy(r); } shared_ptr(shared_ptr&& r) { _swap(std::move(r)); } template shared_ptr(shared_ptr&& r) { _swap(std::move(r)); } ~shared_ptr() { _cleanup(); } bool operator==(const shared_ptr &r) const { return (pointer == r.pointer); } bool operator!=(const shared_ptr &r) const { return (pointer != r.pointer); } shared_ptr& operator=(const shared_ptr& r) NEVER_INLINE; template shared_ptr& operator= (const shared_ptr& r) NEVER_INLINE; shared_ptr& operator=(shared_ptr&& r) NEVER_INLINE; template shared_ptr& operator= (shared_ptr&& r) NEVER_INLINE; void reset() { _cleanup(); } template void reset(U* ptr) { _cleanup(); _setup(ptr); } void swap(shared_ptr& r) { T* tmp0 = r.owner; T* tmp1 = r.pointer; __impl::shared_ptr_count* tmp2 = r.count; r.owner = owner; r.pointer = pointer; r.count = count; owner = tmp0; pointer = tmp1; count = tmp2; } T* get() const { return pointer; } T& operator*() const { return *pointer; } T* operator->() const { return pointer; } long use_count() const { if (count) return count->use_count(); return 0; } bool unique() const { return use_count() == 1; } explicit operator bool() const { return nullptr != get(); } template bool owner_before(const shared_ptr& other) const { return (owner < other.owner); } template friend class shared_ptr; private: __impl::shared_ptr_count* count; T* pointer; T* owner; template void _setup(U* ptr) { owner = pointer = static_cast(ptr); if (pointer) { count = new __impl::shared_ptr_count(); } else { count = nullptr; } } void _cleanup() NEVER_INLINE; template void _copy (const shared_ptr& r) NEVER_INLINE; template void _swap(shared_ptr&& r) { count = r.count; owner = r.owner; pointer = r.pointer; r.count = nullptr; r.owner = nullptr; r.pointer = nullptr; } }; template shared_ptr& shared_ptr::operator=(const shared_ptr& r) { _cleanup(); _copy(r); return *this; } template template shared_ptr& shared_ptr::operator= (const shared_ptr& r) { _cleanup(); _copy(r); return *this; } template shared_ptr& shared_ptr::operator=(shared_ptr&& r) { _cleanup(); _swap(std::move(r)); return *this; } template template shared_ptr& shared_ptr::operator= (shared_ptr&& r) { _cleanup(); _swap(std::move(r)); return *this; } template void shared_ptr::_cleanup() { if (!count) return; if (count->decrement()) { delete count; delete owner; } count = nullptr; owner = nullptr; pointer = nullptr; } template template void shared_ptr::_copy(const shared_ptr& r) { if (r.count) r.count->increment(); count = r.count; owner = static_cast(r.owner); pointer = static_cast(r.pointer); } template shared_ptr make_shared( Args&&... args) { return shared_ptr(new T(std::forward(args)...)); } template shared_ptr static_pointer_cast(const shared_ptr& r) { return shared_ptr(r, static_cast::element_type*>(r.get())); } template shared_ptr dynamic_pointer_cast(const shared_ptr& r) { return shared_ptr(r, dynamic_cast::element_type*>(r.get())); } template shared_ptr const_pointer_cast(const shared_ptr& r) { return shared_ptr(r, const_cast::element_type*>(r.get())); } template void swap(shared_ptr& l, shared_ptr& r) { return l.swap(r); } } #endif