.. _program_listing_file_include_opentelemetry_nostd_shared_ptr.h: Program Listing for File shared_ptr.h ===================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/opentelemetry/nostd/shared_ptr.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2020, OpenTelemetry Authors // // 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. #pragma once #ifdef HAVE_CPP_STDLIB # include "opentelemetry/std/shared_ptr.h" #else # include # include # include # include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { template class shared_ptr { public: using element_type = T; using pointer = element_type *; private: static constexpr size_t kMaxSize = 32; static constexpr size_t kAlignment = 8; struct alignas(kAlignment) PlacementBuffer { char data[kMaxSize]; }; class shared_ptr_wrapper { public: shared_ptr_wrapper() noexcept = default; shared_ptr_wrapper(std::shared_ptr &&ptr) noexcept : ptr_{std::move(ptr)} {} virtual ~shared_ptr_wrapper() {} virtual void CopyTo(PlacementBuffer &buffer) const noexcept { new (buffer.data) shared_ptr_wrapper{*this}; } virtual void MoveTo(PlacementBuffer &buffer) noexcept { new (buffer.data) shared_ptr_wrapper{std::move(this->ptr_)}; } template ::value>::type * = nullptr> void MoveTo(typename shared_ptr::PlacementBuffer &buffer) noexcept { new (buffer.data) shared_ptr_wrapper{std::move(this->ptr_)}; } virtual pointer Get() const noexcept { return ptr_.get(); } virtual void Reset() noexcept { ptr_.reset(); } private: std::shared_ptr ptr_; }; static_assert(sizeof(shared_ptr_wrapper) <= kMaxSize, "Placement buffer is too small"); static_assert(alignof(shared_ptr_wrapper) <= kAlignment, "Placement buffer not properly aligned"); public: shared_ptr() noexcept { new (buffer_.data) shared_ptr_wrapper{}; } explicit shared_ptr(pointer ptr) { std::shared_ptr ptr_(ptr); new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)}; } shared_ptr(std::shared_ptr ptr) noexcept { new (buffer_.data) shared_ptr_wrapper{std::move(ptr)}; } shared_ptr(shared_ptr &&other) noexcept { other.wrapper().MoveTo(buffer_); } template ::value>::type * = nullptr> shared_ptr(shared_ptr &&other) noexcept { other.wrapper().template MoveTo(buffer_); } shared_ptr(const shared_ptr &other) noexcept { other.wrapper().CopyTo(buffer_); } ~shared_ptr() { wrapper().~shared_ptr_wrapper(); } shared_ptr &operator=(shared_ptr &&other) noexcept { wrapper().~shared_ptr_wrapper(); other.wrapper().MoveTo(buffer_); return *this; } shared_ptr &operator=(std::nullptr_t) noexcept { wrapper().Reset(); return *this; } shared_ptr &operator=(const shared_ptr &other) noexcept { wrapper().~shared_ptr_wrapper(); other.wrapper().CopyTo(buffer_); return *this; } element_type &operator*() const noexcept { return *wrapper().Get(); } pointer operator->() const noexcept { return wrapper().Get(); } operator bool() const noexcept { return wrapper().Get() != nullptr; } pointer get() const noexcept { return wrapper().Get(); } void swap(shared_ptr &other) noexcept { shared_ptr tmp{std::move(other)}; wrapper().MoveTo(other.buffer_); tmp.wrapper().MoveTo(buffer_); } template friend class shared_ptr; private: PlacementBuffer buffer_; shared_ptr_wrapper &wrapper() noexcept { return *reinterpret_cast(buffer_.data); } const shared_ptr_wrapper &wrapper() const noexcept { return *reinterpret_cast(buffer_.data); } }; template bool operator!=(const shared_ptr &lhs, const shared_ptr &rhs) noexcept { return lhs.get() != rhs.get(); } template bool operator==(const shared_ptr &lhs, const shared_ptr &rhs) noexcept { return lhs.get() == rhs.get(); } template inline bool operator==(const shared_ptr &lhs, std::nullptr_t) noexcept { return lhs.get() == nullptr; } template inline bool operator==(std::nullptr_t, const shared_ptr &rhs) noexcept { return nullptr == rhs.get(); } template inline bool operator!=(const shared_ptr &lhs, std::nullptr_t) noexcept { return lhs.get() != nullptr; } template inline bool operator!=(std::nullptr_t, const shared_ptr &rhs) noexcept { return nullptr != rhs.get(); } } // namespace nostd OPENTELEMETRY_END_NAMESPACE #endif