npapi-vlc | branch: master | Hugo Beauzée-Luyssen <[email protected]> | Wed Jan 27 16:18:44 2016 +0100| [0dc92cb3037ff374a02612e87a4dad382e57a8b8] | committer: Hugo Beauzée-Luyssen
npapi: Don't wrap callback arguments into Variant's out of the plugin thread This completes previous #16292 fix > https://code.videolan.org/videolan/npapi-vlc/commit/0dc92cb3037ff374a02612e87a4dad382e57a8b8 --- npapi/utils.hpp | 120 +++++++++++------------------------------------ npapi/vlcplugin_base.cpp | 18 ++++--- 2 files changed, 39 insertions(+), 99 deletions(-) diff --git a/npapi/utils.hpp b/npapi/utils.hpp index 2b6d20b..3ee47d6 100644 --- a/npapi/utils.hpp +++ b/npapi/utils.hpp @@ -24,13 +24,14 @@ #ifndef UTILS_NPP #define UTILS_NPP -#include <npruntime.h> +#include <array> +#include <cassert> +#include <cstring> #include <memory> -#include <type_traits> +#include <npruntime.h> #include <string> - -#include <cstring> -#include <cassert> +#include <tuple> +#include <type_traits> using CStr = std::unique_ptr<char, void(*)(void*)>; @@ -614,107 +615,40 @@ private: using Variant = details::Variant<details::policy::Embeded>; using OutVariant = details::Variant<details::policy::Wrapped>; -class VariantArray +namespace details { - using VPtr = std::unique_ptr<Variant[]>; -public: - VariantArray() - : m_variants( nullptr ) - , m_size( 0 ) - { - } - VariantArray(unsigned int nbValue) - : m_variants( VPtr( new Variant[nbValue] ) ) - , m_size( nbValue ) - { - } - - Variant& operator[](size_t idx) - { - return m_variants[idx]; - } - - const Variant& operator[](size_t idx) const - { - return m_variants[idx]; - } - - // Warning: this assumes the same binary layout between Variant & NPVariant - operator NPVariant*() - { - return (NPVariant*)m_variants.get(); - } - - operator const NPVariant*() const - { - return (const NPVariant*)m_variants.get(); - } - - size_t size() const + template <size_t... Ns> + struct Seq { - return m_size; - } - - VariantArray(const VariantArray&) = delete; - VariantArray& operator=(const VariantArray&) = delete; -#ifndef _MSC_VER - VariantArray(VariantArray&&) = default; - VariantArray& operator=(VariantArray&&) = default; -#else - VariantArray(VariantArray&& v) - : m_variants(std::move( v.m_variants ) ) - , m_size( v.m_size ) - { - } + using type = Seq<Ns..., sizeof...(Ns)>; + }; - VariantArray& operator=(VariantArray&& v) + template <size_t N> + struct GenSeq { - if (&v == this) - return *this; - m_variants = std::move(v.m_variants); - m_size = v.m_size; - return *this; - } - -#endif -private: - VPtr m_variants; - size_t m_size; -}; + // This will recurse down to Seq<> which yields type = Seq<0> + // Then, from Seq<0>::type, up to Seq<N-1>::type, which ends + // up generating Seq<0, 1, ... N> + using type = typename GenSeq<N - 1>::type::type; + }; -// Private implementation namespace -namespace details -{ - template <size_t Idx, typename T> - void wrap( VariantArray& array, T arg ) + template <> + struct GenSeq<0> { - array[Idx] = Variant<details::policy::Embeded>(arg); - } + using type = Seq<>; + }; - template <size_t Idx, typename T, typename... Args> - void wrap( VariantArray& array, T arg, Args&&... args ) + template <typename Tuple, size_t... Indices> + std::array<npapi::Variant, sizeof...(Indices)> wrap( const Tuple& t, Seq<Indices...> ) { - wrap<Idx + 1>( array, std::forward<Args>( args )... ); - // This needs the Variant wrapper to be the exact size of a NPVariant - // For future proofness, we make this explicit: - array[Idx] = Variant<details::policy::Embeded>(arg); + return { npapi::Variant( std::get<Indices>( t ) )... }; } } -// public entry point. Responsible for allocating the array and initializing -// the template index parameter (to avoid filling to array in reverse order with -// sizeof...() template <typename... Args> -VariantArray wrap(Args&&... args) -{ - auto array = VariantArray{sizeof...(args)}; - details::wrap<0>( array, std::forward<Args>( args )... ); - return array; -} - -inline VariantArray wrap() +std::array<Variant, sizeof...(Args)> wrap( const std::tuple<Args...>& args ) { - return VariantArray{}; + return details::wrap( args, typename details::GenSeq<sizeof...(Args)>::type{} ); } } diff --git a/npapi/vlcplugin_base.cpp b/npapi/vlcplugin_base.cpp index 5160826..a78e640 100644 --- a/npapi/vlcplugin_base.cpp +++ b/npapi/vlcplugin_base.cpp @@ -277,28 +277,34 @@ bool VlcPluginBase::handle_event(void *) return false; } +template <typename... Args> struct AsyncEventWrapper { - AsyncEventWrapper(NPP b, NPObject* l, npapi::VariantArray&& a) + template <typename... PFArgs> + AsyncEventWrapper(NPP b, NPObject* l, PFArgs&&... args) : browser( b ) , listener( l ) - , args( std::move( a ) ) + , args( std::make_tuple( std::forward<Args>( args )... ) ) { } NPP browser; NPObject* listener; - npapi::VariantArray args; + // If we do not decay Args here, we will end up declaring a tuple holding references + // The tuple returned by make_tuple does that, but we end up converting from the correct tuple + // type to an invalid tuple type, since we would end up using dangling references. + std::tuple<typename std::decay<Args>::type...> args; }; template <typename... Args> static void invokeEvent( NPP browser, NPObject* listener, Args&&... args ) { - auto wrapper = new AsyncEventWrapper( browser, listener, npapi::wrap( std::forward<Args>( args )... ) ); + auto wrapper = new AsyncEventWrapper<Args...>( browser, listener, std::forward<Args>( args )... ); NPN_PluginThreadAsyncCall( browser, [](void* data) { - auto w = reinterpret_cast<AsyncEventWrapper*>( data ); + auto w = reinterpret_cast<AsyncEventWrapper<Args...>*>( data ); + auto args = npapi::wrap( w->args ); NPVariant result; - if (NPN_InvokeDefault( w->browser, w->listener, w->args, w->args.size(), &result )) + if (NPN_InvokeDefault( w->browser, w->listener, reinterpret_cast<NPVariant*>( args.data() ), args.size(), &result )) { // "result" content is unspecified when invoke fails. Don't clean potential garbage NPN_ReleaseVariantValue( &result ); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
