*/\r
#pragma once\r
\r
+#include "../utility/assert.h"\r
+#include "../memory/safe_ptr.h"\r
+\r
#include <assert.h>\r
\r
#include <tbb/parallel_for.h>\r
\r
namespace caspar {\r
\r
-namespace internal {\r
+namespace detail {\r
\r
-static void* fast_memcpy(void* dest, const void* source, size_t count)\r
+static void* fast_memcpy_aligned_impl(void* dest, const void* source, size_t count)\r
{\r
- assert(dest != nullptr);\r
- assert(source != nullptr);\r
+ CASPAR_ASSERT(dest != nullptr);\r
+ CASPAR_ASSERT(source != nullptr);\r
+ CASPAR_ASSERT(reinterpret_cast<int>(dest) % 16 == 0);\r
+ CASPAR_ASSERT(reinterpret_cast<int>(source) % 16 == 0);\r
+\r
+ if(count == 0)\r
+ return dest;\r
\r
__asm \r
{ \r
return dest;\r
}\r
\r
+static void* fast_memcpy_unaligned_impl(void* dest, const void* source, size_t count)\r
+{\r
+ CASPAR_ASSERT(dest != nullptr);\r
+ CASPAR_ASSERT(source != nullptr);\r
+\r
+ if(count == 0)\r
+ return dest;\r
+\r
+ __asm \r
+ { \r
+ mov esi, source; \r
+ mov edi, dest; \r
+ mov ebx, count; \r
+ shr ebx, 7;\r
+\r
+ cpy: \r
+ movdqu xmm0, [esi+00h]; \r
+ movdqu xmm1, [esi+10h]; \r
+ movdqu xmm2, [esi+20h]; \r
+ movdqu xmm3, [esi+30h]; \r
+\r
+ movdqu [edi+00h], xmm0;\r
+ movdqu [edi+10h], xmm1;\r
+ movdqu [edi+20h], xmm2; \r
+ movdqu [edi+30h], xmm3;\r
+\r
+ movdqu xmm4, [esi+40h];\r
+ movdqu xmm5, [esi+50h];\r
+ movdqu xmm6, [esi+60h];\r
+ movdqu xmm7, [esi+70h]; \r
+\r
+ movdqu [edi+40h], xmm4; \r
+ movdqu [edi+50h], xmm5; \r
+ movdqu [edi+60h], xmm6; \r
+ movdqu [edi+70h], xmm7; \r
+\r
+ lea edi, [edi+80h]; \r
+ lea esi, [esi+80h]; \r
+\r
+ dec ebx; \r
+ jnz cpy; \r
+ } \r
+ return dest;\r
}\r
\r
-static void* fast_memcpy(void* dest, const void* source, size_t count)\r
+static void* fast_memcpy_small_aligned(char* dest8, const char* source8, size_t count)\r
{ \r
- if((reinterpret_cast<int>(source) & 15) || (reinterpret_cast<int>(dest) & 15))\r
- return memcpy(dest, source, count);\r
+ size_t rest = count & 127;\r
+ count &= ~127;\r
+\r
+ fast_memcpy_aligned_impl(dest8, source8, count); \r
+\r
+ return memcpy(dest8+count, source8+count, rest);\r
+}\r
\r
- if(count < 2048)\r
- return memcpy(dest, source, count);\r
+static void* fast_memcpy_small_unaligned(char* dest8, const char* source8, size_t count)\r
+{ \r
+ size_t rest = count & 127;\r
+ count &= ~127;\r
+\r
+ fast_memcpy_unaligned_impl(dest8, source8, count); \r
\r
- size_t rest = count % 128;\r
- count -= rest;\r
+ return memcpy(dest8+count, source8+count, rest);\r
+}\r
\r
- tbb::affinity_partitioner ap;\r
+static void* fast_memcpy_aligned(void* dest, const void* source, size_t count)\r
+{ \r
+ auto dest8 = reinterpret_cast<char*>(dest);\r
+ auto source8 = reinterpret_cast<const char*>(source);\r
+ \r
+ size_t rest = count & 2047;\r
+ count &= ~2047;\r
+ \r
tbb::parallel_for(tbb::blocked_range<size_t>(0, count/128), [&](const tbb::blocked_range<size_t>& r)\r
{ \r
- internal::fast_memcpy(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128); \r
- }, ap);\r
+ fast_memcpy_aligned_impl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128); \r
+ });\r
+ \r
+ return fast_memcpy_small_aligned(dest8+count, source8+count, rest);\r
+}\r
\r
- return memcpy(reinterpret_cast<char*>(dest)+count, reinterpret_cast<const char*>(source)+count, rest);\r
+static void* fast_memcpy_unaligned(void* dest, const void* source, size_t count)\r
+{ \r
+ auto dest8 = reinterpret_cast<char*>(dest);\r
+ auto source8 = reinterpret_cast<const char*>(source);\r
+ \r
+ size_t rest = count & 2047;\r
+ count &= ~2047;\r
+ \r
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, count/128), [&](const tbb::blocked_range<size_t>& r)\r
+ { \r
+ fast_memcpy_unaligned_impl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128); \r
+ });\r
+ \r
+ return fast_memcpy_small_unaligned(dest8+count, source8+count, rest);\r
}\r
\r
+}\r
\r
-}
\ No newline at end of file
+template<typename T>\r
+T* fast_memcpy(T* dest, const void* source, size_t count)\r
+{ \r
+ if((reinterpret_cast<int>(source) & 15) || (reinterpret_cast<int>(dest) & 15))\r
+ return reinterpret_cast<T*>(detail::fast_memcpy_unaligned(dest, source, count));\r
+ else\r
+ return reinterpret_cast<T*>(detail::fast_memcpy_aligned(dest, source, count));\r
+}\r
+\r
+}\r
-/*\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
#pragma once\r
\r
#include <common/exception/exceptions.h>\r
+#include <common/utility/string.h>\r
\r
#include <string>\r
\r
namespace caspar { namespace ffmpeg {\r
\r
struct ffmpeg_error : virtual caspar_exception{};\r
+struct averror_bsf_not_found : virtual ffmpeg_error{};\r
+struct averror_decoder_not_found : virtual ffmpeg_error{};\r
+struct averror_demuxer_not_found : virtual ffmpeg_error{};\r
+struct averror_encoder_not_found : virtual ffmpeg_error{};\r
+struct averror_eof : virtual ffmpeg_error{};\r
+struct averror_exit : virtual ffmpeg_error{};\r
+struct averror_filter_not_found : virtual ffmpeg_error{};\r
+struct averror_muxer_not_found : virtual ffmpeg_error{};\r
+struct averror_option_not_found : virtual ffmpeg_error{};\r
+struct averror_patchwelcome : virtual ffmpeg_error{};\r
+struct averror_protocol_not_found : virtual ffmpeg_error{};\r
+struct averror_stream_not_found : virtual ffmpeg_error{};\r
\r
static std::string av_error_str(int errn)\r
{\r
return std::string(buf);\r
}\r
\r
-#define THROW_ON_ERROR(ret, source, func) \\r
- if(ret < 0) \\r
- { \\r
- BOOST_THROW_EXCEPTION( \\r
- ffmpeg_error() << \\r
- msg_info(av_error_str(ret)) << \\r
- source_info(narrow(source)) << \\r
- boost::errinfo_api_function(func) << \\r
- boost::errinfo_errno(AVUNERROR(ret))); \\r
+static void throw_on_ffmpeg_error(int ret, const char* source, const char* func, const char* local_func, const char* file, int line)\r
+{\r
+ if(ret >= 0)\r
+ return;\r
+\r
+ switch(ret)\r
+ {\r
+ case AVERROR_BSF_NOT_FOUND:\r
+ ::boost::exception_detail::throw_exception_(averror_bsf_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line); \r
+ case AVERROR_DECODER_NOT_FOUND:\r
+ ::boost::exception_detail::throw_exception_(averror_decoder_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_DEMUXER_NOT_FOUND:\r
+ ::boost::exception_detail::throw_exception_(averror_demuxer_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_ENCODER_NOT_FOUND:\r
+ ::boost::exception_detail::throw_exception_(averror_encoder_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line); \r
+ case AVERROR_EOF: \r
+ ::boost::exception_detail::throw_exception_(averror_eof()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_EXIT: \r
+ ::boost::exception_detail::throw_exception_(averror_exit()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_FILTER_NOT_FOUND: \r
+ ::boost::exception_detail::throw_exception_(averror_filter_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_MUXER_NOT_FOUND: \r
+ ::boost::exception_detail::throw_exception_(averror_muxer_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_OPTION_NOT_FOUND: \r
+ ::boost::exception_detail::throw_exception_(averror_option_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_PATCHWELCOME: \r
+ ::boost::exception_detail::throw_exception_(averror_patchwelcome()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_PROTOCOL_NOT_FOUND: \r
+ ::boost::exception_detail::throw_exception_(averror_protocol_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ case AVERROR_STREAM_NOT_FOUND:\r
+ ::boost::exception_detail::throw_exception_(averror_stream_not_found()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
+ default:\r
+ ::boost::exception_detail::throw_exception_(ffmpeg_error()<< \r
+ msg_info(av_error_str(ret)) << \r
+ source_info(narrow(source)) << \r
+ boost::errinfo_api_function(func) << \r
+ boost::errinfo_errno(AVUNERROR(ret)), local_func, file, line);\r
}\r
+}\r
+\r
+static void throw_on_ffmpeg_error(int ret, const std::wstring& source, const char* func, const char* local_func, const char* file, int line)\r
+{\r
+ throw_on_ffmpeg_error(ret, narrow(source).c_str(), func, local_func, file, line);\r
+}\r
+\r
+\r
+//#define THROW_ON_ERROR(ret, source, func) throw_on_ffmpeg_error(ret, source, __FUNC__, __FILE__, __LINE__)\r
\r
#define THROW_ON_ERROR_STR_(call) #call\r
#define THROW_ON_ERROR_STR(call) THROW_ON_ERROR_STR_(call)\r
\r
+#define THROW_ON_ERROR(ret, func, source) \\r
+ throw_on_ffmpeg_error(ret, source, func, __FUNCTION__, __FILE__, __LINE__); \r
+\r
#define THROW_ON_ERROR2(call, source) \\r
[&]() -> int \\r
{ \\r
int ret = call; \\r
- if(ret < 0) \\r
- { \\r
- BOOST_THROW_EXCEPTION( \\r
- ffmpeg_error() << \\r
- msg_info(av_error_str(ret)) << \\r
- source_info(narrow(source)) << \\r
- boost::errinfo_api_function(THROW_ON_ERROR_STR(call)) << \\r
- boost::errinfo_errno(AVUNERROR(ret))); \\r
- } \\r
+ throw_on_ffmpeg_error(ret, source, THROW_ON_ERROR_STR(call), __FUNCTION__, __FILE__, __LINE__); \\r
return ret; \\r
- }();\r
+ }()\r
\r
}}
\ No newline at end of file