From a17fbd3cb1027617aee6915d9b4a6c8640f562cc Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Thu, 5 Nov 2015 23:01:34 -0600 Subject: Implement std::shared_ptr. RTC: 124148 Change-Id: Iad6430ec701caec0d3c65de3618cc8d5605e6aa0 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/21800 Tested-by: Jenkins Server Reviewed-by: STEPHEN M. CPREK Reviewed-by: Brian Silver Reviewed-by: A. Patrick Williams III --- src/include/util/impl/shared_ptr.H | 231 +++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 src/include/util/impl/shared_ptr.H (limited to 'src/include/util/impl/shared_ptr.H') diff --git a/src/include/util/impl/shared_ptr.H b/src/include/util/impl/shared_ptr.H new file mode 100644 index 000000000..4530b5acf --- /dev/null +++ b/src/include/util/impl/shared_ptr.H @@ -0,0 +1,231 @@ +/* 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 */ +/* [+] 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 + +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(); } + + shared_ptr& operator=(const shared_ptr& r) + { + _cleanup(); + _copy(r); + + return *this; + } + template shared_ptr& operator=(const shared_ptr& r) + { + _cleanup(); + _copy(r); + + return *this; + } + + shared_ptr& operator=(const shared_ptr&& r) + { + _cleanup(); + _swap(std::move(r)); + + return *this; + } + template shared_ptr& operator=(const shared_ptr&& r) + { + _cleanup(); + _swap(std::move(r)); + + return *this; + } + + 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() + { + if (!count) return; + + if (count->decrement()) + { + delete count; + count = nullptr; + delete owner; + owner = nullptr; + pointer = nullptr; + } + } + + template void _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 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 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 -- cgit v1.2.3