-/*\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