diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2015-11-05 23:01:34 -0600 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2015-12-11 15:30:27 -0600 |
commit | a17fbd3cb1027617aee6915d9b4a6c8640f562cc (patch) | |
tree | a9497e7c674656dcf087bd0b3986c2ce04bb6d18 /src/include/util | |
parent | 9a54b1a965309773bac3bd3ea915e20151397503 (diff) | |
download | talos-hostboot-a17fbd3cb1027617aee6915d9b4a6c8640f562cc.tar.gz talos-hostboot-a17fbd3cb1027617aee6915d9b4a6c8640f562cc.zip |
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 <smcprek@us.ibm.com>
Reviewed-by: Brian Silver <bsilver@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/include/util')
-rw-r--r-- | src/include/util/impl/shared_ptr.H | 231 |
1 files changed, 231 insertions, 0 deletions
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 <cstddef> +#include <utility> +#include <stdint.h> + +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 <typename T> + 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<typename U> explicit shared_ptr(U* ptr) + { + _setup(ptr); + } + + template<typename U> shared_ptr(const shared_ptr<U>& r, T* ptr) + { _copy(r); pointer = ptr; } + + shared_ptr(const shared_ptr& r) { _copy(r); } + template<typename U> shared_ptr(const shared_ptr<U>& r) + { _copy(r); } + + shared_ptr(shared_ptr&& r) { _swap(std::move(r)); } + template<typename U> shared_ptr(shared_ptr<U>&& r) + { _swap(std::move(r)); } + + ~shared_ptr() { _cleanup(); } + + shared_ptr& operator=(const shared_ptr& r) + { + _cleanup(); + _copy(r); + + return *this; + } + template<typename U> shared_ptr& operator=(const shared_ptr<U>& r) + { + _cleanup(); + _copy(r); + + return *this; + } + + shared_ptr& operator=(const shared_ptr&& r) + { + _cleanup(); + _swap(std::move(r)); + + return *this; + } + template<typename U> shared_ptr& operator=(const shared_ptr<U>&& r) + { + _cleanup(); + _swap(std::move(r)); + + return *this; + } + + void reset() { _cleanup(); } + template<typename U> 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<typename U> + bool owner_before(const shared_ptr<U>& other) const + { + return (owner < other.owner); + } + + template <typename U> friend class shared_ptr; + + private: + __impl::shared_ptr_count* count; + T* pointer; + T* owner; + + template<typename U> void _setup(U* ptr) + { + owner = pointer = static_cast<T*>(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<typename U> void _copy(const shared_ptr<U>& r) + { + if (r.count) r.count->increment(); + count = r.count; + owner = static_cast<T*>(r.owner); + pointer = static_cast<T*>(r.pointer); + } + + template<typename U> void _swap(shared_ptr<U>&& r) + { + count = r.count; + owner = r.owner; + pointer = r.pointer; + r.count = nullptr; + r.owner = nullptr; + r.pointer = nullptr; + } + }; + + template <typename T, typename... Args> + shared_ptr<T> make_shared( Args&&... args) + { + return shared_ptr<T>(new T(std::forward<Args>(args)...)); + } + + template <typename T, typename U> + shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) + { + return shared_ptr<T>(r, + static_cast<typename shared_ptr<T>::element_type*>(r.get())); + } + + template <typename T, typename U> + shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) + { + return shared_ptr<T>(r, + dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())); + } + + template <typename T, typename U> + shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) + { + return shared_ptr<T>(r, + const_cast<typename shared_ptr<T>::element_type*>(r.get())); + } + + template <typename T> + void swap(shared_ptr<T>& l, shared_ptr<T>& r) { return l.swap(r); } +} + +#endif |