--- /dev/null
+#ifndef _OS_SMART_POINTER_H
+#define _OS_SMART_POINTER_H
+
+#include <sys/cdefs.h>
+#include <os/cpp_util.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++11-extensions"
+
+#if __has_attribute(trivial_abi)
+# define OS_TRIVIAL_ABI __attribute__((trivial_abi))
+#else
+# error Smart pointers depend on trivial_abi attribute
+#endif
+
+#if !OS_HAS_RVALUE_REFERENCES
+# error Smart pointers depend on rvalue references
+#endif
+
+/* C++98 compatibility */
+#if !OS_HAS_NULLPTR && !defined(nullptr)
+# define nullptr NULL
+#endif
+
+#ifndef OSPTR_LOG
+# define OSPTR_LOG(x, ...) do {} while(0)
+#endif
+
+namespace os {
+static struct no_retain_t {} no_retain;
+
+template<class T, class Policy>
+class OS_TRIVIAL_ABI smart_ptr
+{
+ template<class U, class OtherPolicy> friend class smart_ptr;
+
+public:
+
+/*
+ * Default constructor, creates a null pointer
+ */
+ smart_ptr() : pointer(nullptr)
+ {
+ OSPTR_LOG("Default construct smart_ptr\n");
+ }
+
+#if OS_HAS_NULLPTR
+/*
+ * Construction from a nullptr
+ */
+ smart_ptr(os::nullptr_t) : pointer(nullptr)
+ {
+ OSPTR_LOG("Construct smart_ptr from null\n");
+ }
+#endif
+
+/*
+ * Construct from a raw pointer, taking a reference to the object
+ */
+ explicit smart_ptr(T *&p) : pointer(p)
+ {
+ OSPTR_LOG("Construct smart_ptr from raw %p\n", pointer);
+ if (pointer != nullptr) {
+ _retain(pointer);
+ }
+ }
+
+/*
+ * Construct from a raw pointer, without bumping the refcount
+ */
+ explicit smart_ptr(T *&p, no_retain_t) : pointer(p)
+ {
+ OSPTR_LOG("Construct smart_ptr from raw %p no retain\n", pointer);
+ }
+
+/*
+ * Copy constructor from the same smart_ptr type
+ */
+ smart_ptr(smart_ptr const &rhs) : pointer(rhs.pointer)
+ {
+ OSPTR_LOG("Copy construct smart_ptr with %p\n", rhs.pointer);
+ if (pointer != nullptr) {
+ _retain(pointer);
+ }
+ }
+
+#if !LIBKERN_NO_MEMBER_TEMPLATES
+/*
+ * Allows copy of a smart_ptr<T> from a smart_ptr<U>
+ * if U is convertible to T. For example, if T is a base class of U
+ */
+ template<class U>
+ smart_ptr(smart_ptr<U, Policy> const &rhs) : pointer(rhs.get())
+ {
+ OSPTR_LOG("Copy construct smart_ptr with compatible %p\n", rhs.pointer);
+ if (pointer != nullptr) {
+ _retain(pointer);
+ }
+ }
+#endif
+
+/*
+ * Assign to an OSPointer from a raw pointer
+ */
+ smart_ptr &
+ operator=(T *&rhs)
+ {
+ OSPTR_LOG("Assign smart_ptr with replacing %p with raw %p\n", pointer, rhs);
+ smart_ptr(rhs).swap(*this);
+ return *this;
+ }
+
+#if OS_HAS_NULLPTR
+/*
+ * Assign to an OSPointer from a null pointer
+ */
+ smart_ptr &
+ operator=(os::nullptr_t)
+ {
+ OSPTR_LOG("Assign smart_ptr to null replacing %p\n", pointer);
+ smart_ptr().swap(*this);
+ return *this;
+ }
+#endif
+
+/*
+ * Assign to a smart_ptr from a smart_ptr of the same type
+ */
+ smart_ptr &
+ operator=(smart_ptr &rhs)
+ {
+ OSPTR_LOG("Assign smart_ptr replacing %p with %p\n", pointer, rhs.pointer);
+ smart_ptr(rhs).swap(*this);
+ return *this;
+ }
+
+#if !LIBKERN_NO_MEMBER_TEMPLATES
+/*
+ * Allows assignment of a smart_ptr<T> from a smart_ptr<U>
+ * if U is convertible to T. For example, if T is a base class of U.
+ */
+ template <class U>
+ smart_ptr &
+ operator=(smart_ptr<U, Policy> const &rhs)
+ {
+ OSPTR_LOG("Assign smart_ptr to compatible replacing %p with %p\n", pointer, rhs.pointer);
+ smart_ptr(rhs.get()).swap(*this);
+ return *this;
+ }
+#endif
+
+/*
+ * Move support
+ */
+
+#if OS_HAS_RVALUE_REFERENCES
+/*
+ * Move-construct from a different smart_ptr of the same pointer type
+ */
+ smart_ptr(smart_ptr &&rhs) : pointer(rhs.pointer)
+ {
+ OSPTR_LOG("Move construct smart_ptr with %p\n", rhs.pointer);
+ rhs.pointer = nullptr;
+ }
+
+/*
+ * Move-construct from a raw pointer
+ */
+ smart_ptr(T *&&p) : pointer(p)
+ {
+ OSPTR_LOG("Move construct smart_ptr with %p\n", pointer);
+ if (pointer != nullptr) {
+ _retain(pointer);
+ }
+ p = nullptr;
+ }
+
+/*
+ * Move-construct from a raw pointer without bumping the refcount
+ */
+ smart_ptr(T *&&p, no_retain_t) : pointer(p)
+ {
+ OSPTR_LOG("Move construct smart_ptr with %p no retain\n", pointer);
+ p = nullptr;
+ }
+
+/*
+ * Move-assign to a smart_ptr from a raw pointer
+ */
+ smart_ptr &
+ operator=(T *&&rhs)
+ {
+ OSPTR_LOG("Move assign smart_ptr replacing %p with raw %p\n", pointer, rhs);
+ smart_ptr(os::move(rhs)).swap(*this);
+ rhs = nullptr;
+ return *this;
+ }
+
+/*
+ * Move-assign from a different smart_ptr of the same type
+ */
+ smart_ptr &
+ operator=(smart_ptr &&rhs)
+ {
+ OSPTR_LOG("Move assign smart_ptr replacing %p with %p\n", pointer, rhs.pointer);
+ smart_ptr(os::move(rhs)).swap(*this);
+ return *this;
+ }
+
+/*
+ * Move from a different smart_ptr with a compatible pointer type
+ */
+ template<class U>
+ smart_ptr(smart_ptr<U, Policy> &&rhs) : pointer(rhs.pointer)
+ {
+ OSPTR_LOG("Move construct smart_ptr with compatible %p\n", rhs.pointer);
+ rhs.pointer = nullptr;
+ }
+
+ template<class U>
+ smart_ptr &
+ operator=(smart_ptr<U, Policy> &&rhs)
+ {
+ OSPTR_LOG("Move assign smart_ptr replacing %p with compatible %p\n", pointer, rhs.pointer);
+ smart_ptr(os::move(rhs)).swap(*this);
+ return *this;
+ }
+#endif
+
+/*
+ * Destructor - decreases the object's reference count
+ */
+ ~smart_ptr()
+ {
+ OSPTR_LOG("Destroy smart_ptr with %p\n", pointer);
+ if (pointer) {
+ _release(pointer);
+ }
+ }
+
+/*
+ * Create a new object of type T and wrap it in a smart_ptr. The object will have
+ * a reference count of 1, so destruction of the smart_ptr will result in the
+ * object being freed if the smart_ptr wasn't copied first.
+ */
+ static inline smart_ptr
+ alloc()
+ {
+ return smart_ptr(_alloc(), no_retain);
+ }
+
+ void
+ reset()
+ {
+ smart_ptr().swap(*this);
+ }
+
+ T *
+ get() const
+ {
+ return pointer;
+ }
+
+ T **
+ get_for_out_param()
+ {
+ reset();
+ return &pointer;
+ }
+
+/*
+ * Take ownership of object from raw pointer
+ */
+ void
+ attach(T *&p)
+ {
+ OSPTR_LOG("Attach smart_ptr with %p\n", p);
+ smart_ptr(p, no_retain).swap(*this);
+ }
+
+ void
+ attach(T *&&p)
+ {
+ OSPTR_LOG("Move attach smart_ptr with %p\n", p);
+ smart_ptr(os::move(p), no_retain).swap(*this);
+ }
+
+/* Return and drop ownership of pointer with NO release() */
+ T *
+ detach()
+ {
+ OSPTR_LOG("Detach smart_ptr with %p\n", pointer);
+ T *ret = pointer;
+ pointer = nullptr;
+ return ret;
+ }
+
+ T *
+ operator->() const
+ {
+ OSPTR_LOG("Dereference smart_ptr with %p\n", pointer);
+ return pointer;
+ }
+
+ explicit
+ operator bool() const
+ {
+ return pointer != nullptr;
+ }
+
+ inline void
+ swap(smart_ptr &p)
+ {
+ T *temp = pointer;
+ pointer = p.pointer;
+ p.pointer = temp;
+ }
+
+/* swap pointers to the same type but with different policies */
+ template<class OtherPolicy>
+ void
+ swap(smart_ptr<T, OtherPolicy> &p)
+ {
+ if (p.pointer) {
+ _retain(p.pointer);
+ }
+ if (pointer) {
+ smart_ptr<T, OtherPolicy>::_retain(pointer);
+ }
+
+ T *temp = pointer;
+ pointer = p.pointer;
+ p.pointer = temp;
+
+ if (p.pointer) {
+ _release(p.pointer);
+ }
+ if (pointer) {
+ smart_ptr<T, OtherPolicy>::_release(pointer);
+ }
+ }
+
+ template<class U>
+ smart_ptr<U, Policy>
+ const_pointer_cast() const &
+ {
+ OSPTR_LOG("const_pointer_cast smart_ptr with %p\n", pointer);
+ return smart_ptr<U, Policy>(const_cast<U *>(pointer));
+ }
+
+ template <class U>
+ smart_ptr<U, Policy>
+ const_pointer_cast() &&
+ {
+ OSPTR_LOG("const_pointer_cast move smart_ptr with %p\n", pointer);
+ U *newPointer = const_cast<U *>(detach());
+ return smart_ptr<U, Policy>(os::move(newPointer), no_retain);
+ }
+
+ template <class U>
+ smart_ptr<U, Policy>
+ static_pointer_cast() const &
+ {
+ OSPTR_LOG("static_pointer_cast smart_ptr with %p\n", pointer);
+ return smart_ptr<U, Policy>(static_cast<U *>(pointer));
+ }
+
+ template <class U>
+ smart_ptr<U, Policy>
+ static_pointer_cast() &&
+ {
+ OSPTR_LOG("static_pointer_cast move smart_ptr with %p\n", pointer);
+ return smart_ptr<U, Policy>(static_cast<U *>(detach()), no_retain);
+ }
+
+ template <class U>
+ smart_ptr<U, Policy>
+ dynamic_pointer_cast() const &
+ {
+ OSPTR_LOG("dynamic_pointer_cast smart_ptr with %p\n", pointer);
+ return smart_ptr<U, Policy>(Policy::template dyn_cast<T, U>(pointer));
+ }
+
+ template <class U>
+ smart_ptr<U, Policy>
+ dynamic_pointer_cast() &&
+ {
+ OSPTR_LOG("dynamic_pointer_cast move smart_ptr with %p\n", pointer);
+ U *newPointer = Policy::template dyn_cast<T, U>(pointer);
+
+ if (newPointer != nullptr) {
+ detach();
+ } else {
+ reset();
+ }
+ return smart_ptr<U, Policy>(os::move(newPointer), no_retain);
+ }
+
+private:
+ static inline void
+ _retain(T *obj)
+ {
+ OSPTR_LOG(" %s with %p\n", __FUNCTION__, obj);
+ Policy::retain(obj);
+ }
+
+ static inline void
+ _release(T *obj)
+ {
+ OSPTR_LOG(" %s with %p\n", __FUNCTION__, obj);
+ Policy::release(obj);
+ }
+
+ static inline T *
+ _alloc()
+ {
+ OSPTR_LOG(" %s\n", __FUNCTION__);
+ return Policy::template alloc<T>();
+ }
+
+ T *pointer;
+};
+
+/*
+ * Comparison
+ */
+
+template<class T, class Policy>
+inline bool
+operator==(smart_ptr<T, Policy> const &a, smart_ptr<T, Policy> const &b)
+{
+ return a.get() == b.get();
+}
+
+template<class T, class Policy>
+inline bool
+operator!=(smart_ptr<T, Policy> const &a, smart_ptr<T, Policy> const &b)
+{
+ return a.get() != b.get();
+}
+
+template<class A, class A_policy, class B, class B_policy>
+inline bool
+operator==(smart_ptr<A, A_policy> const &a, smart_ptr<B, B_policy> const &b)
+{
+ return a.get() == b.get();
+}
+
+template<class A, class A_policy, class B, class B_policy>
+inline bool
+operator!=(smart_ptr<A, A_policy> const &a, smart_ptr<B, B_policy> const &b)
+{
+ return a.get() != b.get();
+}
+
+/*
+ * Comparison with nullptr
+ */
+
+#if OS_HAS_NULLPTR
+template<class T, class Policy>
+inline bool
+operator==(smart_ptr<T, Policy> const &p, os::nullptr_t)
+{
+ return p.get() == nullptr;
+}
+
+template<class T, class Policy> inline bool
+operator==(os::nullptr_t, smart_ptr<T, Policy> const &p)
+{
+ return p.get() == nullptr;
+}
+
+template<class T, class Policy>
+inline bool
+operator!=(smart_ptr<T, Policy> const &p, os::nullptr_t)
+{
+ return p.get() != nullptr;
+}
+
+template<class T, class Policy>
+inline bool
+operator!=(os::nullptr_t, smart_ptr<T, Policy> const &p)
+{
+ return p.get() != nullptr;
+}
+#endif
+
+/*
+ * Comparison with raw pointer
+ */
+
+template<class T, class Policy>
+inline bool
+operator==(smart_ptr<T, Policy> const &p, const os::remove_const_t<T> *other)
+{
+ return p.get() == other;
+}
+
+template<class T, class Policy>
+inline bool
+operator==(const os::remove_const_t<T> *other, smart_ptr<T, Policy> const &p)
+{
+ return other == p.get();
+}
+
+template<class T, class Policy>
+inline bool
+operator!=(smart_ptr<T, Policy> const &p, const os::remove_const_t<T> *other)
+{
+ return p.get() != other;
+}
+
+template<class T, class Policy>
+inline bool
+operator!=(const os::remove_const_t<T> *other, smart_ptr<T, Policy> const &p)
+{
+ return other != p.get();
+}
+};
+
+#pragma clang diagnostic pop
+#endif /* _OS_SMART_POINTER_H */