]> git.sesse.net Git - casparcg/blobdiff - common/memory/safe_ptr.h
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / common / memory / safe_ptr.h
index 88c184af3f6f796c2678fa48851a6b7eb9e3282a..32016f37e6508b4fe051c0984bc013e9727e4179 100644 (file)
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
 #pragma once\r
 \r
 #include <memory>\r
+#include <stdexcept>\r
 #include <type_traits>\r
-#include <exception>\r
 \r
-namespace caspar {\r
-       \r
+namespace caspar\r
+{\r
+\r
 template<typename T>\r
 class safe_ptr\r
-{      \r
-       std::shared_ptr<T> impl_;\r
-       template <typename> friend class safe_ptr;\r
+{   \r
+    template <typename> friend class safe_ptr;\r
 public:\r
-       typedef T element_type;\r
-       \r
-       safe_ptr() : impl_(std::make_shared<T>()){}     \r
-       \r
-       safe_ptr(const safe_ptr& other) : impl_(other.impl_){}  // noexcept\r
-       safe_ptr(safe_ptr&& other) : impl_(std::move(other.impl_)){}\r
-\r
-       template<typename U>\r
-       safe_ptr(const safe_ptr<U>& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) : impl_(other.impl_){}  // noexcept\r
-               \r
-       template<typename U>    \r
-       safe_ptr(const U& impl, typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, void>::type* = 0)\r
-               : impl_(std::make_shared<U>(impl)) {}\r
-       \r
-       template<typename U, typename D>                \r
-       safe_ptr(const U& impl, D dtor, typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, void>::type* = 0)\r
-               : impl_(new U(impl), dtor) {}\r
-\r
-       template<typename U>    \r
-       safe_ptr(U&& impl, typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, void>::type* = 0)\r
-               : impl_(std::make_shared<U>(std::forward<U>(impl))) {}\r
-\r
-       template<typename U, typename D>        \r
-       safe_ptr(U&& impl, D dtor, typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, void>::type* = 0)\r
-               : impl_(new U(std::forward<U>(impl)), dtor) {}\r
-                       \r
-       template<typename U>    \r
-       explicit safe_ptr(const std::shared_ptr<U>& impl, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) : impl_(impl)\r
-       {\r
-               if(!impl_)\r
-                       throw std::invalid_argument("impl");\r
-       }\r
-       \r
-       template<typename U>    \r
-       explicit safe_ptr(std::shared_ptr<U>&& impl, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) : impl_(std::move(impl))\r
-       {\r
-               if(!impl_)\r
-                       throw std::invalid_argument("impl");\r
-       }\r
-\r
-       template<typename U>    \r
-       explicit safe_ptr(U* impl, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) : impl_(impl)\r
-       {\r
-               if(!impl_)\r
-                       throw std::invalid_argument("impl");\r
-       }\r
-\r
-       template<typename U, typename D>        \r
-       explicit safe_ptr(U* impl, D dtor, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) : impl_(impl, dtor)\r
-       {\r
-               if(!impl_)\r
-                       throw std::invalid_argument("impl");\r
-       }\r
-\r
-       template<typename U>\r
-       typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, safe_ptr&>::type\r
-       operator=(const safe_ptr<U>& other)\r
-       {\r
-               safe_ptr(other).swap(*this);\r
-               return *this;\r
-       }\r
-\r
-       template<typename U>\r
-       typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, safe_ptr&>::type\r
-       operator=(safe_ptr<U>&& other)\r
-       {\r
-               safe_ptr(std::move(other)).swap(*this);\r
-               return *this;\r
-       }\r
-\r
-       template <typename U>\r
-       typename std::enable_if<std::is_convertible<typename std::add_pointer<U>::type, T*>::value, safe_ptr&>::type\r
-       operator=(U&& impl)\r
-       {\r
-               safe_ptr temp(std::forward<T>(impl));\r
-               temp.swap(*this);\r
-               return *this;\r
-       }\r
-\r
-       T& operator*() const // noexcept\r
-       {\r
-               return *impl_.get();\r
-       } \r
-\r
-       T* operator->() const // noexcept\r
-       {\r
-               return impl_.get();\r
-       } \r
-\r
-       T* get() const // noexcept\r
-       {\r
-               return impl_.get();\r
-       }  \r
-\r
-       bool unique() const { return impl_.unique();}  // noexcept\r
-\r
-       long use_count() const { return impl_.use_count();}  // noexcept\r
-                               \r
-       void swap(safe_ptr& other) { impl_.swap(other.impl_); }  // noexcept\r
-       \r
-       operator const std::shared_ptr<T>&() const { return impl_;}  // noexcept\r
-\r
-       template<class U>\r
-       bool owner_before(const safe_ptr& ptr){ return impl_.owner_before(ptr.impl_); }  // noexcept\r
-\r
-       template<class U>\r
-       bool owner_before(const std::shared_ptr<U>& ptr){ return impl_.owner_before(ptr); }  // noexcept\r
-       \r
-       template<class D, class U> \r
-       D* get_deleter(safe_ptr<U> const& ptr) { return impl_.get_deleter(); }  // noexcept\r
+    typedef T  element_type;\r
+\r
+    safe_ptr(); // will construct new T object using make_safe<T>()\r
+\r
+    safe_ptr(const safe_ptr& other) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    template<typename U>\r
+    safe_ptr(const safe_ptr<U>& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    safe_ptr(safe_ptr&& other) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    template<typename U>\r
+    safe_ptr(safe_ptr<U>&& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(other.p_)\r
+    {\r
+    }\r
+\r
+    template<typename U>    \r
+    safe_ptr(U&& v, typename std::enable_if<std::is_convertible<U*, T*>::value, void>::type* = 0)\r
+        : p_(std::make_shared<U>(std::forward<U>(v))) \r
+    {\r
+    }\r
+\r
+    template<typename U, typename D>    \r
+    safe_ptr(U&& v, D d, typename std::enable_if<std::is_convertible<U*, T*>::value, void>::type* = 0)\r
+        : p_(new U(std::forward<U>(v)), d) \r
+    {\r
+    }\r
+\r
+    template<typename U>    \r
+    explicit safe_ptr(const std::shared_ptr<U>& p, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(p)\r
+    {\r
+        if(!p)\r
+            throw std::invalid_argument("p");\r
+    }\r
+\r
+    template<typename U>    \r
+    explicit safe_ptr(std::shared_ptr<U>&& p, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(std::move(p))\r
+    {\r
+        if(!p_)\r
+            throw std::invalid_argument("p");\r
+    }\r
+\r
+    template<typename U>    \r
+    explicit safe_ptr(U* p, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(p)\r
+    {\r
+        if(!p)\r
+            throw std::invalid_argument("p");\r
+    }\r
+\r
+    template<typename U, typename D>    \r
+    explicit safe_ptr(U* p, D d, typename std::enable_if<std::is_convertible<U*, T*>::value, void*>::type = 0) \r
+        : p_(p, d)\r
+    {\r
+        if(!p)\r
+            throw std::invalid_argument("p");\r
+    }\r
+    \r
+    template<typename U>\r
+    typename std::enable_if<std::is_convertible<U*, T*>::value, safe_ptr&>::type\r
+    operator=(const safe_ptr<U>& other)\r
+    {\r
+        safe_ptr(other).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+    template<typename U>\r
+    typename std::enable_if<std::is_convertible<U*, T*>::value, safe_ptr&>::type\r
+    operator=(safe_ptr<U>&& other)\r
+    {\r
+        safe_ptr<T>(std::move(other)).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+    template <typename U>\r
+    typename std::enable_if<std::is_convertible<U*, T*>::value, safe_ptr&>::type\r
+    operator=(U&& v)\r
+    {\r
+        safe_ptr(std::forward<U>(v)).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+    T& operator*() const \r
+    { \r
+        return *p_.get();\r
+    }\r
+\r
+    T* operator->() const \r
+    { \r
+        return p_.get();\r
+    }\r
+\r
+    T* get() const \r
+    { \r
+        return p_.get();\r
+    }\r
+\r
+    bool unique() const \r
+    { \r
+        return p_.unique();\r
+    }\r
+\r
+    long use_count() const \r
+    {\r
+        return p_.use_count();\r
+    }\r
+\r
+    void swap(safe_ptr& other) \r
+    { \r
+        p_.swap(other.p_); \r
+    } \r
+\r
+    operator std::shared_ptr<T>() const \r
+    { \r
+        return p_;\r
+    }\r
+\r
+    operator std::weak_ptr<T>() const \r
+    { \r
+        return std::weak_ptr<T>(p_);\r
+    }\r
+    \r
+    template<class U>\r
+    bool owner_before(const safe_ptr& ptr)\r
+    { \r
+        return p_.owner_before(ptr.p_); \r
+    }\r
+\r
+    template<class U>\r
+    bool owner_before(const std::shared_ptr<U>& ptr)\r
+    { \r
+        return p_.owner_before(ptr); \r
+    }\r
+\r
+    template<class D, class U> \r
+    D* get_deleter(safe_ptr<U> const& ptr) \r
+    { \r
+        return p_.get_deleter(); \r
+    }\r
+\r
+private:    \r
+    std::shared_ptr<T> p_;\r
 };\r
 \r
 template<class T, class U>\r
-bool operator==(const std::shared_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator==(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator==(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator==(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator!=(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator!=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator!=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
 {\r
-       return a.get() == b.get();\r
+    return a.get() != b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator==(const safe_ptr<T>& a, const std::shared_ptr<U>& b)  // noexcept\r
+bool operator<(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
 {\r
-       return a.get() == b.get();\r
+    return a.get() < b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator==(const safe_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator<(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
 {\r
-       return a.get() == b.get();\r
+    return a.get() < b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator!=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator<(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
 {\r
-       return a.get() != b.get();\r
+    return a.get() < b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator!=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)  // noexcept\r
+bool operator>(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
 {\r
-       return a.get() != b.get();\r
+    return a.get() > b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator!=(const safe_ptr<T>& a, const safe_ptr<U>& b) // noexcept\r
+bool operator>(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
 {\r
-       return a.get() != b.get();\r
+    return a.get() > b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator<(const safe_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator>(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
 {\r
-       return a.get() < b.get();\r
+    return a.get() > b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator>(const safe_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator>=(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
 {\r
-       return a.get() > b.get();\r
+    return a.get() >= b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator>=(const safe_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator>=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
 {\r
-       return a.get() >= b.get();\r
+    return a.get() >= b.get();\r
 }\r
 \r
 template<class T, class U>\r
-bool operator<=(const safe_ptr<T>& a, const safe_ptr<U>& b)  // noexcept\r
+bool operator>=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
 {\r
-       return a.get() <= b.get();\r
+    return a.get() >= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<=(const safe_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() <= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<=(const std::shared_ptr<T>& a, const safe_ptr<U>& b)\r
+{\r
+    return a.get() <= b.get();\r
+}\r
+\r
+template<class T, class U>\r
+bool operator<=(const safe_ptr<T>& a, const std::shared_ptr<U>& b)\r
+{\r
+    return a.get() <= b.get();\r
 }\r
 \r
 template<class E, class T, class U>\r
-std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& out,    const safe_ptr<U>& p)\r
+std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& out, const safe_ptr<U>& p)\r
 {\r
-       return out << p.get();\r
+    return out << p.get();\r
 }\r
 \r
 template<class T> \r
-void swap(safe_ptr<T>& a, safe_ptr<T>& b)  // noexcept\r
+void swap(safe_ptr<T>& a, safe_ptr<T>& b)\r
 {\r
-       a.swap(b);\r
+    a.swap(b);\r
 }\r
 \r
 template<class T> \r
-T* get_pointer(safe_ptr<T> const& p)  // noexcept\r
+T* get_pointer(safe_ptr<T> const& p)\r
 {\r
-       return p.get();\r
+    return p.get();\r
 }\r
 \r
 template <class T, class U>\r
-safe_ptr<T> static_pointer_cast(const safe_ptr<U>& p)  // noexcept\r
+safe_ptr<T> static_pointer_cast(const safe_ptr<U>& p)\r
 {\r
-       return safe_ptr<T>(std::static_pointer_cast<T>(std::shared_ptr<U>(p)));\r
+    return safe_ptr<T>(std::static_pointer_cast<T>(std::shared_ptr<U>(p)));\r
 }\r
 \r
 template <class T, class U>\r
-safe_ptr<T> const_pointer_cast(const safe_ptr<U>& p)  // noexcept\r
+safe_ptr<T> const_pointer_cast(const safe_ptr<U>& p)\r
 {\r
-       return safe_ptr<T>(std::const_pointer_cast<T>(std::shared_ptr<U>(p)));\r
+    return safe_ptr<T>(std::const_pointer_cast<T>(std::shared_ptr<U>(p)));\r
 }\r
 \r
 template <class T, class U>\r
 safe_ptr<T> dynamic_pointer_cast(const safe_ptr<U>& p)\r
 {\r
-       auto temp = std::dynamic_pointer_cast<T>(std::shared_ptr<U>(p));\r
-       if(!temp)\r
-               throw std::bad_cast();\r
-       return safe_ptr<T>(temp);\r
+    auto temp = std::dynamic_pointer_cast<T>(std::shared_ptr<U>(p));\r
+    if(!temp)\r
+        throw std::bad_cast();\r
+    return safe_ptr<T>(std::move(temp));\r
 }\r
 \r
+//\r
+// enable_safe_this \r
+//\r
+// A safe_ptr version of enable_shared_from_this.\r
+// So that an object may get safe_ptr objects to itself.\r
+//\r
+\r
+template<class T>\r
+class enable_safe_from_this : public std::enable_shared_from_this<T>\r
+{\r
+public:\r
+    safe_ptr<T> safe_from_this() \r
+    {\r
+        return safe_ptr<T>(this->shared_from_this());\r
+    }\r
+\r
+    safe_ptr<T const> safe_from_this() const \r
+    {\r
+        return safe_ptr<T const>(this->shared_from_this());\r
+    }\r
+protected:\r
+    enable_safe_from_this()\r
+    {\r
+    }\r
+    \r
+    enable_safe_from_this(const enable_safe_from_this&)\r
+    {\r
+    }\r
+    \r
+    enable_safe_from_this& operator=(const enable_safe_from_this&)\r
+    {        \r
+        return *this;\r
+    }\r
+    \r
+    ~enable_safe_from_this ()\r
+    {\r
+    }\r
+};\r
+\r
+//\r
+// make_safe\r
+//\r
+// safe_ptr equivalents to make_shared\r
+//\r
+\r
 template<typename T>\r
-safe_ptr<T> make_safe(const std::shared_ptr<T>& ptr)\r
+safe_ptr<T> make_safe_ptr(const std::shared_ptr<T>& ptr)\r
 {\r
        return safe_ptr<T>(ptr);\r
 }\r
 \r
 template<typename T>\r
-safe_ptr<T> make_safe(std::shared_ptr<T>&& ptr)\r
+safe_ptr<T> make_safe_ptr(std::shared_ptr<T>&& ptr)\r
 {\r
-       return safe_ptr<T>(std::move(ptr));\r
+       return safe_ptr<T>(ptr);\r
 }\r
 \r
 template<typename T>\r
 safe_ptr<T> make_safe()\r
 {\r
-       return safe_ptr<T>();\r
+    return safe_ptr<T>(std::make_shared<T>());\r
 }\r
 \r
 template<typename T, typename P0>\r
 safe_ptr<T> make_safe(P0&& p0)\r
 {\r
-       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0)));\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0)));\r
 }\r
 \r
 template<typename T, typename P0, typename P1>\r
 safe_ptr<T> make_safe(P0&& p0, P1&& p1)\r
 {\r
-       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1)));\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1)));\r
 }\r
 \r
 template<typename T, typename P0, typename P1, typename P2>\r
 safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2)\r
 {\r
-       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));\r
 }\r
 \r
 template<typename T, typename P0, typename P1, typename P2, typename P3>\r
 safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3)\r
 {\r
-       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));\r
 }\r
 \r
 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4>\r
 safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)\r
 {\r
-       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));\r
 }\r
 \r
 template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>\r
 safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)\r
 {\r
-       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5)));\r
+    return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5)));\r
 }\r
 \r
-}
\ No newline at end of file
+template<typename T>\r
+safe_ptr<T>::safe_ptr() \r
+    : p_(make_safe<T>())\r
+{\r
+} \r
+\r
+} // namespace\r