| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 | // Copyright The OpenTelemetry Authors// SPDX-License-Identifier: Apache-2.0#pragma once#if defined(OPENTELEMETRY_STL_VERSION)#  if OPENTELEMETRY_STL_VERSION >= 2011#    include "opentelemetry/std/shared_ptr.h"#    define OPENTELEMETRY_HAVE_STD_SHARED_PTR#  endif#endif#if !defined(OPENTELEMETRY_HAVE_STD_SHARED_PTR)#  include <cstdlib>#  include <memory>#  include <utility>#  include "opentelemetry/nostd/unique_ptr.h"#  include "opentelemetry/version.h"OPENTELEMETRY_BEGIN_NAMESPACEnamespace nostd{/** * Provide a type-erased version of std::shared_ptr that has ABI stability. */template <class T>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<T> &&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 <class U,              typename std::enable_if<std::is_convertible<pointer, U *>::value>::type * = nullptr>    void MoveTo(typename shared_ptr<U>::PlacementBuffer &buffer) noexcept    {      using other_shared_ptr_wrapper = typename shared_ptr<U>::shared_ptr_wrapper;      new (buffer.data) other_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<T> 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<T> ptr_(ptr);    new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)};  }  shared_ptr(std::shared_ptr<T> ptr) noexcept  {    new (buffer_.data) shared_ptr_wrapper{std::move(ptr)};  }  shared_ptr(shared_ptr &&other) noexcept { other.wrapper().MoveTo(buffer_); }  template <class U,            typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr>  shared_ptr(shared_ptr<U> &&other) noexcept  {    other.wrapper().template MoveTo<T>(buffer_);  }  shared_ptr(const shared_ptr &other) noexcept { other.wrapper().CopyTo(buffer_); }  shared_ptr(unique_ptr<T> &&other) noexcept  {    std::shared_ptr<T> ptr_(other.release());    new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)};  }  shared_ptr(std::unique_ptr<T> &&other) noexcept  {    std::shared_ptr<T> ptr_(other.release());    new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)};  }  ~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<T> &other) noexcept  {    shared_ptr<T> tmp{std::move(other)};    wrapper().MoveTo(other.buffer_);    tmp.wrapper().MoveTo(buffer_);  }  template <typename U>  friend class shared_ptr;private:  PlacementBuffer buffer_;  shared_ptr_wrapper &wrapper() noexcept  {    return *reinterpret_cast<shared_ptr_wrapper *>(buffer_.data);  }  const shared_ptr_wrapper &wrapper() const noexcept  {    return *reinterpret_cast<const shared_ptr_wrapper *>(buffer_.data);  }};template <class T1, class T2>bool operator!=(const shared_ptr<T1> &lhs, const shared_ptr<T2> &rhs) noexcept{  return lhs.get() != rhs.get();}template <class T1, class T2>bool operator==(const shared_ptr<T1> &lhs, const shared_ptr<T2> &rhs) noexcept{  return lhs.get() == rhs.get();}template <class T>inline bool operator==(const shared_ptr<T> &lhs, std::nullptr_t) noexcept{  return lhs.get() == nullptr;}template <class T>inline bool operator==(std::nullptr_t, const shared_ptr<T> &rhs) noexcept{  return nullptr == rhs.get();}template <class T>inline bool operator!=(const shared_ptr<T> &lhs, std::nullptr_t) noexcept{  return lhs.get() != nullptr;}template <class T>inline bool operator!=(std::nullptr_t, const shared_ptr<T> &rhs) noexcept{  return nullptr != rhs.get();}}  // namespace nostdOPENTELEMETRY_END_NAMESPACE#endif /* OPENTELEMETRY_HAVE_STD_SHARED_PTR */
 |